2010-11-09 44 views
5

tôi muốn triển khai kiến ​​trúc ba lớp điển hình. Cách tiếp cận hiện tại của tôi trông giống như sauCâu hỏi thiết kế đối tượng POCO/truy cập DAL

  • DAL - với EF 4.0 và kho lưu trữ cho từng thực thể của tôi. truy cập thông qua giao diện
  • Tôi đã nghĩ đến việc sử dụng các đối tượng POCO. Câu hỏi đầu tiên của tôi sẽ là nơi tôi nên đặt những tập tin ? Trong một hội đồng được tham chiếu bởi tất cả các dự án khác?
  • BLL - Làm cách nào để lấy dữ liệu từ DAL đến BLL và cuối cùng là GUI Đây có phải là cách tốt nếu tôi có toàn bộ các lớp người quản lý ở đó như CustomerManager trong BLL. Các lớp này sẽ truy cập vào kho lưu trữ tương ứng trong BLL và sau đó chuyển các đối tượng vào GUI

Hoặc bạn có nghĩ tốt hơn là đặt kho lưu trữ trong BLL và truy cập chúng trực tiếp từ nút nói của tôi?

Hy vọng bạn có thể mang một số ánh sáng vào bóng tối

+0

Nếu một trong các câu trả lời của chúng tôi giúp, vui lòng đánh dấu nó là được chấp nhận – Basic

Trả lời

6

Chúng tôi có bản repo trong DAL. BLL tham khảo các kho lưu trữ thông qua một giao diện - vì vậy các kho được gắn với DAL nhưng tách khỏi BLL. Tôi không biết lý do nào tại sao các kho lưu trữ không thể trực tiếp trong BLL. Chúng tôi đã có chúng trong DAL như chúng tôi không đặt bất kỳ logic trong họ. Sau đó chúng tôi có "Người quản lý" trong BLL bao bọc các kho lưu trữ và xử lý logic cụ thể theo thực thể.

FWIW chúng tôi thực sự có chung Repository(Of IEntity) và sử dụng sự thống nhất để khởi tạo kho lưu trữ thích hợp theo yêu cầu - nó rất nhỏ gọn và khá thanh lịch. Tất cả các thực thể POCO của chúng tôi thực hiện IEntity có chứa Id, CreatedDate, v.v. phổ biến cho TẤT CẢ các thực thể của chúng tôi. Điều này cho phép một số lợi ích khác khi bạn cần để xử lý bất kỳ loại thực thể tổng quát - CreatedDate được thiết lập bởi kho khi CreateInstance() được gọi, ModifiedDate được thiết lập bởi bối cảnh riêng của mình khi nó cam kết một thực thể với tình trạng Modified

Chúng tôi tiếp tục các thực thể trong một dự án riêng biệt - DAL cần có khả năng tham khảo chúng, cũng như BLL. Bạn không muốn chúng trong DAL khi trao đổi DAL ra sẽ gây ra vấn đề. Bạn không thể đặt chúng trong BLL hoặc bạn nhận được một tham chiếu vòng tròn. Cấu hình cho các thực thể có thể sống trong DAL vì nó là nguồn dữ liệu cụ thể.

Chúng tôi cố gắng gắn bó với BLL trong các nguyên thủy và trả lại các thực thể. Hãy cẩn thận về việc giữ các thực thể trong giao diện người dùng quá lâu, đặc biệt trong ứng dụng web vì bạn có thể có ngữ cảnh khác theo DAL khi bạn trả về thực thể cho BLL để xử lý (nghĩa là qua các yêu cầu được lưu trữ trong phiên hoặc tương tự) có thể dẫn đến tất cả các loại thú vị gắn/tách thực thể từ ngữ cảnh và mất cho bạn một số lợi ích như theo dõi thay đổi.

Hy vọng rằng sẽ giúp nhưng nếu bạn muốn làm rõ, hãy để tôi biết

+0

Cảm ơn câu trả lời của bạn. Lớp người quản lý của bạn có tĩnh không? – Developer23

+0

Trên thực tế không, chúng ta lại sử dụng phép tính thống nhất/phụ thuộc để trả về một tham chiếu đến một cá thể duy nhất. Điều này là do các nhà quản lý phụ thuộc vào repos mà lần lượt phụ thuộc vào bối cảnh mà không phải là tĩnh. Bạn có thể làm việc xung quanh điều này nhưng chúng tôi đã không. – Basic

+0

Một câu hỏi tầm thường nữa. Đề xuất của bạn về đặt tên là gì. Bạn có sử dụng một cái gì đó như CustomerManager hoặc như RPM1984 đã viết CustomerService? – Developer23

1

Bạn có thể giữ điều này thực sự đơn giản bằng cách giữ kho và POCOs của bạn trong cùng một dự án. Điều này về cơ bản sẽ là Mô hình miền dữ liệu của bạn. POCO của bạn là công khai và các giao diện kho lưu trữ của bạn cũng vậy. Bạn nên giữ kho lưu trữ cụ thể của bạn bên trong dự án này.

BLL của bạn có thể là Mặt tiền kinh điển hoặc Dịch vụ định vị. Dự án này sẽ xoa bóp dữ liệu của bạn và áp dụng bất kỳ quy tắc kinh doanh có liên quan nào trước khi giao cho UI. Điều này cũng sẽ chịu trách nhiệm xác thực dữ liệu đến từ giao diện người dùng trước khi gửi nó đến DAL.

