LINQ到生成错误SQL的实体
我正在过滤一个IQueryable,以返回字段UserId(可为null的int)设置为null的所有实体。查询生成不正确的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,并且被查询的表有
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();
}