2014-04-07 56 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可能会问很多问题。但是,我在设计者中指定的关系告诉实体框架,每个位置应该只有一个安全性。 –

相关问题