2014-04-07 90 views
2

我在實體框架中的linq查詢有問題。我正在查詢導航屬性上的某個字段。問題是生成的sql不夠理想。下面的例子被簡化了,實際上我試圖傳遞一個表達式樹,這就是爲什麼使用let綁定的第二個查詢不是一個足夠的解決方案,即使生成的sql是我想要的。這些查詢爲什麼會生成不同的sql?

所以總結我有兩個問題:

爲什麼生成的sql不同?有沒有什麼辦法來產生一個SQL查詢不會創建每個標準與表達式樹的聯接?

更新:我意識到,我必須包含(「證券」)的第一個查詢,而不是第二次,當我第一次張貼的問題,但它不會改變審覈規定的應用方式,僅列選擇。

var qry = db.Positions     
    .Where(criteria) 
    .ToList(); 

var qry1 = (from p in db.Positions 
      where p.Security.Country == "NO" || p.Security.Country == "US" || p.Security.Country == "GB" 
      select p).ToList(); 

var qry2 = (from p in db.Positions 
      let s = p.Security 
      where s.Country == "NO" || s.Country == "US" || s.Country == "GB" 
      select p).ToList(); 


--qry1 
SELECT 
    [Extent1].* --All columns from tblPositions 
    FROM  [dbo].[tblPositions] AS [Extent1] 
    LEFT OUTER JOIN [dbo].[tblSecurities] AS [Extent2] ON ([Extent2].[SecurityType] IN (1,2..)) AND ([Extent1].[Security] = [Extent2].[SecuritySeq]) 
    LEFT OUTER JOIN [dbo].[tblSecurities] AS [Extent3] ON ([Extent3].[SecurityType] IN (1,2..)) AND ([Extent1].[Security] = [Extent3].[SecuritySeq]) 
    LEFT OUTER JOIN [dbo].[tblSecurities] AS [Extent4] ON ([Extent4].[SecurityType] IN (1,2..)) AND ([Extent1].[Security] = [Extent4].[SecuritySeq]) 
    LEFT OUTER JOIN [dbo].[tblSecurities] AS [Extent5] ON ([Extent5].[SecurityType] IN (1,2..)) AND ([Extent1].[Security] = [Extent5].[SecuritySeq]) 
    WHERE [Extent2].[Country] = 'NO' OR [Extent3].[Country] = 'US' OR [Extent4].[Country] = 'GB' 

--qry2 
SELECT 
    [Extent1].* 
    FROM [dbo].[tblPositions] AS [Extent1] 
    LEFT OUTER JOIN [dbo].[tblSecurities] AS [Extent2] ON ([Extent2].[SecurityType] IN (1,2..)) AND ([Extent1].[Security] = [Extent2].[SecuritySeq]) 
    WHERE [Extent2].[Country] IN ('NO','US','GB') 
+0

哪個版本EF這是? –

+0

@GertArnold 6.0.2 –

回答

0

在第一個查詢

var qry1 = (from p in db.Positions.Include("Security") 
      where p.Security.Country == "NO" 
      || p.Security.Country == "US" 
      || p.Security.Country == "GB" 
      select p).ToList(); 

你似乎認爲實體框架具有神奇的力量,可以推斷,每個所生成的表達式樹的or報表是同一個對象,並它可以將它們組合成一個包含。到目前爲止,這並不是那麼聰明。

此外,兩個查詢返回的行都不相同。第二個也需要include,以包含來自安全的行(如果需要的話)。否則,您可以從第一個查詢中刪除它們(僅包含返回行,它與where子句篩選行的能力無關)。

或者使其更加面向對象和可讀性。

var allowedCountries = new List<string>() { "NO, "US", "GB" }; 

var qry1 = (from p in db.Positions 
      // I'm not sure if this is exactly correct 
      where p.Security.Country in allowedCountries 
      select p).ToList(); 

或拉姆達(我更熟悉)

var qry1 = db.Positions 
      .Where(p => allowedCountries.Contains(p.Security.Country)) 
      .ToList(); 
+0

你是對的; EF可能會問很多問題。但是,我在設計者中指定的關係告訴實體框架,每個位置應該只有一個安全性。 –

相關問題