Chúng tôi đang phát triển một ứng dụng ASP.NET MVC và hiện đang xây dựng các lớp kho lưu trữ / dịch vụ. Tôi tự hỏi liệu có bất kỳ lợi thế lớn nào để tạo giao diện IRep repository chung mà tất cả các kho lưu trữ đều thực hiện, so với mỗi Kho lưu trữ có giao diện và bộ phương thức riêng.
Ví dụ: giao diện IRep repository chung có thể trông giống như (lấy từ câu trả lời này ):
public interface IRepository : IDisposable
{
T[] GetAll<T>();
T[] GetAll<T>(Expression<Func<T, bool>> filter);
T GetSingle<T>(Expression<Func<T, bool>> filter);
T GetSingle<T>(Expression<Func<T, bool>> filter, List<Expression<Func<T, object>>> subSelectors);
void Delete<T>(T entity);
void Add<T>(T entity);
int SaveChanges();
DbTransaction BeginTransaction();
}
Mỗi Kho lưu trữ sẽ triển khai giao diện này, ví dụ:
- Kho lưu trữ khách hàng: Kho lưu trữ
- ProductRep repository: IRep repository
- Vân vân.
Sự thay thế mà chúng tôi đã theo dõi trong các dự án trước sẽ là:
public interface IInvoiceRepository : IDisposable
{
EntityCollection<InvoiceEntity> GetAllInvoices(int accountId);
EntityCollection<InvoiceEntity> GetAllInvoices(DateTime theDate);
InvoiceEntity GetSingleInvoice(int id, bool doFetchRelated);
InvoiceEntity GetSingleInvoice(DateTime invoiceDate, int accountId); //unique
InvoiceEntity CreateInvoice();
InvoiceLineEntity CreateInvoiceLine();
void SaveChanges(InvoiceEntity); //handles inserts or updates
void DeleteInvoice(InvoiceEntity);
void DeleteInvoiceLine(InvoiceLineEntity);
}
Trong trường hợp thứ hai, các biểu thức (LINQ hay nói cách khác) sẽ hoàn toàn được chứa trong triển khai Kho lưu trữ, bất cứ ai đang triển khai dịch vụ chỉ cần biết chức năng kho lưu trữ nào sẽ gọi.
Tôi đoán tôi không thấy lợi thế của việc viết tất cả cú pháp biểu thức trong lớp dịch vụ và chuyển đến kho lưu trữ. Điều này có nghĩa là mã LINQ dễ gây rối sẽ bị trùng lặp trong nhiều trường hợp?
Ví dụ: trong hệ thống lập hóa đơn cũ, chúng tôi gọi
InvoiceRepository.GetSingleInvoice(DateTime invoiceDate, int accountId)
từ một vài dịch vụ khác nhau (Khách hàng, Hóa đơn, Tài khoản, v.v.). Điều đó có vẻ sạch sẽ hơn nhiều so với viết sau đây ở nhiều nơi:
rep.GetSingle(x => x.AccountId = someId && x.InvoiceDate = someDate.Date);
Nhược điểm duy nhất tôi thấy khi sử dụng cách tiếp cận cụ thể là chúng ta có thể kết thúc với nhiều hoán vị của các hàm Get *, nhưng điều này có vẻ vẫn thích hợp hơn để đẩy logic biểu thức lên các lớp Dịch vụ.
Tôi đang thiếu gì?