【问题标题】:LINQ Strange SQL OutputLINQ 奇怪的 SQL 输出
【发布时间】:2014-05-20 23:00:58
【问题描述】:

所以我通过这个 LINQ 查询得到了一些很奇怪的 SQL 输出。

public string GetHeaders(string header,string lec, string state)
{
    string[] states = { "FL", "CA", "IN", "AL", "MI" };
    string[] updatedstateslist = states.Where(x => x != state).ToArray();
    var headers = (from h in db.Headers
                   where h.Description.Contains(header) & h.LEC == lec & !updatedstateslist.Contains(h.State)
                   select new
                   {
                       description = h.Description,
                       sic = h.SIC,
                       yphv = h.YPHV,
                       state = h.State
                   });

SQL OutPut 即将推出

SELECT 
    1 AS [C1], 
    [Extent1].[Description] AS [Description], 
    [Extent1].[SIC] AS [SIC], 
    [Extent1].[YPHV] AS [YPHV], 
    [Extent1].[State] AS [State]
FROM [dbo].[Headers] AS [Extent1]
WHERE ([Extent1].[Description] LIKE @p__linq__0 ESCAPE N'~') 
  AND (([Extent1].[LEC] = @p__linq__1) OR (([Extent1].[LEC] IS NULL) AND (@p__linq__1 IS NULL))) 
  AND ( NOT (([Extent1].[State] IN (N'FL', N'CA', N'AL', N'MI')) AND ([Extent1].[State] IS NOT NULL)))

奇怪的具体部分是 (@p__linq__1 IS NULL)

我无法弄清楚 LINQ 的哪一部分导致了这一小部分的出现。如果我知道我可以重写 Linq 以避免这种情况发生。

【问题讨论】:

  • 这肯定看起来像一个绑定变量,不是吗?

标签: c# linq


【解决方案1】:

这里没有问题,框架做对了。

它必须转换 C# 谓词

h.LEC == lec

转化为 SQL 等价物。

SQL 的一个有趣的怪癖是谓词NULL = NULL 的计算结果为NULL,当转换为布尔值时,它变成false(see this question)

因此框架必须将其转换为一个 sql 谓词,以确定它们是否具有相等的值,或者都为空。如果你不得不手写,你最终会写同样的东西:

([Extent1].[LEC] = @p__linq__1) 
             OR 
(([Extent1].[LEC] IS NULL) AND (@p__linq__1 IS NULL)))

【讨论】:

  • 添加注释:绑定变量对于数据库性能良好。它们允许引擎执行已经编译的查询,因为引擎已经知道执行计划;只有那些变量——具有相同的数据类型——正在改变。如果你避免绑定变量,就性能而言,你是在直接打自己的脚。
  • 如果我在数据库上运行此查询并删除此部分 OR (([Extent1].[LEC] IS NULL) AND (@p__linq__1 IS NULL)) 我会得到我期望得到的结果。所以我很困惑你说当结果不一样时它正在正确地做事。我使用 SQL 已经有一段时间了,但我承认无论如何我都不是专家。话虽这么说,你能解释一下你的答案吗
  • @scripter78 - 你说你得到了你期望的结果。但是尝试将行值设置为null,将查询参数设置为null,看看你是否仍然得到匹配。
  • 也许我没有正确阅读您的评论(过去 72 小时真的很长),但您最后的评论似乎是要添加这个(([Extent1].[LEC] IS NULL) AND (@p__linq__1 IS NULL))) 到查询中,如果是这种情况并且您建议我这样做,那么答案是否定的,我没有得到任何结果。
  • @scripter78 - 我的意思是,对于你的一行,SET [Extent1].[LEC] = NULL。然后SET @p__linq___1 = NULL。然后只使用谓词 `[Extent1].[LEC] = @p__linq__1' 运行您的查询。不匹配。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-03
  • 2015-02-18
相关资源
最近更新 更多