当前位置: 首页 > 面试题库 >

防止LINQ到实体联接中的NULL检查

富锦
2023-03-14
问题内容

我们有一个名为的表格Student。该表有一个名为的字段Homeroom,其中的值是该学生所在房间的房间号。该值可以为空。

我们还有第二张桌子叫Staff。该表还具有一个字段,Homeroom用于指示教师分配给哪个教室。该值可以为空。

但是,当学生的Homeroomnull为空时,Staff不应返回记录。

我们以前利用了以下事实:在SQL中检查两个空字段是否相等总是返回false。通过SQL,这就是我们获取所需数据的方式:

SELECT STUDENT.ID, STAFF.NAME as [Homeroom Teacher]
FROM STUDENT
LEFT OUTER JOIN STAFF ON
    STAFF.BUILDING = STUDENT.BUILDING AND
    STAFF.HOMEROOM = STUDENT.HOMEROOM

学生将被归还,但没有老师。

我们正在使用带有Code First POCO对象的实体框架。因此,我们有一个Student对象和一个Staff对象。当我们在LINQ中重新创建此SQL时:

from student in repo.GetStudents()
join homeroomTeacher in repo.GetStaff()
    new { student.Building, Room = student.Homeroom }
     equals new { homeroomTeacher.Building, Room = homeroomTeacher.Homeroom }
into roj2
from homeroomTeacherRoj in roj2.DefaultIfEmpty()
select student.Id, homeroomTeacherRoj.Name;

生成的SQL在两个Homeroom字段中都包含NULL检查:

SELECT STUDENT.ID, STAFF.NAME
FROM STUDENT AS [Extent1]
LEFT OUTER JOIN [dbo].[STAFF] AS [Extent2] ON 
    ([Extent1].[BUILDING] = [Extent2].[BUILDING]) AND 
    (
        ([Extent1].[HOMEROOM] = [Extent2].[HOMEROOM]) OR 
        (([Extent1].[HOMEROOM] IS NULL) AND ([Extent2].[HOMEROOM] IS NULL))
    )

这将返回学生以及未定义教室的所有职员。根据我们先前编写SQL语句的方式,这不是我们想要或期望的。

解决这个问题的一个明显方法是确保我们不包括没有家室的员工(join homeroomTeacher in repo.GetStaff().Where(staff => staff.Homeroom != null)。但是LINQ中还有另一种方法可以防止在加入字段时对字段进行空检查吗?


问题答案:

如果将联接移到where子句中,则DbContext对象上的以下设置将关闭(引入的EF 6)NULL检查行为:

Context.Configuration.UseDatabaseNullSemantics = true;

因此,要在where子句中“加入”,您可以将查询分为2个IQueryable对象

var subquery = from homeroomTeacher in repo.GetStaff()
               where ...
               select homeroomTeacher;

var query = from student in repo.GetStudents()
            where subquery.Any(homeroomTeacher => 
                 homeroomTeacher.xxx == student.xxx) -- simplified join for demo code
            select student;

因此,引入了UseDatabaseNullSemantics来修复此行为,但看起来他们忘记了JOIN语义,而仅将其应用于WHERE语义。

此原始陈述是错误的-EF 4.3.1表现出相同的JOIN行为:

从本质上讲,这意味着EF 6的某些结果集与以前的版本相比有所不同。在我看来,这是一笔大交易!!!因为它在我的工作解决方案中引入了错误!

我在Codeplex上提出了一个问题:https
://entityframework.codeplex.com/workitem/2006



 类似资料:
  • 问题内容: 我用多个(包括一个)编写了这个SQL请求。 它给了我预期的结果 。 但是,“ Id就像此请求的Linq等效项一样,将其放在应用程序的数据访问层中。 我尝试了类似的东西: 我试图适应这个问题,但我无法弄清楚。我对分组子请求的内部迷失了。 谁能解释我哪里错了? 专家提示:如果有人可以用lambda表达式编写等效项,则可获赠积分 问题答案: 要将SQL转换为LINQ查询理解: 将子选择转换为

  • 问题内容: 我有一个连接到另一个的Hibernate实体:。在数据库中,我有一列在上具有外键约束。假设我正在延迟加载,那么当我加载的实例时,我希望能够在不引起表查找的情况下进行访问。 我希望返回的代理能够完成请求,因为它已经从列中加载了孩子的ID 。但是,我在桌上看到另一个查询。 为什么需要这个额外的查询,我该如何避免呢?在这种情况下,我只对外键ID感兴趣,而不希望加载整个行。 类: 表格: 问题

  • 问题内容: 我有一些用户输入。在我的代码中,我确保对以下符号进行转义: OWASP指出还有更多的字符可以转义。 对于属性,我做了另一种转义: 这样可以确保所有属性都用“括起来。”这样就可以确定自己的html属性,而不是HTML本身。 问题答案: 我也使用OWASP(ESAPI)库,以转义不同显示类型的字符串,请使用: HTML(假设为jsp) 更新 ( 2017 ) 由于ESAPI编码器被认为是旧

  • 问题内容: 我在TSQL中有以下查询 我在实体框架中有以下查询 当我尝试编译它时,我得到 错误3名称“ p”不在“等于”左侧的范围内。考虑在“等号”的任一侧交换表达式。 错误4名称“链接”不在“等于”右侧的范围内。考虑在“等号”的任一侧交换表达式。 问题答案: 错误究竟在说什么 应该 完整的代码

  • 我有下面这个例子,感觉可读性不是很好。由于getStudents()可能为null,getTests()也可能为null,所以我必须进行大量检查。我必须执行isStudentsAvailable()和isStestAvailable()。 我如何将这个例子转移到不需要那些检查的lambda表达式中呢?会很乐意得到一些暗示。谢谢

  • 我目前正在尝试使用KStream到KTable的连接来执行Kafka主题的充实。对于我的概念证明,我目前有一个Kafka流,其中有大约600,000条记录,它们都有相同的键,还有一个KTable,它是从一个主题创建的,其中KTable主题中的键与创建KStream的主题中的600,000条记录中的键匹配。 当我使用左联接(通过下面的代码)时,所有记录在ValueJoiner上都返回NULL。 下面