+0

Cách tiếp cận thú vị. Cấu hình thực thể của bạn ở đâu? tức là các kiểu dữ liệu SQL cho các thuộc tính, các chỉ mục? – Basic

+0

Tôi không chắc chắn nếu tôi hiểu câu hỏi của bạn một cách chính xác. Tất cả quyền truy cập vào SQL sẽ bị Mô hình Dữ liệu (.edmx) trừu tượng hóa. – Praveen

+0

Ah okay - Chúng tôi sử dụng mã EF4 đầu tiên để thực thể của chúng tôi là các lớp chúng tôi tạo bằng tay và chúng tôi tạo thủ công các cấu hình của chúng tôi (khóa, FK, v.v.) có nghĩa là chúng tôi có thể giữ những thứ cụ thể như kiểu dữ liệu liên quan đến DAL nhưng có các thực thể POCO chung chung. – Basic

3

Đây là thiết lập của chúng tôi:

Company.Project.Domain.Model  (POCOs) 
Company.Project.Business.Services (BLL) 
Company.Project.Data.Repositories (Repository) 
Company.Project.Web    (Presentation) 
  • POCO của là trong lắp ráp riêng của họ. Tham chiếu không có gìĐược tham chiếu bởi tất cả.
  • BLL thực hiện truy vấn đối với kho lưu trữ, áp dụng quy tắc kinh doanh và hydrat hóa. Trả lại ICollection<T> hoặc T. Tham khảo Kho lưu trữ (qua IRepository<T> giao diện chung) và POCOs.
  • Kho lưu trữ được thiết lập của các lớp chung thực hiện IRepository<T> để cung cấp độ bền cơ bản đối với cửa hàng cơ bản. Tìm, Thêm, Xóa, v.v. Trả lại IQueryable. Tài liệu tham khảo POCO's, Được tham chiếu bởi BLL.
  • Bản trình bày là giao diện người dùng. Tham khảo POCOs và BLL.

Kết quả cuối cùng là một cách tiếp cận giống như ngăn xếp và vì cơ bản mọi thứ đều thông qua giao diện (và đăng ký DI), tính linh hoạt rất lớn.

Chúng tôi có kho lưu trữ giả được đưa vào các dự án thử nghiệm thông qua DI và Kho lưu trữ khung thực thể được tiêm vào BLL qua DI.

Ví dụ dòng chảy từ giao diện người dùng -> DB:

// "Company.Project.Web.ProductsController.cs" 
public class ProductsController : BaseController 
{ 
    private IProductService _productService; 

    public ProductsController(IProductService productService) 
    { 
     this._productService = productService; // DI makes me happy :) 
    } 

    public ActionResult GetOrdersForProduct(Product product) 
    { 
     var orders = _productService.GetOrders(product); 
     return View(orders); 
    } 
} 

// "Company.Project.Business.Services.ProductService.cs" 
public class ProductService : IProductService 
{ 
    private IRepository<Product> _productRepository; 

    public ProductService (IRepository<Product> productRepository) 
    { 
     this._productRepository = productRepository; // DI makes me happy :) 
    } 

    public ICollection<Orders> GetOrdersForProduct(Product product) 
    { 
     return _productRepository 
       .Find() 
       .ForProduct(product) // IQueryable<Product> pipe/extension filter 
       .ToList(); 
    } 
} 

// "Company.Project.Data.Repositories.GenericRepository.cs 
public class GenericRepository<T> : IRepository<T> where T : class 
{ 
    private IObjectSet<T> _objectSet; 

    public GenericRepository(IUnitOfWork unitOfWork) 
    { 
     CurrentContext = unitOfWork as SqlServerUnitOfWork; 
    } 

    public IQueryable<T> Find() 
    { 
     return CurrentContext.GetEntitySet<T>(); 
    } 

    protected SqlServerUnitOfWork CurrentContext { get; private set; } 

    protected IObjectSet<T> CurrentEntitySet 
    { 
     // some plularization smarts in "SqlServerUnitofWork.cs", to dynamically pull 
     // back entity set based on T. 
     get { return _objectSet ?? (_objectSet = CurrentContext.GetEntitySet<T>()); } 
    } 
} 

Như bạn thấy, tôi là một fanboy DI.

+1

Chỉ là một gợi ý hiệu suất - Thay vì trả lại ICollection hãy thử trả lại IQueryable - Điều này cho phép bạn tải Lười các mục trong danh sách giảm chi phí nếu giao diện người dùng chỉ cần tập con (ví dụ: để phân trang) – Basic

+0

@Basiclife - đọc phần của tôi về Kho. Tôi đang làm chính xác điều đó. IMO họ nên được hoãn lại cho BLL, không tiếp tục xuống giao diện người dùng, nếu không bạn có thể nhận được kết quả không mong muốn. Phân trang rất dễ dàng, chỉ cần chuyển pagenumber/pagesize vào phương thức trong BLL, nó bỏ qua/nhận trên iqueryable từ repo. – RPM1984

+0

Và bằng cách này, đó không phải là tải lười biếng, đó là ** thực hiện trì hoãn **. Cẩn thận đừng làm lẫn lộn cả hai. Tôi vô hiệu hóa tải lười biếng trong EF, và mong muốn tải các thực thể BLL yêu cầu sử dụng '.Include'. – RPM1984