2013-03-22 83 views
2

我想爲我的NHibernate數據訪問編寫一個通用的存儲庫。 Get<T>()方法應該能夠接受一個可選謂詞,該謂詞應該包含在查詢中 - 也就是說,NHibernate應該在SQL中生成WHERE子句。NHibernate何時執行我的查詢?

public virtual IList<T> Get(Func<T, bool> predicate = null) 
    { 
     // Open NHibernate Session 
     using (var session = NHibernateHelper.OpenSession()) 
      return (predicate != null 
         ? session.Query<T>().Where(predicate) 
         : session.Query<T>()).ToList(); 

    } 

當我傳入一個謂詞並觀察NH生成的SQL語句時,我看不到where子句。

NHibernate何時執行查詢?請致電.Query<T>()?如果是這樣,我該如何做到這一點?

回答

6

該查詢應該由電話ToList()執行。

爲什麼WHERE子句不包含在您的sql語句中的原因是您需要將Expression<Func<T,bool>>傳遞給您的方法。

public virtual IList<T> Get(Expression<Func<T, bool>> predicate = null) 
    { 
     // Open NHibernate Session 
     using (var session = NHibernateHelper.OpenSession()) 
      return (predicate != null 
         ? session.Query<T>().Where(predicate) 
         : session.Query<T>()).ToList(); 

    } 

Where(Func<T,bool>>)方法是在Enumerable定義,該擴展,使得所述查詢加載所有數據,然後在存儲器中應用WHERE濾波器。

Queryable上定義了擴展方法Where(Expression<Func<T,bool>>),這樣查詢提供程序(NHibernate)就可以構建一個sql語句,包括您在數據源上執行的WHERE條件。

+0

謝謝,絕對完美! – Jeff 2013-03-22 09:42:30

1

由於@Jehof給了你正確的解釋,我只是想添加單獨的註釋 - 你不應該從你的倉庫方法返回IList<T>,因爲任何其他的linq操作都將在內存中執行,而不是在數據庫中執行。所以現在假設下面的調用

var data = repository.Get<Company>(c=>c.Name.StartsWith("MyCompany")); 
... some other operations/method calls etc. 
var companySubset = data.Where(...); 

,如果你有IList<T> Get<T>()你降低性能,但IQueryable<T> Get<T>你仍然會有第二凡()追加到數據庫查詢。

當然不是所有的linq操作都支持IQueryable like(join,last),這是唯一可以調用ToList()擴展來評估表達式的地方。

+0

這是重點,但感謝您的注意:) - 我不希望我的業務邏輯觸發數據庫調用時,我沒有明確要求它。 – Jeff 2013-03-22 09:41:09