Cách tốt nhất để kết nối bối cảnh (mô hình) cơ sở dữ liệu Entity Framework với ViewModel trong MVVM WPF là gì?


9

Như trong câu hỏi trên: Cách tốt nhất để kết nối mô hình cơ sở dữ liệu Entity Framework (bối cảnh) để xemModel trong MVVM (WPF) là gì?

Tôi đang học mẫu MVVM trong WPF, rất nhiều ví dụ cho thấy cách triển khai mô hình để viewModel, nhưng các mô hình trong các ví dụ đó chỉ là các lớp đơn giản, tôi muốn sử dụng MVVM cùng với mô hình khung thực thể (cách tiếp cận cơ sở đầu tiên). Cách tốt nhất để mô hình dây để xemModel.

Cảm ơn câu trả lời.

//ctor of ViewModel 
public ViewModel()
{ 
db = new PackageShipmentDBEntities(); // Entity Framework generated class

ListaZBazy = new ObservableCollection<Pack>(db.Packs.Where(w => w.IsSent == false)); 
}

Đây là trình quản lý thông thường của ViewModel, tôi nghĩ có một cách tốt hơn, tôi đã đọc về mẫu kho lưu trữ, không chắc tôi có thể điều chỉnh điều này với MVVM của WPF không

Câu trả lời:


4

Tôi đã xem xét điều này khá nhiều và chưa tìm thấy giải pháp "hoàn hảo". Mẫu kho lưu trữ hoạt động tuyệt vời cho các ứng dụng MVC trong đó bối cảnh tồn tại trong một thời gian ngắn vì nó tồn tại trong một bộ điều khiển tồn tại ngắn, nhưng vấn đề xảy ra khi bạn cố gắng áp dụng cấu trúc tương tự cho ứng dụng wpf trong đó VM có thể tồn tại trong thời gian dài.

Tôi đã sử dụng giải pháp này trong quá khứ đơn giản hơn nhiều mẫu repo mà tôi đã thấy rằng cố gắng trừu tượng hóa mọi thứ đến mức cực đoan, dẫn đến số lượng mã khó đọc gần như khó đọc. Dưới đây là các bước ...

  1. Tạo một dự án riêng để EDMX hoạt động như lớp truy cập Dữ liệu của bạn
  2. Tạo thư mục "Kho lưu trữ" trong cùng một dự án
  3. Tạo một lớp cơ sở "BaseRep repository" để hoạt động như "Đơn vị công việc". IDisposablesẽ cho phép bạn sử dụng điều này trong một using(){}partialsẽ cho phép bạn thực hiện các kho khác

    public partial class MyEntityRepository : IDisposable
    {
        MyEntities context = new MyEntities();
    
        public void Dispose()
        {
            context.Dispose();
        }
    }
  4. Tạo một tệp khác gọi là "MyOtherRep repository". tạo cùng một lớp một phần nhưng thực hiện các phương thức dựa trên những gì bạn muốn tệp đó chứa

    public partial class MyEntityRepository
    {
        public void MyOtherMethodSave(EntityObject obj)
        {
            //work with context
            ...
    
            context.SaveChanges();
        }
    }

Bây giờ trong VM của bạn, bạn có thể làm điều này ...

using(MyEntityRepository repo = new MyEntityRepository())
{
     repo.MyOtherMethodSave(objectToSave);
}

Nhóm này tất cả các kho lưu trữ của bạn dưới một lớp để bạn không phải đối phó với bối cảnh riêng biệt. Nó cho phép bạn quản lý tốt hơn các repos khác nhau bằng cách nhóm các phương thức vào các tệp khác nhau và giúp ngăn ngừa sao chép mã. Trên hết, bối cảnh của bạn chỉ tồn tại trong thời gian ngắn mà không sử dụng mô hình này.

Nhược điểm là với các hệ thống lớn hơn, bạn có thể có rất nhiều phương thức được gói trong repo của bạn. Một giải pháp trong trường hợp đó là triển khai một số lệnh phổ biến cơ bản như "Tìm" hoặc "Thêm" và triển khai các lệnh chuyên biệt trong kho lưu trữ tương ứng của chúng.


2
Bạn có thể thay thế bối cảnh riêng của 'MyEntityRep repository' và bạn sẽ nhận được kết quả tương tự. Trừ khi bạn muốn bọc bối cảnh của EF bằng "kho lưu trữ" của riêng bạn, tăng sự trùng lặp.
Euphoric

@Euphoric Vâng, bạn có thể, nhưng sau đó bạn không đảm bảo rằng kho lưu trữ được sử dụng trong bối cảnh. Toàn bộ vấn đề là trừu tượng hóa cách thức hoạt động của EF thành các yêu cầu kinh doanh đơn giản
Giày

4

Đối lập với kho lưu trữ, mà tôi không thích. Tôi sẽ khuyên bạn nên sử dụng mẫu Command, theo khuyến nghị của Ayende .

Nói một cách đơn giản, với mỗi thao tác, bạn tạo một ThisOperationCommandlớp riêng . Trong lớp này, bạn sẽ làm việc với bối cảnh EF bình thường. Bạn thậm chí có thể sử dụng một số lớp cơ sở EFCommandmà một số hệ thống ống nước cho bạn.

Từ phía ViewModel, bạn tạo phiên bản của lệnh này, điền vào nó bằng các tham số (thậm chí bạn có thể chuyển toàn bộ cá thể ViewModel nếu bạn không nhớ kết hợp chặt chẽ giữa lệnh và ViewModel) và sau đó chuyển nó sang một loại Executephương thức nào đó, nó sẽ bắt đầu lên lệnh, thực thi nó, xé nó và sau đó trả lại bất cứ thứ gì lệnh nhận được. Bạn cũng có thể yêu cầu nó trả về nhiều giá trị nếu bạn nhận được nó từ thể hiện của lệnh sau khi thực thi.

Ưu điểm là bạn không cần sao chép toàn bộ lớp truy cập dữ liệu dưới dạng reposotory và bạn có thể sử dụng lại và soạn thảo các lệnh miễn là bạn tạo một số cơ sở hạ tầng đơn giản để hỗ trợ nó. Ví dụ thực hiện các lệnh từ các lệnh khác.


0

Đối với các kịch bản đơn giản, tôi đã sử dụng như sau:

public class ViewModel : IDisposable {

    private EntitiesContext _context = new EntitiesContext();

    private SomeEntity _model;
    public SomeEntity Model {
       get { return _model; }
    }

    public View(int id) {
        _model = _context.SomeEntity.Find(id);
    }

    private ICommand _saveCommand = new RelayCommand(() => _context.SaveChanges());
    public ICommand SaveCommand {
        get { return _saveCommand; }
    }        

    public void Dispose() {
         _context.Dispose();
    }

}

1
Vấn đề với điều này là bối cảnh của bạn hiện có khả năng "sống lâu".
Giày

1
Bạn không nên tạo ra thể hiện của bối cảnh bên trong lớp, nhưng thay vào đó, đưa nó vào hàm tạo.
Oscar Mederos
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.