2015-11-17 145 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