Một ứng dụng ASP.NET MVC có nên trực tiếp sử dụng Entity Framework làm mô hình không?


22

Tôi đang xây dựng ứng dụng MVC đầu tiên của mình trong Visual Studio 2013 (MVC 5) và tôi không rõ ràng về cách tốt nhất để thiết lập mô hình của mình.

Tôi đã tạo một mô hình khung thực thể bằng cách sử dụng mã đầu tiên từ cơ sở dữ liệu hiện có. Bản năng đầu tiên của tôi là tạo ra một số lớp trung gian sẽ là mô hình được sử dụng bởi các khung nhìn và để các lớp đó hoạt động với các lớp khung thực thể.

Khi tôi đang viết các lớp trung gian, tôi nhận ra rằng tôi hầu như chỉ thực hiện lại rất nhiều điều mà các lớp EF đã làm chỉ với trình thiết lập riêng tư thỉnh thoảng hoặc chuyển từ kiểu dữ liệu này sang kiểu dữ liệu khác. Vì vậy, đó dường như là một sự lãng phí.

Là quy tắc chung để sử dụng trực tiếp các lớp khung thực thể làm Mô hình cho ứng dụng MVC? Hoặc có một số lợi ích tôi đang thiếu để xây dựng các lớp trung gian này?



Nếu bạn đang sử dụng mã đầu tiên, thì không có cơ sở dữ liệu hiện có, phải không?
Isaac Kleinman

1
Với EF 6.1+, bạn có thể tạo mô hình mã đầu tiên từ cơ sở dữ liệu hiện có. Xem bài viết MSDN này: msdn.microsoft.com/en-au/data/jj200620.aspx
Mike D.

Câu trả lời:


23

Trong các ứng dụng của mình, tôi luôn tách biệt mọi thứ, với các mô hình khác nhau cho cơ sở dữ liệu (Entity Framework) và MVC. Tôi cũng đã tách chúng ra thành các dự án khác nhau:

  • Ví dụ.Entities - chứa các thực thể của tôi cho EF và bối cảnh DB để truy cập chúng.
  • Ví dụ.Models - chứa các mô hình MVC.
  • Ví dụ.Web - ứng dụng web. Phụ thuộc vào cả example.Domain và example.Models.

Thay vì giữ các tham chiếu đến các đối tượng khác như các thực thể miền, các mô hình MVC giữ ID làm số nguyên.

Khi một yêu cầu GET cho một trang đến, bộ điều khiển MVC thực hiện truy vấn cơ sở dữ liệu, trả về một thực thể. Tôi đã viết các phương thức "Converter" lấy một thực thể miền và chuyển đổi nó thành một mô hình MVC. Có các phương thức khác làm ngược lại (từ mô hình MVC sang thực thể miền). Mô hình sau đó được chuyển đến khung nhìn và do đó cho máy khách.

Khi có yêu cầu POST, bộ điều khiển MVC nhận được mô hình MVC. Một phương thức chuyển đổi chuyển đổi nó thành một thực thể miền. Phương thức này cũng thực hiện bất kỳ xác nhận hợp lệ nào không thể được biểu thị dưới dạng các thuộc tính và đảm bảo rằng nếu thực thể miền đã tồn tại thì chúng tôi đang cập nhật nó chứ không phải lấy một thuộc tính mới. Các phương thức thường trông giống như thế này:

public class PersonConverter
{
    public MyDatabaseContext _db;

    public PersonEntity Convert(PersonModel source)
    {
         PersonEntity destination = _db.People.Find(source.ID);

         if(destination == null)
             destination = new PersonEntity();

         destination.Name = source.Name;
         destination.Organisation = _db.Organisations.Find(source.OrganisationID);
         //etc

         return destination;
    }

    public PersonModel Convert(PersonEntity source)
    {
         PersonModel destination = new PersonModel()
         {
             Name = source.Name,
             OrganisationID = source.Organisation.ID,
             //etc
         };

         return destination;
    }
}

Bằng cách sử dụng các phương thức này, tôi loại bỏ sự trùng lặp sẽ xảy ra trong mỗi bộ điều khiển. Việc sử dụng thuốc generic có thể lặp lại nhiều thứ hơn nữa.

