2013-01-03 66 views
8

我有兩個類似的查詢返回理論上相同的結果:意外LINQ的行爲 - ToList()

var requestNotWorking = SessionManagement.Db.Linq<Item>(false).Where(i => 
         i.Group != null && i.Group.Id == methodParameter) 
         .ToList(); 

此請求返回0的項目,即使它應該返回一個。 以下是對後者的重寫,但是調用了ToList()方法。此請求有效並返回第一個查詢中預期的項目!

var requestWorking = SessionManagement.Db.Linq<Item>(false).ToList().Where(i => 
        i.Group != null && i.Group.Id == methodParameter).ToList(); 

注:SessionManagement.Db.Linq<Item>(false)是一個通用的LINQ到NHibernate的方法與所述布爾屬性確定該請求必須在高速緩存中(真)或數據庫(假)來執行。這種方法應該沒有錯,因爲它在解決方案的許多其他部分中正常工作。項目的映射是沒有什麼奇特的:沒有袋子和以下參數: lazy="false" schema="dbo" mutable="false" polymorphism="explicit"

這是爲什麼呢?

編輯

(Item.Group_ID is not null) and [email protected]',N'@p0 int',@p0=11768

requestWorking的生成的SQL請求是大致一個select * from dbo.Items

+1

如果您使用的是Sql Server,您是否曾嘗試在運行這兩個查詢的同時運行SQL Profiler? – nerdybeardo

+0

i.Group在兩者之間有所不同。具有相同的名稱,但在不同類型的館藏中完全不同。 –

+1

請發佈生成的SQL。 SQL與C#語義規定的內容之間存在語義差異。 LINQ不承諾相同的語義。 – usr

回答

1

我對c.Group.Id != null的理論非常感興趣,我發現它是合乎邏輯的,即使它與我的解決方案中的其他代碼相矛盾。但是,刪除它並沒有改變任何東西。我發現刪除mutable="false"屬性解決了這個問題。這似乎有點神奇,但它的工作。

我發佈的請求實際上是在檢查更新/刪除可能性的方法中發生的。我的結論是,不知怎的,使項目不可改變的結果。但我不明白的是爲什麼requestWorking工作呢!

0

所有我可以看到的是:

requestNoWorking的生成的SQL請求結尾在第二個版本中,您的Where由LINQ執行到對象而不是LINQ到NHibernate。所以第一個版本必須做一些LINQ to NHibernate不能很好地消化的東西。

它是LINQ NHibernate的有問題的i.Group != null,看到使用null是CLR特定的。您可能需要在LINQ to NHibernate中使用另一個構造來測試空字段值。

4

我假設你已經在那裏返回一個可查詢的nhibernate會話的事情。如果是這樣,則第一個查詢的評估將延遲至調用.ToList(),並且整個查詢在服務器上運行。如果可能的話,我建議你在sql服務器上運行一個跟蹤,或者下載NHProf來查看正在執行的實際查詢是什麼。

第一個查詢會在您點擊第一個.ToList()後立即求值,因此您將整個表從數據庫中取出,然後使用.net進行過濾。我真的不能告訴你爲什麼他們會以不同的方式進行評估,但我認爲有一些映射/配置會導致db查詢被寫入稍微錯誤。

+3

我的猜測是圍繞null比較,SQL NULL比較總是PITA。 – anydot