2015-11-17 142 views
4

关于如何使用泛型类与工作单元模式一起实现存储库模式,有几个很好的博客。实体框架存储库模式为什么不返回Iqueryable?

Implementing a Data Access Layer with Entity Framework 6.1

Implementing the Repository and Unit of Work Patterns

理念是,定义一个通用接口IRepository和类信息库,它隐藏该数据实际上是如何访问。它可以使用实体框架DbContext进行访问,也可以将知识库作为内存集合进行单元测试。

public interface public interface IRepository<T> where T : class 
{ 
    T GetById(int Id); 
    void DeleteById(int Id); 

    void Add(T entity); 
    void Update(T entity); 

    etc. 
} 

常常我看到添加几个查询功能类似于可查询和/或可枚举函数。

比如在Implementing a data access layer我看到:

/// Returns an IEnumerable based on the query, order clause and the properties included 
/// <param name="query">Link query for filtering.</param> 
/// <param name="orderBy">Link query for sorting.</param> 
/// <param name="includeProperties">Navigation properties seperated by comma for eager loading.</param> 
/// <returns>IEnumerable containing the resulting entity set.</returns> 
IEnumerable<T> GetByQuery(Expression<Func<T, bool>> query = null, Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null, string includeProperties = ""); 

/// <summary> 
/// Returns the first matching entity based on the query. 
/// </summary> 
/// <param name="predicate"></param> 
/// <returns></returns> 
T GetFirst(Expression<Func<T, bool>> predicate); 

如果接口有一个功能的IQueryable GetQuery(),那么我就不会做功能,如GetFirst()和GetByQuery()。

问题:为什么不推荐这么做?人们能否以不希望的方式改变数据?

回答

4

一个我们使用的存储库模式是封装脂肪查询的原因。这些查询使得很难在ASP.NET MVC控制器中阅读,理解和测试操作。另外,随着应用程序的增长,您在多个地方重复胖查询的机会也会增加。使用存储库模式,我们将这些查询封装在存储库类中。其结果是更苗条,更清洁,更易于维护和更易于测试的操作。考虑这个例子:

var orders = context.Orders 
    .Include(o => o.Details) 
     .ThenInclude(d => d.Product) 
    .Where(o => o.CustomerId == 1234); 

这里我们直接使用没有存储库模式的DbContext。当您的存储库方法返回IQueryable时,其他人将获得该IQueryable并在其上构建一个查询。结果如下:

var orders = repository.GetOrders() 
    .Include(o => o.Details) 
     .ThenInclude(d => d.Product) 
    .Where(o => o.CustomerId == 1234); 

你可以看到这两个代码片段的区别吗?唯一的区别在于第一行。在第一个例子中,我们使用context.Orders,在第二个例子中我们使用repository.GetOrders()。那么,这个知识库解决什么问题?没有!

您的存储库应该返回域对象。所以,GetOrders()方法应该返回一个IEnumerable。有了这个,第二个例子可以重写为:

var orders = repository.GetOrders(1234); 

看到区别? 取自Hamedani先生blog

+2

嘿,它是从这个博客的文本复制粘贴:https://programmingwithmosh.com/entity-framework/common-mistakes-with-the-repository-pattern/。 你应该提到这个信息“借” - ))) –

4

这不被推荐,因为它会使存储库模式无效。 这种模式的目的是通过抽象的方式使DAL实现与其他项目分离。

实际上,返回IQueryable将返回TSQL语句,而不是结果意味着任何引用您的DAL的项目都需要额外的EF引用才能执行查询。这种“数据泄漏”会让你的项目更加紧密,因此会与关注原则分离相矛盾。

你可以阅读更多有关存储库模式,它的好处在这里: http://www.codeproject.com/Articles/526874/Repositorypluspattern-cplusdoneplusright