Entity Framework Repository Pattern why not return Iqueryable?

不羁岁月 提交于 2019-11-26 21:36:42

问题


There are several good blogs about how to implement the repository pattern together with the unit-of-work pattern using generic classes.

Implementing a Data Access Layer with Entity Framework 6.1

Implementing the Repository and Unit of Work Patterns

The Idea is, to define a generic interface IRepository and a class Repository that hides how the data is actually accessed. It can be accessed using Entity Framework DbContext, or maybe the repository is an in memory collection for unit testing.

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.
}

Quite often I see that several Query functions are added that are similar to Queryable and/or Enumerable functions.

For instance in Implementing a data access layer I see:

/// 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);

If the interface had a function IQueryable GetQuery(), then I wouldn't have to make functions like GetFirst() and GetByQuery().

Question: Why is this not recommended? Can people change the data in an undesirable way?


回答1:


One of the reasons we use the repository pattern is to encapsulate fat queries. These queries make it hard to read, understand and test actions in ASP.NET MVC controllers. Also, as your application grows, the chances of you repeating a fat query in multiple places increases. With the repository pattern, we encapsulate these queries inside repository classes. The result is slimmer, cleaner, more maintainable and easier-to-test actions. Consider this example:

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

Here we are directly using a DbContext without the repository pattern. When your repository methods return IQueryable, someone else is going to get that IQueryable and compose a query on top of it. Here’s the result:

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

Can you see the difference between these two code snippets? The only difference is in the first line. In the first example, we use context.Orders, in the second we use repository.GetOrders(). So, what problem is this repository solving? Nothing!

Your repositories should return domain objects. So, the GetOrders() method should return an IEnumerable. With this, the second example can be re-written as:

var orders = repository.GetOrders(1234);

See the difference? Retrieved from Mr. Hamedani blog




回答2:


This isn't recommended because it would invalidates the repository pattern. The purpose of this pattern is to keep your DAL implementation separate from your other projects by means of abstraction.

In essence returning an IQueryable would return the TSQL statement and NOT the results meaning any projects that reference your DAL would require additional references to EF to be able to perform the execution of the query. This 'data leak' would make your projects more tightly-knit and thus would contradict the separation of concern principle.

You can read more about the repository pattern and its benefits here: http://www.codeproject.com/Articles/526874/Repositorypluspattern-cplusdoneplusright



来源:https://stackoverflow.com/questions/33755499/entity-framework-repository-pattern-why-not-return-iqueryable

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!