Làm những việc theo cách này cung cấp nhiều lợi ích:

  • Bạn có thể tùy chỉnh một mô hình cho một chế độ xem hoặc hành động cụ thể. Giả sử bạn có mẫu đăng ký cho một người mà khi gửi, sẽ tạo ra nhiều thực thể khác nhau (người, tổ chức, địa chỉ). Nếu không có các mô hình MVC riêng biệt thì điều này sẽ rất khó khăn.
  • Nếu tôi cần chuyển nhiều thông tin hơn cho chế độ xem hơn là chỉ có sẵn trong thực thể hoặc kết hợp hai thực thể thành một mô hình duy nhất, thì các mô hình cơ sở dữ liệu quý giá của tôi sẽ không bao giờ được chạm vào.
  • Nếu bạn từng tuần tự hóa một mô hình MVC dưới dạng JSON hoặc XML, bạn chỉ nhận được mô hình ngay lập tức được tuần tự hóa, không phải mọi thực thể khác được liên kết với mô hình này.

Câu trả lời tốt, sẽ khuyên bạn nên sử dụng ValueInjection hoặc một cái gì đó tương tự (cá nhân tôi ghét automapper) thay vì ánh xạ thủ công các thuộc tính từ lớp này sang lớp khác.
Rocklan

1
Thay vì thêm một câu trả lời riêng biệt, tôi sẽ chỉ nhận xét ở đây rằng trong thực tiễn DDD, "bộ chuyển đổi" và các mô hình riêng biệt cho chế độ xem sẽ được coi là một phần của Lớp dịch vụ ứng dụng. Về cơ bản, nó cho phép Mô hình miền của bạn phức tạp đến mức cần thiết trong khi che giấu sự phức tạp đó khỏi ứng dụng. Nó cũng bảo vệ ứng dụng khỏi phải thay đổi do thay đổi mô hình miền. ASL xử lý bản dịch.
Michael Brown

Vì vậy, bạn thực hiện cuộc gọi cho từng mô hình bạn có trong PersonModel (tức là đối tượng Tổ chức) để lấy thông tin của mô hình đó? Giả sử bạn có một biểu mẫu để cập nhật thông tin về người và tổ chức, bạn có gọi thêm khi bạn cập nhật Tổ chức không? Tôi đang sử dụng các procs được lưu trữ vì vậy tôi không thể gửi tất cả các thuộc tính của mô hình và bất kỳ thuộc tính chứa mô hình nào cùng một lúc?
Sáng

1
Làm thế nào bạn sẽ xử lý ánh xạ trở lại một bộ sưu tập? Điều đó dường như đã phức tạp hơn nhiều trong EF6 khi bạn không còn có thể tạo một danh sách các thực thể mới với các bản cập nhật vì điều này chỉ tạo lại mọi thứ ...
Gerard Wilkinson

2
Thay vì viết các lớp trình chuyển đổi của riêng bạn, tôi khuyên bạn nên sử dụng thư viện Automapper đã được viết để giải quyết vấn đề này. Nó đã trưởng thành hơn rất nhiều kể từ năm 2014!
BenSmith

6

Tôi muốn nói rằng nó thực sự phụ thuộc vào ứng dụng của bạn. Có phải nó chỉ làm CRUD thuần túy, không có logic kinh doanh? Sau đó, tôi sẽ sử dụng các mô hình EF trực tiếp trong quan điểm của tôi.

Hầu hết thời gian có ít nhất một số logic kinh doanh liên quan và sau đó một lớp giữa các mô hình dữ liệu / EF và chế độ xem có thể là một ý tưởng tốt. Trong trường hợp này, có thể thích hợp để thực hiện "CQRS-lite" (xem bên dưới) và sử dụng các mô hình khác nhau trong và ngoài bộ điều khiển của bạn. Hầu hết thời gian các mô hình đọc rất nhiều "béo" hơn các mô hình viết ...

Tuy nhiên, nếu ứng dụng chứa nhiều logic nghiệp vụ và / hoặc cần mở rộng quy mô, tôi sẽ triển khai ít nhất cốt lõi của nó bằng CQRS (Phân đoạn trách nhiệm truy vấn lệnh), DDD (Thiết kế hướng tên miền) và có thể là Tìm nguồn sự kiện. Sau đó, EF có thể được sử dụng làm mặt tiền mô hình đọc.

Ngoài ra, hãy nhớ rằng bạn không cần phải tuân theo một chiến lược / mẫu cho toàn bộ ứng dụng, một số khu vực có thể là CRUD thuần túy và các khu vực khác có thể chứa nhiều logic kinh doanh ...

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.