LINQ语句生成与LinqPad不同的查询

时间:2015-02-13 13:35:15

标签: c# linq

我有以下代码通过LEFT JOIN查询一些数据:

Model1 db = new Model1();

db.Database.Log = System.Console.Write;

var x = from e in db.Employees
        where e.id == 746
        join f in db.Company on e.CompanyID equals f.ID into fa
        from fr in fa.DefaultIfEmpty()
        select new
        {
          e.id,
          e.name,
          companyName = fr.name
        };

x.Any(); // to see the query in console

此处使用的类由Visual Studio向导生成,以确保模型和数据库上下文代码正确。

当我在LINQpad中运行该代码时,SQL查询看起来像

SELECT [t0].[id] AS [id], [t0].[name] AS [name], [t1].[name] AS [companyName]
FROM [Employees] AS [t0]
LEFT OUTER JOIN [Company] AS [t1] ON [t0].[CompanyID] = [t1].[ID]
WHERE [t0].[id] = 1615

但是当我在一个简单的控制台应用程序中运行代码时,我得到以下完全错误的神秘查询:

SELECT 
    CASE WHEN ( EXISTS (SELECT 
        1 AS [C1]
        FROM  [dbo].[Employees] AS [Extent1]
        LEFT OUTER JOIN [dbo].[Company] AS [Extent2] ON ([Extent1].[CompanyID] = [Extent2].[ID]) OR (([Extent1].[CompanyID] IS NULL) AND ([Extent2].[ID] IS NULL))
        WHERE 1615 = [Extent1].[id]
    )) THEN cast(1 as bit) ELSE cast(0 as bit) END AS [C1]
    FROM  ( SELECT 1 AS X ) AS [SingleRowTable1]

我试图找到一个解决方案现在几个小时,LINQ只是没有得到正确的查询。

有人有同样的问题并以某种方式解决了吗?非常感谢任何帮助。

2 个答案:

答案 0 :(得分:4)

此查询对我来说是正确的。 LINQpad查询看起来不同,因为在您的代码中使用Any()

在LINQpad中尝试以下查询。它应该显示相同的sql:

 (from e in Employees
    where e.id == 746
    join f in Company on e.CompanyID equals f.ID into fa
    from fr in fa.DefaultIfEmpty()
    select new
    {
      e.id,
      e.name,
      companyName = fr.name
    }).Any()

要在控制台中查看正确的查询,您可以使用ToList()代替Any()

答案 1 :(得分:1)

显然,这两个使用不同的底层提供商。 LinqPAD将xx.Any()视为两个单独的查询 - 它在SQL中执行x并在内存中执行x.Any()

您的控制台应用程序使用的编译器或提供程序会创建一个IQueryable,因此您最终会得到一个SQL查询。请注意,您应该获得正确的答案,但组合的SQL查询会删除Any不需要的项目,例如您请求的字段名称。

如果您使用x进行其他内容,例如将其转换为List或称为AsEnumerable,我打赌您会看到大致相同的查询来自控制台应用程序。