LINQ到生成错误SQL的实体

LINQ到生成错误SQL的实体,linq,entity-framework,null,Linq,Entity Framework,Null,我正在过滤一个IQueryable,以返回字段UserId(可为null的int)设置为null的所有实体。查询生成不正确的SQL,因此失败——语句为 如下- var filtered = certificates.Where(c => !c.UserId.HasValue).Select(c => c.SubjectName); 生成的SQL是-- 知道世贸基金会在进行什么吗?想法很简单,我只想返回字段UserId为false的所有行。UserId可以为null,并且被查询的表有

我正在过滤一个IQueryable,以返回字段UserId(可为null的int)设置为null的所有实体。查询生成不正确的SQL,因此失败——语句为 如下-

var filtered = certificates.Where(c => !c.UserId.HasValue).Select(c => c.SubjectName);
生成的SQL是--

知道世贸基金会在进行什么吗?想法很简单,我只想返回字段UserId为false的所有行。UserId可以为null,并且被查询的表有三行与所描述的条件匹配,但是LINQ查询返回0


谢谢

也许你可以尝试一个更明确的选项

  var filtered = certificates.Where(c => c.UserId == null).Select(c => c.SubjectName);

我相信它不适用于您的原因是c.UserId有一个值,它只是null。您应该将其与null进行比较:

var filtered = certificates.Where(c => c.UserId == null).Select(c => c.SubjectName);

编辑:这里不小心有错误的if语句。

这是EF在确定查询不会返回任何结果时生成的查询类型。这样的查询最小化了数据库处理

EF怎么能这么肯定?仅当它知道数据库中的
UserId
不可为空时,才可以使用此选项。反过来,只有当
证书
(POCO类)中也有一个
用户
引用时,才能根据需要进行映射。寻找类似于

HasRequired(t => t.User).WithMany(t => t.Certificates)
EntityTypeConfiguration
中,或在
DbContext
中的
OnModelCreating
重写中。(在code first中,可以有一个必需的引用,而附带的primitive Id属性是一个可为空的类型。在edmx文件中,这不会验证)


因此,我认为如果数据库中的外键可以为空,则必须将
用户映射为可选。

我添加了这个答案,因为我花了相当长的时间试图诊断这个问题,也许它会帮助某些人

我使用的是EntityFramework6.1.3,注意到当我使用下面的查询时,它永远不会返回任何内容,即使数据库中有符合此条件的项

dbContext.Items.Where(n => n.TypeID == null)
当我查看它正在执行的查询时,它使用的是与op相同的命令:

SELECT 
CAST(NULL AS int) AS [C1], 
CAST(NULL AS int) AS [C2], 
CAST(NULL AS varchar(100)) AS [C3], 
FROM  ( SELECT 1 AS X ) AS [SingleRowTable1]
WHERE 1 = 0
我知道这意味着EF认为该字段永远不能为null,并返回一个空集。当我使用代码优先实体框架设计时,我查看了
tblItems
的模型声明,但没有发现任何问题,我甚至尝试将.Optional()添加到属性定义中,但运气不佳

事实证明,我没有在
tblType
侧正确配置
tblItems
tblType
之间的关系,并且在定义两个表之间的关系时使用了
.HasRequired()
而不是
.HasRequired()


摘要:如果正在使用此默认查询,并且该表与其他表有关系,请确保在模型中正确定义了关系的两侧。

在我的示例中,当EF(v6.4.0)确定结果为空时,此查询也会出现在探查器中。这只是一个简单得多的例子:

var productsIds = new List<int>(); var result = products.Where(p => productsIds.Contains(p.Id)).ToList();
我希望EF能进一步优化它,在这种情况下不做任何db查询,但我想最好什么都不做;)

-1:要求用户ID必须为null。另外,说c.UserId有一个值是非常奇怪的。这些是由EF转换为SQL的表达式树;在这一点上没有评估,这是绝对正确的。我们遇到了同样的问题。Db列已转换为nullable,但更改未传播到edm。有趣的是,我们只是通过搜索
[SingleRowTable1]
找到了这篇文章,因为我们在Profiler中看到了这个查询,并且有相同的WTF反应! var productsIds = new List<int>(); var result = products.Where(p => productsIds.Contains(p.Id)).ToList();
if (products.Any()) 
{
    var result = products.Where(p => productsIds.Contains(p.Id)).ToList();
}