具有实体框架通用存储库模式的规范模式

Ome*_*r K 0 c# design-patterns entity-framework specification-pattern repository-pattern

最近遇到一篇文章实现查询规范模式,我对将规范模式与通用存储库一起使用感到困惑。

我已经有一个像这样的通用回购协议:

public interface IGenericRepository<T> where T:class
{ 
    IReadOnlyList<T> GetAllAsunc(int id); 
    IReadOnlyList<T> FindAsync(Expression<Func<T, bool>> filter); 
    T GetById(int id)
    void Add(T item); 
    void Update(T item); 
    void Delete(T item); 
}
Run Code Online (Sandbox Code Playgroud)

以及规范模式的示例方法

public BaseSpecification(Expression<Func<T, bool>> criteria)
{
    Criteria = criteria;
}
Run Code Online (Sandbox Code Playgroud)

我可以用IReadOnlyList<T> FindAsync(Expression<Func<T, bool>> filter);方法发送任何表达式。所以,我真的不明白为什么我需要带有通用存储库的规范模式。看起来他们在做同样的事情。你能澄清一下吗?

Ste*_* Py 5

规范模式不仅仅涵盖过滤表达式,还涵盖急切加载和分页。在您的示例中,如果您正在处理一个引用 3 个其他实体并具有子集合的实体,您将如何告诉您的存储库方法应立即加载哪些实体?如果您的 List 方法可以返回数十万行,您将如何告诉它一次仅加载 50 页?

在我个人看来,使用规范是通用存储库上的 SRP 创可贴。通用存储库是 EF 系统中的一种反模式,您可以将存储库代码定位为使用规范来缓解这种情况,从而拥有大量“力量”游说更改。我绝不会提倡尝试使用单一通用Controller<T>实现来构建 MVC Web 应用程序,出于同样的原因,我也不提倡使用Repository<T>. 规范不能保护调用者免受域/EF 知识的污染,因为传入的每个表达式都必须符合域实现制定的规则。虽然规范可能会处理过滤、急切加载和分页...排序、投影或其他聚合函数(例如存在检查和计数)怎么样?归根结底,这是一个复杂性的兔子洞,试图满足 SOLID 原则,使您的代码变得更加复杂且难以遵循,并且由于新的需求不符合过去的假设而不断地撞上障碍。