为什么 Linq Contains 会生成此 SQL?

2024-04-11

背景:我正在开发一个系统,用于清理内部客户列表并找出联系人的电子邮件地址,其中我们已经拥有该公司其他人的电子邮件地址。为了做到这一点,我有(简化的)3 个表:

Contacts:

ID
CompanyId
Email
Domain

电子邮件域名:

ID
Domain
EmailFormat
EmailFormatConfirmed

我有一个手动例程,即给定公司,找到我下一个联系人,我们有他们的域名但没有他们的电子邮件地址:

int companyId = 53;

var emails = Contacts.Where(p => p.companyId == companyId
                                            && p.Email == null
                                            && !string.IsNullOrEmpty(p.Domain)).Select(p => p.Domain);
var domain =
    EmailDomains.FirstOrDefault(
        d => !d.EmailFormatConfirmed 
            && !string.IsNullOrEmpty(d.Domain)
            && emails.Contains(d.Domain));

该查询运行速度非常慢,并且在检查生成的 Sql 时:

    -- Region Parameters
DECLARE @p__linq__0 Int = 53
-- EndRegion
SELECT TOP (1) 
    [Extent1].[Id] AS [Id], 
    [Extent1].[Domain] AS [Domain], 
    [Extent1].[EmailFormat] AS [EmailFormat], 
    [Extent1].[EmailFormatConfirmed] AS [EmailFormatConfirmed], 
    FROM [dbo].[EmailDomain] AS [Extent1]
    WHERE ([Extent1].[EmailFormatConfirmed] <> 1) 
        AND ( NOT (([Extent1].[Domain] IS NULL) OR ((LEN([Extent1].[Domain])) = 0))) 
        AND ( EXISTS (
            SELECT 1 AS [C1]
            FROM [dbo].[Contacts] AS [Extent2]
            WHERE ([Extent2].[CompanyId] = @p__linq__0) 
                AND ([Extent2].[Email] IS NULL) 
                    AND ( NOT (([Extent2].[Domain] IS NULL) OR ((LEN([Extent2].[Domain])) = 0))) 
                    AND (([Extent2].[Domain] = [Extent1].[Domain]) OR (([Extent2].[Domain] IS NULL) AND ([Extent1].[Domain] IS NULL)))
    ))

我可以看到有问题的部分是OR (([Extent2].[Domain] IS NULL) AND ([Extent1].[Domain] IS NULL))在存在子句的末尾。为什么会有这个?我不明白它是如何有效的,如果我手工编写 Sql 代码(目前这是我必须依靠的),那就不会了。我错过了一些明显的事情吗?删除这个使得查询运行得非常快(正如预期的那样 - 有很多空域在这里有效地交叉连接)


在 EF6 中,此行为由DbContextConfiguration UseDatabaseNullSemantics https://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k(System.Data.Entity.Infrastructure.DbContextConfiguration.UseDatabaseNullSemantics);属性(默认情况下false):

获取或设置一个值,该值指示在比较两个操作数(这两个操作数都可能为空)时是否显示数据库空语义。默认值为 false。例如 (operand1 == operand2) 将被翻译为: (operand1 = operand2) 如果 UseDatabaseNullSemantics 为 true,则分别 (((operand1 = operand2) AND (NOT (operand1 IS NULL OR operand2 IS NULL))) OR ((operand1 IS NULL) AND (operand2 IS NULL))) 如果 UseDatabaseNullSemantics 为 false。

所以只需将其转为true问题就会得到解决。

你可以在你的内部做到这一点DbContext构造函数:

this.Configuration.UseDatabaseNullSemantics = true;

或者仅针对执行命令之前的特定上下文实例:

var db = new YourDbContext();
db.Configuration.UseDatabaseNullSemantics = true;
var emails = db.Contacts.Where(...)
...

但请注意,如果您比较查询中的可为空字段并且不包含显式字段,则打开该选项可能会导致一些意外结果null检查,所以要小心使用。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 Linq Contains 会生成此 SQL? 的相关文章

