5

我在C#標準庫接口,其中包括以下方法:存儲庫/工作單元模式 - 如何查詢符合特定條件的對象的存儲庫?

IEnumerable<T> GetAll(); 
T GetById(int id); 
void Delete(T entity); 
void Add(T entity); 

在我的領域層我的全部實例是工作包裝紙的新單位,並把它傳遞到存儲庫。工作單元包裝類隱藏了我是否使用NHibernate或實體框架並公開了一個Commit()方法。

在我的域圖層中,如何查詢僅滿足特定條件的對象?

我認爲我目前所做的工作非常低效。我目前做這個:

var results = myRepository.GetAll().Where...... 

如果我有一個非常大的物體,是GETALL()會過濾掉我不需要的那些前,他們中的每一個迴歸?我怎樣才能防止不需要的對象被返回?

很明顯,我可以在界面中添加更多的方法,但這似乎並不符合通過界面公開CRUD操作。

即 - 我不認爲我應該增加之類的東西(但也許我錯了):

IList<T> GetAllWhereMeetsMyCriteria(); 

回答

3

查看this blog post [weblogs.asp.net]中使用的存儲庫模式。我發現源代碼使用了一些有趣的模式,我不斷返回並再次檢查。該代碼實現了存儲庫和工作模式單元。

爲了回答您的具體問題,庫接口包含的方法:

IEnumerable<T> GetMany(Expression<Func<T, bool>> where);  

它作爲RepositoryBase<T>類實現方式是:

public virtual IEnumerable<T> GetMany(Expression<Func<T, bool>> where) 
{ 
    return dbset.Where(where).ToList(); 
} 

大概都EF和NHibarnate將有接口必須支持這種用法。

+0

的確他們非常感謝。這解決了我的問題。 – JMc 2011-05-14 11:54:21

2

不熟悉NHibernate的,但通常情況下,我跟你最後溶液(IList<T> GetAllWhereMeetsMyCriteria();) :

public IList<TEntity> Find<TEntity>(Func<TEntity, bool> criteria) where TEntity : class 
{ 
    return this.Query<TEntity>().Where<TEntity>(criteria).ToList<TEntity>(); 
} 

有在寫一個偉大的Genric庫:http://www.martinwilley.com/net/code/nhibernate/genericrepository.html

你可能想使用,因爲它涵蓋了更多的情況。此外,您可以根據特定需求從中派生自定義存儲庫。 (例如:http://www.martinwilley.com/net/code/nhibernate/productrepository.html

UPDATE
您可以在您導出庫定義自定義指標分析,並使用它們。例如

private ICriteria CriteriaCategoryId(int categoryId) 
    { 
     ICriteria criteria = Session.CreateCriteria(typeof(Product)); 
     criteria.CreateCriteria("Category") 
      .Add(Expression.Eq("Id", categoryId)); 
     return criteria; 
    } 
public IList<Product> ProductByCategory(int categoryId, int pageStartRow, int pageSize) 
    { 
     var criteria = CriteriaCategoryId(categoryId) 
      .SetFirstResult(pageStartRow) 
      .SetMaxResults(pageSize); 

     return criteria.List<Product>(); 
    } 
+0

這很有幫助,非常感謝+1。如果事實證明是這樣,我會研究你的建議並標記爲答案。謝謝! – JMc 2011-05-14 11:01:23

+0

沒問題。只要注意許多人不直接使用通用存儲庫。他們從那裏(例如'ProductRepository')派生定製的存儲庫並直接使用這些派生的存儲庫。祝你好運。 – Kamyar 2011-05-14 11:05:43

6

是的,您的GetAll().Where會將您的所有對象從數據庫中提取到您的應用程序並執行linq-to-objects。 @Kamyar解決方案也會這樣做。 @Dysaster在我寫這個答案時提供了一個正確的解決方案。

首先 - 你真的需要它必須支持的NHibernate或EF庫?它是客戶的要求嗎?如果不是你在浪費資源。選擇技術並創建應用程序所需的最小抽象,以遵循問題分離。

如果你真的需要高層次的抽象和持久性API,你應該從家庭使用第三圖案絕對的獨立性 - Specification pattern。使用自定義規範,如果將規範描述的條件轉換爲數據源所需的操作,您將能夠將持久性更改爲任何內容。 NHibernate中的Criteria API或IQueryable的擴展方法是規範,但它們是技術相關的。

+0

請你解釋,爲什麼'this.Query ()。凡(標準).ToList ();'返回的所有實體,然後執行LINQ到對象?我以爲它不會從數據庫中獲取數據,直到我們使用ToList()或等價的方法。是否查詢。在哪裏'首先返回來自數據庫的所有數據,並且它們執行linq? – Kamyar 2011-05-14 11:22:17

+0

不是客戶的要求。我正在爲我的MSc編寫一個項目,在其中檢查實體框架的各個方面。我被要求將它與一個更成熟的O/RM(NHibernate)進行對比,看看它們是如何相互疊加的,因此需要支持這兩者。感謝您的答覆。 – JMc 2011-05-14 11:23:24

+1

@Kamyar:'ToList'執行查詢,但問題是您在'Expressoin '而不是'Expressoin '處使用'Func'。 'Func'是'IEnumerable'上使用的委託,因此EF必須首先將所有實體加載到內存才能運行委託。 '表達式'在'IQueryable'上使用,並被轉換爲SQL。這是非常常見的錯誤。 – 2011-05-14 11:50:57