例如:通用的IRepository接口可能如下所示(取自这个答案):
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();
}
每个存储库都会实现这个接口,例如:
- CustomerRepository:IRepository
- ProductRepository:IRepository
- 等等。
我们在以前的项目中遵循的替代方案是:
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);
}
在第二种情况下,表达式(LINQ或其他)将完全包含在存储库实现中,无论谁实现服务,只需要知道调用哪个存储库函数即可。
我想我没有看到在服务类中编写所有表达式语法并传递给存储库的优势。这是否意味着易于出错的LINQ代码在许多情况下都被复制了?
例如,在我们旧的发票系统中,我们调用
InvoiceRepository.GetSingleInvoice(DateTime invoiceDate, int accountId)
从几个不同的服务中获取数据(客户、发票、账户等)。这比在多个地方编写以下内容要清晰得多:
rep.GetSingle(x => x.AccountId = someId && x.InvoiceDate = someDate.Date);
我认为使用特定方法的唯一缺点是我们可能会得到许多Get *函数的排列组合,但这仍然比将表达式逻辑推入Service类更可取。
我错过了什么?