c# - Entity Framework linq 到 sql 转换问题

标签 c# entity-framework linq-to-sql entity-framework-6

与 EF6/linq to SQL 进行斗争以获得期望的结果。我不想在数据库中创建 View 。

关于为什么 EF 以这种方式转换它或者如何欺骗它有什么想法吗?

我的 linq 谓词:

.Where(x => 
   (x.AccountId == viewModel.AccountId || x.AccountId == null)
   && (x.CompanyId == viewModel.CompanyId || x.Company == null)
   && (x.FacilityId == viewModel.FacilityId || x.FacilityId == null)
)

生成的SQL:

WHERE 
   (([Extent1].[AccountId] = 1) 
    OR (([Extent1].[AccountId] IS NULL) AND (1 IS NULL)) 
    OR ([Extent1].[AccountId] IS NULL)
   ) 
   AND 
   (
    ([Extent1].[CompanyId] = 11) 
    OR (([Extent1].[CompanyId] IS NULL) AND (11 IS NULL)) 
    OR ([Extent2].[Id] IS NULL)
   ) 
   AND 
   (
    ([Extent1].[FacilityId] = 1) 
    OR (([Extent1].[FacilityId] IS NULL) AND (1 IS NULL)) 
    OR ([Extent1].[FacilityId] IS NULL)
   )  
   AND 
   (
    ([Extent1].[FacilityId] = 1) 
    OR (([Extent1].[FacilityId] IS NULL) AND (1 IS NULL))
   )

我认为我会得到的 SQL,并且确实达到了预期的结果:

WHERE 
(
    ([Extent1].[AccountId] = 1) 
    OR ([Extent1].[AccountId] IS NULL)
) 
AND 
(
    ([Extent1].[CompanyId] = 11) 
    OR ([Extent2].[Id] IS NULL)
) 
AND 
(
    ([Extent1].[FacilityId] = 1) 
    OR ([Extent1].[FacilityId] IS NULL)
) 

最佳答案

请尝试:

.Where(x => 
   (x.AccountId == (int)viewModel.AccountId || x.AccountId == null)
   && (x.CompanyId == (int)viewModel.CompanyId || x.Company == null)
   && (x.FacilityId == (int)viewModel.FacilityId || x.FacilityId == null)
)

或者:

var accountId = viewModel.AccountId.GetValueOrDefault();
var companyId = viewModel.CompanyId.GetValueOrDefault();
var facilityId = viewModel.FacilityId.GetValueOrDefault();
...
...
.Where(x => 
   (x.AccountId == accountId || x.AccountId == null)
   && (x.CompanyId == companyId || x.Company == null)
   && (x.FacilityId == facilityId || x.FacilityId == null)
)

您的原始查询引用可为 null 的类型作为参数,因此,EF 需要生成一个谓词,该谓词在参数值为 null 时能够按预期工作,这就是为什么您会看到额外的 ([Extent1] .[AccountId] IS NULL) AND (@p__linq__0 IS NULL)。通过将参数转换为查询中的下划线类型(在本例中为 System.Int32),EF 将不会认为需要执行此操作,因为它“认为”您的参数不能为 null。

所有这些都是必需的,因为默认情况下您的 SQL 服务器连接将启用 ANSI_NULLS 选项,这意味着与 NULL 的任何比较都将是 false,这就是为什么EF 需要生成这个额外的逻辑(IS NULL 运算符),以确保当参数值为 null 时可以获得可预测的结果。

您可以尝试此操作来查看 ANSI_NULLS 的实际效果:

SET ANSI_NULLS ON;
SELECT 1 WHERE NULL = NULL;

SET ANSI_NULLS OFF;
SELECT 1 WHERE NULL = NULL;

关于c# - Entity Framework linq 到 sql 转换问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54472964/

相关文章:

c# - LINQ to SQL where 子句返回零

c# - sql——变量存储

c# - 追踪仅在一个客户的盒子上可见的内存泄漏 (C#) 的最佳方法

c# - 一对多和递归关系 - 要设置的强制值

c# - 在 IEquatable 上重写等于

c# - Linq 在不传递上下文的情况下编译查询

c# - 是什么导致此代码中的空引用异常?

c# - 如何将子元素作为解码字符串添加到 XElement?

c# - Select LINQ 的最佳返回类型是什么

.net - 使用编译查询时我们还需要存储过程吗?