2010-02-21 50 views
2

在下面的代碼中,當我將「dl.DamageCount> 5」直接放入查詢中,或者將「dl.DamageCount> 5」移動到某個方法或函數然後從查詢中調用時,它有什麼區別?是否有必要不使用LINQ查詢中的方法?

看來,當我將它移入一個方法,查詢無法正常工作。事實上,無論條件評估如何,函數/方法總是返回true。我正在使用Linq-to-NHibernate。

var q = from dl in session.Linq<DamageList>() 
      where 
      dl.DamageCount > 5 

回答

4

您可以做的最好的事情是在Expression<>中捕獲謂詞。一種方法已經被編譯給IL,所以不能被Linq提供者挑選出來。

Expression<Func<DamageList, bool>> predicate = item => item.DamageCount > 5; 

然後,您可以直接傳遞謂詞來Where

var q = session.Linq<DamageList>().Where(predicate); 

如果要動態地結合兩個這樣的表情,你要麼兩者的代碼寫入到一個表達式,也同時捕獲在單獨的表達式。這變得複雜,因爲你需要每一個來引用傳遞的item這的確是一個不同的問題,已經問:How do I dynamically create an Expression<Func<MyClass, bool>> predicate?

您可以使用& & oerator寫一個複合謂語,仍然捕捉它在表達式:

Expression<Func<DamageList, bool>> predicate = 
    dl => dl.DamageCount > 5 && dl.Name.Contains(criteria); 

你問過在這樣一個表達式中調用方法 - 那麼這個例子確實調用了一個方法!

它建立了Expression各種類型的節點樹。包括某處將會有一個方法調用節點,該節點表示調用方法string(假設Namestring)。所以這是嵌入表達式中的方法調用指令的一個例子。爲了使其發揮作用,Linq提供者必須知道該方法的作用,因此它可以將其轉換爲等效的SQL(就像典型的ORM系統那樣)。

因此,您可以在表達式中嵌入某些標準方法調用 - 它需要Linq提供者瞭解它們。 string的方法是明確的,但不是每個提供者都必須能夠處理所有這些方法。

Linq提供程序不允許你添加自己的擴展來處理額外的方法,但我不知道有任何支持(顯然如果系統是開源的,你可以添加你自己)。總結 - Linq提供者需要一個表達式節點樹,它可以分析轉換成其他語言(如SQL),以便在另一個環境(如遠程數據庫內)中執行。如果您編寫普通方法,C#編譯器會將它們編譯爲低級可執行文件IL,而不是表達式節點。所以這就像一個死衚衕:沒有內置的設備可以將IL轉換回表達式節點。

+0

那麼我有多個條件呢?例如:其中dl.DamageCount> 5 && dl.Name.Contains(條件) – 2010-02-21 11:40:51

+0

查看已添加的文本... – 2010-02-21 11:50:49

+0

親愛的Earwicker,另外一個問題:是否可以用這個表達式調用另一個方法?我的意思是:Expression > predicate = MyFunc(); – 2010-02-21 11:54:58

相關問題