Tiêm phụ thuộc với giải pháp Khung thực thể n-tier


12

Tôi hiện đang thiết kế một giải pháp n tầng đang sử dụng Entity Framework 5 (.net 4) làm chiến lược truy cập dữ liệu của nó, nhưng tôi lo ngại về cách kết hợp tiêm phụ thuộc để làm cho nó có thể kiểm tra / linh hoạt.

Bố cục giải pháp hiện tại của tôi như sau (giải pháp của tôi được gọi là lớp Methraz):

Orbitraz.WebUI : Một dự án biểu mẫu web asp.net, giao diện người dùng ở phía trước, tham khảo các dự án lớp Methraz.Business và lớp Methraz.Data.Models .

Orbitraz.Business : Một dự án thư viện lớp, chứa logic kinh doanh, tham khảo các dự án lớp Methraz.Data.Access , lớp Methraz.Data.Models

Alcatraz.Data.Access : Một dự án thư viện lớp, nhà AlcatrazModel.edmxAlcatrazEntitiesDbContext, tài liệu tham khảo dự án Alcatraz.Data.Models .

Orbitraz.Data.Models : Một dự án thư viện lớp, chứa POCO cho mô hình lớp Methraz, không có tài liệu tham khảo.

Tầm nhìn của tôi về cách giải pháp này hoạt động là web-ui sẽ khởi tạo một kho lưu trữ trong thư viện doanh nghiệp, kho lưu trữ này sẽ có một phụ thuộc (thông qua hàm tạo) của chuỗi kết nối (không phải là một AlcatrazEntitiesthể hiện). Web-ui sẽ biết các chuỗi kết nối cơ sở dữ liệu, nhưng không phải đó là chuỗi kết nối khung thực thể.

Trong dự án kinh doanh:

public class InmateRepository : IInmateRepository
{
    private string _connectionString;

    public InmateRepository(string connectionString)
    {
        if (connectionString == null)
        {
            throw new ArgumentNullException("connectionString");
        }

        EntityConnectionStringBuilder connectionBuilder = new EntityConnectionStringBuilder();

        connectionBuilder.Metadata = "res://*/AlcatrazModel.csdl|res://*/AlcatrazModel.ssdl|res://*/AlcatrazModel.msl";
        connectionBuilder.Provider = "System.Data.SqlClient";
        connectionBuilder.ProviderConnectionString = connectionString;

        _connectionString = connectionBuilder.ToString();
    }

    public IQueryable<Inmate> GetAllInmates()
    {
        AlcatrazEntities ents = new AlcatrazEntities(_connectionString);

        return ents.Inmates;
    }
}

Trong giao diện người dùng web:

IInmateRepository inmateRepo = new InmateRepository(@"data source=MATTHEW-PC\SQLEXPRESS;initial catalog=Alcatraz;integrated security=True;");

List<Inmate> deathRowInmates = inmateRepo.GetAllInmates().Where(i => i.OnDeathRow).ToList();

Tôi có một vài câu hỏi liên quan về thiết kế này.

  1. Thiết kế này thậm chí còn có ý nghĩa về khả năng của Entity Frameworks? Tôi nghe nói khung Entity đã sử dụng mẫu Đơn vị công việc, tôi chỉ cần thêm một lớp trừu tượng không cần thiết phải không?

  2. Tôi không muốn web-ui của mình giao tiếp trực tiếp với Entity Framework (hoặc thậm chí tham chiếu nó cho vấn đề đó), tôi muốn tất cả quyền truy cập cơ sở dữ liệu sẽ đi qua lớp doanh nghiệp vì trong tương lai tôi sẽ có nhiều dự án sử dụng cùng một lớp doanh nghiệp (dịch vụ web, ứng dụng windows, v.v.) và tôi muốn dễ dàng duy trì / cập nhật bằng cách có logic kinh doanh ở một khu vực trung tâm. Đây có phải là một cách thích hợp để đạt được điều này?

  3. Lớp Business thậm chí có nên chứa các kho lưu trữ hay nên được chứa trong lớp Access? Nếu nơi họ ổn, việc truyền chuỗi kết nối có phụ thuộc tốt không?

Cảm ơn đã dành thời gian để đọc!

Câu trả lời:


11

Cách bạn đang làm DI là sai.

Đầu tiên, chuỗi kết nối thuộc về lớp dữ liệu. Hoặc trong tệp web.config.

Sự trừu tượng tiếp theo bạn sẽ xử lý là DbContext, không phải chuỗi kết nối. Kho lưu trữ của bạn không nên biết về chuỗi kết nối. Logic kinh doanh của bạn sẽ không biết về DbContext, v.v.

