存储库/ IQueryable的/查询对象(Repository / IQueryable / Qu

2019-06-27 01:48发布

我建立一个资料库,我已经在很多地方2个原因看到不暴露IQueryable的仓库外。

1)首先是因为不同的LINQ提供程序可以表现不同,这种差异应包含在存储库中。

2)第二个是防止服务级别从开发人员修改数据库查询,使得其不小心会导致性能问题。

我想问题2只能通过保持库中的所有查询逻辑,而不是让任何形式的外部查询建筑可以预防吗? 但是,这似乎有点不切实际给我。

第1期似乎通过使用数据对象模式来解决。

例如public IEnumerable<T> FindBy(Query query)

我的问题是,为什么我不只是传递一个lambda表达式,因为这是独立供应商,似乎为我提供相同的功能为查询对象,分离的同一级别?

例如public IEnumerable<T> FindBy(Expression<Func<T,bool>> predicate)

有什么理由不这样做呢? 它打破一些规则? 最佳做法? 我应该知道的吗?

Answer 1:

只是返回IQueryable<T>

之前你写的“仓库代码”另一位,你会从阅读Ayende的文章显著受益的库抽象层的罪恶-架构在死命坑

你的做法是,毫无疑问,加入显著不必要的复杂性。

所有的在其他问题的代码排序依据LAMBDA的泛型列表不能做的比掩盖现有的有效的API和不必要的和不熟悉的抽象的任何其他。

关于你提到的两个问题,

  1. LINQ提供程序的行为不同,但只要您正在传递的谓词可以通过LINQ提供程序进行处理,这是无关紧要的。 否则,你还是会遇到同样的问题,因为你传递一个Expression ,它被传递到IQueryable最终反正。 如果IQueryProvider实现无法处理您的谓语,那么就无法处理您的谓语。 (您可以随时调用ToList()如果你需要评估之前,进一步的过滤不能被翻译)。

  2. 修改查询可能会导致性能问题,但它更容易暴露急需的功能。 此外,通过一个次优的LINQ查询所产生的性能问题可能比拉了很多的记录所产生的性能问题显著较少的危害比你需要的,以避免暴露的IQueryable ,或者通过系统过滤的任何数据访问逻辑抽象,实际上并不做任何事情的臃肿水平(第一个威胁是更显著)。 在一般情况下,这不会是一个问题,因为最领先的LINQ提供者将在翻译过程中优化您的查询逻辑。

如果你想从前端隐藏你的查询逻辑,那么不要尝试做一个通用的存储库。 封装与实际业务的具体方法查询。 现在,我可能是错误的,但我假设你的仓库模式的使用是由领域驱动设计的启发。 如果是这样的话,那么使用存储库的原因是为了让你创建一个持久昧域中的一个主要焦点域模型。 但是,使用这种通用的存储库并没有做太多超过改变从语义的Create Read Update Delete ,以Find Add Remove Save 。 没有嵌入有没有真正的商业知识。

考虑的是否有意义(和可用性)

interface IPersonRepository 
{ 
     Person GetById(int id);
     IEnumerable<Person> FindByName(string firstName, string lastName);
}

对比

interface IRepository<T> { 
     IEnumerable<T> FindBy(Query<T> query);
}

此外,你能实际上指向一个好处是用所述IRepository<T>在所有的(而不是一个IQueryable<T>

此外,考虑到与通用的方法,你实际上并没有封装查询逻辑可言。 你最终会在外部构建它,这是会导致更多不必要的额外代码。

*有关建议不要使用资源的另外一个音符IQueryable<T>就在于它是值得看看他们的出版日期。 曾经有LINQ提供程序的可用性是相当有限(早期EF和LINQ到SQL)的时间。 当时曝露出IQueryable<T>将需要一些微软ORM比较流行的替代品(LINQ到NHibernate的是早已实现)的不兼容。 在这个时间点,LINQ的支持是严重的ORM的.NET库几乎无处不在



Answer 2:

与上面卫冕答案,反对派明确的一点是单元测试 。 返回一个简单的泛型IQueryable是漏抽象到可以访问调用它的任何客户端。 存在用于存储库的方法没有限制,因此,没有在一个单元测试来断言。

使用IQueryable几乎可以肯定依赖于应用本身,以及体系结构的上下文。 例如,如果你在一个个人项目通过自己的工作,你可以放心地假定这个挥舞着不受限制的权力没有确凿的任何人,但你自己的责任。 但是,如果你在与代码进入生产企业的应用程序时,必然有更多的利益相关者比你参与。 在这种情况下,你可以在数据访问层中工作,并在尝试编码与其他开发人员使用的代码。 现在,你需要控制什么进来,出去,使他们不会破坏你的代码,你不打破他们的。 这就是激励和单元测试是执行。

随着中说,不要简单地使用IQueryable<T> 用什么有意义的应用程序。



文章来源: Repository / IQueryable / Query Object