1

我一直在努力解決爲什麼這個查詢要求經理和他或她的團隊只返回團隊集合的第一個條目。顯然,這是因爲在查詢結束時我有FirstOrDefault。我覺得FirstOrDefault可以應用到整個查詢中,但它似乎也適用於Team集合。爲什麼這兩個Fluent nHibernate查詢產生不同的結果?

原始查詢(只顯示第一個成員在團隊):

session.Query<IEmployee>() 
       .Where(p => p.PersonalNumber == PersonalNumber) 
       .Fetch(p => p.Team) 
       .Fetch(p => p.Manager) 
       .FirstOrDefault(); 

返回完整的團隊,新的查詢:

session.Query<IEmployee>() 
       .Where(p => p.PersonalNumber == PersonalNumber) 
       .Fetch(p => p.Team) 
       .Fetch(p => p.Manager) 
       .ToList().FirstOrDefault(); 

什麼是制定此查詢正確的方法是什麼?我需要一種解決方法意味着我沒有正確地做到這一點。

背景 - 映射:

這是經理基本的層次關係作爲一個IEmployee和團隊是IEmployee的一個IList。

References(x => x.Manager).Column("ManagerId"); 
HasMany(x => x.Team) 
       .AsList(index => index.Column("TeamIndex")) 
       .KeyColumn("ManagerId"); 
+0

您可以從生成的SQL告訴這是怎麼發生的,因爲問題查詢生成的SQL「FETCH NEXT 1行僅對」這大概意味着,只有第一個加入的記錄將被退回。我不清楚如何讓FirstOrDefault與Fetch正常工作。 – kasey

回答

1

我們一直在努力與所述同樣的問題。對我而言,這發生在從NH 3.1 - > 3.3升級時。問題在於,對於Linq,NHibernate 3.3生成一個SQL查詢,其中有一個「Top(1)」語句,有效地殺死查詢的「Fetch」部分。我通過從Linq切換到QueryOver來解決它。我相信這將工作:

session.QueryOver<IEmployee>() 
       .Where(p => p.PersonalNumber == PersonalNumber) 
       .Fetch(p => p.Team) 
       .Fetch(p => p.Manager) 
       .SingleOrDefault(); 
+0

有趣的是,這實際上是我經過一些實驗後發現的(見下面的答案),而且我使用的是nHibernate 3.3。我想知道原始語法是否應該拋出某種異常,說它是無效的。 – kasey

3
session.Query<IEmployee>() 
      .Where(p => p.PersonalNumber == PersonalNumber) 
      .Fetch(p => p.Team) 
      .Fetch(p => p.Manager) 
      .FirstOrDefault(); 

在這個查詢中FirstOrDefault工作的數據庫上,你的預期。

session.Query<IEmployee>() 
      .Where(p => p.PersonalNumber == PersonalNumber) 
      .Fetch(p => p.Team) 
      .Fetch(p => p.Manager) 
      .ToList().FirstOrDefault(); 

在此查詢中,ToList在數據庫上工作。所有背後的工作都在ToList的結果上。所以FirstOrDefault從ToList的結果集中獲取FirstOrDefault。要獲得相同的結果,您需要爲查詢添加一個訂單。當您執行無順序的選擇時,Sql不會授予結果集的相同順序。 ToList結果中的順序與第一個查詢中的內部順序不同。

+0

對不起,我不太明白。結果集的順序(它總是隻包含1個IEmployee,PersonalNumber是唯一的)將如何影響Employee.Team集合中有多少項目? – kasey

0

問題是我要求一個笛卡兒積(使用Fetch),但也使用FirstOrDefault;從生成的SQL中,我可以看到該組合不起作用,因爲您只獲得笛卡爾產品的第一行(SQL生成:「FETCH NEXT 1 ROWS ONLY」)。

如果我想要這樣做,我需要編寫不同類型的查詢,否則只需使用ToList解決方法,在這種情況下,這並不會造成太大的傷害,因爲我只希望從數據庫得到一個結果。

實施例的解決方案:

session.QueryOver<IEmployee>() 
       .Where(p => p.PersonalNumber == PersonalNumber) 
       .Fetch(p => p.Team).Eager 
       .Fetch(p => p.Manager).Eager 
       .SingleOrDefault(); 
相關問題