Giao diện người dùng của bạn sẽ không có ý tưởng và sẽ không khởi tạo bất cứ điều gì liên quan đến EF.

Câu trả lời cụ thể cho quan điểm của bạn:

  1. Không thêm trừu tượng, cho đến khi bạn rất quen thuộc với EF. Nó đã thêm các tóm tắt tốt như UoW, truy vấn, sử dụng POCO, v.v.

  2. Để DI hoạt động, bạn có một Root Root tham chiếu tất cả các thành phần cần thiết. Điều này có thể hoặc có thể không có trong dự án WebUI. Nếu không, bạn nên hy vọng rằng nó không tham chiếu đến EF hoặc bất kỳ công nghệ liên quan đến dữ liệu nào khác.

  3. Dừng lại ngay tại đây. Dừng thêm trừu tượng trên trừu tượng. Bắt đầu với kiến ​​trúc trực tiếp và 'ngây thơ' và phát triển nó theo thời gian.

Trừu tượng là một công cụ để đối phó với sự phức tạp. Sự vắng mặt của sự phức tạp có nghĩa là không có sự trừu tượng cần thiết (chưa).


Để rõ ràng rằng tôi hiểu những gì bạn đang nói: Kho lưu trữ (giao diện tồn tại trong kinh doanh và cụ thể tồn tại trong lớp Methraz.Data.Access?) Chấp nhận DbContextnhư là một phụ thuộc của nó. Các lớp kinh doanh có kho lưu trữ như một phụ thuộc. Đối với việc tiêm phụ thuộc, tôi đang thực hiện thủ công (vì vậy tôi hiểu những gì đang diễn ra). Lý do tôi muốn có thể thiết lập chuỗi kết nối DbContextlà vì tôi sử dụng shending cơ sở dữ liệu nên trong một số trường hợp nhất định tôi cần phải có khung thực thể để kết nối với các cơ sở dữ liệu khác nhau (có cùng cấu trúc). Tôi có hiểu bạn đúng không?
Matthew

Từ mã bạn cung cấp, có vẻ như bạn hoàn toàn không làm DI. Mục tiêu chính của DI là giải phóng bạn và mã của bạn khỏi việc quản lý các phụ thuộc. Tôi không thể tưởng tượng bạn làm nó một cách hiệu quả bằng tay mà không có thùng chứa DI.
Boris Yankov

cũng giữ cho tâm trí của bạn mở với DI. Tôi đã, để giải trí, đã hỏi chính xác câu hỏi tương tự ở đây sau đó trên các diễn đàn khác để có câu trả lời ngược lại. DI là một mô hình, không phải là một kiến ​​trúc. Tùy thuộc vào mục tiêu của bạn, bạn có thể quyết định sử dụng nó hay không. Tôi sử dụng nó nhưng không phải vì lý do hầu hết mọi người bảo tôi sử dụng nó.
Bastien Vandamme

4

Một vài bình luận nhanh. Cá nhân tôi có thể sẽ không vượt qua một chuỗi kết nối. Nếu bất cứ điều gì tôi sẽ thử và tạo giao diện có thể cho các kho lưu trữ và chỉ cần vượt qua các giao diện xung quanh? Có các kho lưu trữ thực hiện hoặc hiển thị giao diện IOW.

Bằng cách này, nó không phải là một cơ sở dữ liệu thực hiện các kho lưu trữ của bạn. chúng có thể là bộ nhớ cache trong bộ nhớ hoặc bất cứ thứ gì. Có lẽ sau đó bạn có thể sử dụng một số loại khung tiêm phụ thuộc để khởi tạo những cái này ngay cả?

Vì vậy, trong câu trả lời cho một số câu hỏi của bạn:

  1. Vâng, tôi nghĩ nó ổn
  2. Tôi vẫn sẽ có giao diện người dùng tham chiếu dự án EF và các giao diện tham chiếu lớp buisness mà lớp kho lưu trữ EF thực hiện. Bằng cách đó, các dự án khác vẫn có thể sử dụng các hội đồng tương tự nhưng họ có linh hoạt để trao đổi nếu muốn?
  3. hmmm, Có lẽ các kho lưu trữ trong lớp truy cập nhưng thực hiện một định nghĩa giao diện được phơi bày trong lớp nghiệp vụ ??

Đây chỉ là một số suy nghĩ để nghiền ngẫm.


Về điểm 2, một mục tiêu tôi đã cố gắng thực hiện là không có CRUD trực tiếp trong lớp ui. Ý tôi là tôi muốn đảm bảo chỉ CRUD có thể xảy ra bằng cách đi qua lớp kinh doanh, theo cách đó nó được quản lý.
Matthew
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.