Linq to SQL Join 允许空值,但我不想要

4
我已经编写了下面的查询来连接几个表格。但是由于某种不可思议的原因,la.UserProfileId具有可空性。
当我编写等效的SQL语句时,我现在得到0条记录,这是应该的。
var result = (from e in _ctx.Employees
                     join la in _ctx.LoginAudits on e.UserProfile.Id equals la.UserProfileId.Value
                     where la.LoginDate >= fromDate
                     && e.Client.Id == clientID
                     select new
                     {
                         la.Id,
                         employeeID = e.Id,
                         e.Client.DisplayName,
                         la.UserProfileId
                     }).ToList();

上述LINQ代码生成以下SQL。
exec sp_executesql N'SELECT 
1 AS [C1], 
[Extent2].[Id] AS [Id], 
[Extent1].[Id] AS [Id1], 
[Extent3].[DisplayName] AS [DisplayName], 
[Extent2].[UserProfileId] AS [UserProfileId]
FROM   [dbo].[Employees] AS [Extent1]
INNER JOIN [dbo].[LoginAudits] AS [Extent2] ON ([Extent1].[UserProfile_Id] = [Extent2].[UserProfileId]) OR (([Extent1].[UserProfile_Id] IS NULL) AND ([Extent2].[UserProfileId] IS NULL))
INNER JOIN [dbo].[Clients] AS [Extent3] ON [Extent1].[Client_Id] = [Extent3].[Id]
WHERE ([Extent2].[LoginDate] >= @p__linq__0) AND ([Extent1].[Client_Id] = @p__linq__1)',N'@p__linq__0 datetime2(7),@p__linq__1 bigint',@p__linq__0='2018-02-09 11:11:29.1047249',@p__linq__1=37

如您所见,它包括“OR (([Extent1].[UserProfile_Id] IS NULL) AND ([Extent2].[UserProfileId] IS NULL))”。

这正好与我想要的相反。我该如何使其执行普通的内部连接而不是尝试允许空值?

我能够通过在WHERE子句中添加&& la.UserProfileId!= null来解决此问题,但理想情况下,我希望将JOIN表现得像普通的INNER JOIN,而不是尝试预测我没有请求的内容。


模型中的字段是否可为空?如果是,尝试使用 e.UserProfile.Id.Value 代替? - Steve Greene
1个回答

4
这正好与我的需求相反。我该如何使其执行普通的内连接而不是尝试允许空值?原因在于,在C#中,null == null的结果为true,而在SQL中则评估为NULL(基本上被处理为FALSE)。因此,EF试图模拟C#行为,以便获得与在LINQ to Objects中��行相同查询时一样的结果。这是EF6的默认行为。它由UseDatabaseNullSemantics属性控制,因此如果你想使用SQL行为,应在DbContext派生类构造函数或外部设置为true
[dbContext.]Configuration.UseDatabaseNullSemantics = true;

但这还不够。 它影响所有比较运算符,但他们忘记将其应用于连接。 解决方案是不使用LINQ join操作符,而是相关的where(EF足够智能,可以将其转换为SQL JOIN)。

因此,除了将UseDatabaseNullSemantics设置为true外,还需替换:

join la in _ctx.LoginAudits on e.UserProfile.Id equals la.UserProfileId

使用

from la in _ctx.LoginAudits where e.UserProfile.Id == la.UserProfileId

你将得到所需的 INNER JOIN


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接