随机推荐

  • 使用 ASP.NET MVC 的 SEO URL

    有没有一个确定的DO and DONT当实施 seo url 时 许多好的做法对于 html 网站来说似乎很好 但在中型 大型数据库网站上却失效了 据我所知 网址应该是www mysite com category page name he
  • require_once 与子文件夹[关闭]

    这个问题不太可能对任何未来的访客有帮助 它只与一个较小的地理区域 一个特定的时间点或一个非常狭窄的情况相关 通常不适用于全世界的互联网受众 为了帮助使这个问题更广泛地适用 访问帮助中心 help reopen questions 我的文件夹
  • Angular2/Angular 种子 http-proxy-middleware 代理 api 请求

    我正在使用角种子项目 https github com mgechev angular seed tree master tools并尝试为在不同端口上运行的后端服务的 api 请求设置代理 到目前为止我的代码 Add proxy midd
  • 如何在 PowerShell 中取消“终止批处理作业 (Y/N)”确认?

    When I press Ctrl C in PowerShell I receive 终止批处理作业 是 否 如同https superuser com questions 35698 how to supress terminate b
  • 在 JFrame 中绘制矩形不起作用

    我有一段代码应该在JFrame但是当我在 Eclipse 上运行该程序时 它只是打开框架 但没有在其上绘制圆圈 这是代码 import javax swing import java awt public class Infout Info
  • 错误:2 UNKNOWN:访问被拒绝:通道 [contentbackchainchannel] 创建者组织

    我已经与两个组织建立了结构网络 协调者组织和参与者组织 使用orchestratororg的用户 我可以调用或查询链代码 但是当尝试使用participantorg的用户查询时 我收到如下错误 错误 2 未知 访问被拒绝 通道 conten
  • constexpr 默认默认构造函数

    如果我想声明我的 Clang 3 8 和 GCC 5 3 我会收到编译器错误default ed 默认构造函数为constexpr 根据this https stackoverflow com questions 20810378 shou
  • google action包如何定义自定义槽类型?

    您好 这是一个关于 google home action sdk gactions exe 的问题 at https developers google com actions reference rest Shared Types Que
  • Angular Material - 设置调色板

    我正在尝试结合材料设计建立一个 Angular 项目 我的 package json 的一部分如下所示 dependencies angular2 material button 2 0 0 alpha 3 angular2 materia
  • 如何在两台电脑之间共享svn仓库

    我的工作站上有 SVN 存储库 我在工作站和笔记本电脑上都使用它 在工作站上 我可以在本地访问存储库 但在笔记本电脑上 我必须连接互联网才能访问存储库 这不方便 因为我无法在飞机 火车和其他无互联网的地方工作 我想比较修订等 在笔记本电脑上
  • 如何获取mysql中两个日期之间的月份列表

    我必须获取 mysql 中两个日期之间的月份列表 For Example My Input is From date 23 01 2013 To Date 01 04 2014 Output Should be Jan 2013 Feb 2
  • 验证错误:ul 不允许作为元素 span 的子元素

    我不明白为什么 WC3 验证器将此 HTML 标记为无效 它报告的错误是 在此上下文中 不允许元素 ul 作为元素 span 的子元素 抑制该子树中的更多错误 我正在使用 HTML5 此代码用于面包屑 span class bread ul
  • 如何以编程方式显示“清除默认值”?

    现在我正在开发一个家庭启动器应用程序 我想清除默认家庭启动器的默认设置 例如 三星主页 即 我想展示Settings gt Applications gt Manage Application gt Samsung Home gt clea
  • Swift:未定义的符号:iTunesApplication

    我现在正在尝试创建 Swift OS X 应用程序 但发现使用 ScriptingBridge 很困难 我包含了正确的 iTunes h 文件 并且当我将 iTunesApplication 写入类型时 Xcode 没有给出任何错误 但是
  • eclipse:链接资源的位置无效

    我尝试链接一个项目文件夹 该文件夹是特殊的 vista 文件夹 appdata roaming user myproj 它显示了上面的错误消息 什么阻止这样做 我尝试以管理员身份运行 但它给出了相同的消息 当然 从appdata文件夹中出来
  • 具有多个约束的 PostgreSQL 更新插入

    我正在尝试在有两个约束的表上进行更新插入 一种是a列是唯一的 另一种是b c d和e列一起是唯一的 我不想要的是 a b c d 和 e 一起是唯一的 因为这将允许两行在 a 列中具有相同的值 如果违反第二个约束 唯一的 b c d e 则
  • MSSQL 和 PHP:“传递给 sqlsrv_query 的参数无效。”

    我正在尝试通过 PHP 运行一个非常简单的 MSSQL 更新语句 但收到一条错误消息 无效的参数已传递给 sqlsrv query 这是连接等级 http pastebin com 3j4zmHJY我正在使用 最相关的是查询功能 funct
  • 控制 Android NDK 中的编译器标志?

    我知道我可以使用LOCAL CFLAGS将参数传递给编译器 然而 ndk build正在我的后面插入选项LOCAL CFLAGS 因此它们优先 例如我想指定 Ofast but ndk build adds O2在我自己的标志之后 并且由于
  • 在Python中处理大型密集矩阵

    基本上 在 python 中存储和使用密集矩阵的最佳方法是什么 我有一个项目 可以生成数组中每个项目之间的相似性度量 每个项目都是一个自定义类 并存储一个指向另一个类的指针和一个表示它与该类的 接近度 的数字 目前 它在处理约 8000 个
  • 为什么 Linq Contains 会生成此 SQL?

    背景 我正在开发一个系统 用于清理内部客户列表并找出联系人的电子邮件地址 其中我们已经拥有该公司其他人的电子邮件地址 为了做到这一点 我有 简化的 3 个表 Contacts ID CompanyId Email Domain 电子邮件域名