Ton*_*ile 6 c# null entity-framework left-join
我在Entity Framework模型中看到了一种奇怪的行为.我有一个看起来像这样的查询:
var rows = ( from alarm in context.Alarms
join temp in context.ListDetails on alarm.ListDetailId equals temp.ListDetailId into entries from entry in entries.DefaultIfEmpty()
join read in context.Reads on alarm.ReadId equals read.ReadId
join plate in context.Images on alarm.ReadId equals plate.ReadId
where alarm.IActive == 1 && ! alarm.TransmittedAlarm
where read.IActive == 1
where plate.IActive == 1 && plate.ImageTypeId == 2
select new { alarm, entry, read, plate } ).ToArray();
Run Code Online (Sandbox Code Playgroud)
该查询按列名称按字母顺序返回所有列.事实证明,对于结果集中的几行,此列为NULL.当我在调试器中展开rows变量时,我看到整行是空的!
编辑:一些澄清.
通过"第一列",我的意思是第一行的第一列,即"SELECT A,B,C FROM ...",我的意思是A.实际上,实体框架构建的查询返回所有的连接结果集中的列按字母顺序排列,第一个按字母顺序排列可为空,对于某些行为空.
有问题的列不是主键; 如果它是主键,则不能为空.
当Entity Framework将返回数据的行处理为对象时,它会查看每行中第一列的值.如果该列为null,则为该行返回null,而不是具有与该列对应的属性设置为null的对象.
我不相信这与左外连接有任何关系; 只是我的查询使用了一个.但是,我没有做任何测试来验证这一点,所以这只是一个假设.
有没有人见过这个?有人有解决方法吗?
托尼
我可以确认我遇到了同样的问题:当EF形成的SQL查询null在结果的第一列中时,它返回null而不是实体.这意味着完全遵循:
using (var dc = new MyDbContext())
{
var q = dc.Lands; //Lands is DbSet<Land>
q = q.Where(criteria); //this leads to SQL query returning null in first column, confirmed by profiler
var t = q.Single(); //t is now null
}
Run Code Online (Sandbox Code Playgroud)
如果我们采用另一个不会导致null第一列的标准,t则是正常的非null实体.
在我看来,它是EF中某种模糊的行为/错误.
更新
经过几个小时的探测,我发现了以下行为.EF确实返回null了NULL第一列结果中的entites (它打破了预期的行为),但它有几个关于首先放入选择列表的列的概念.因此,在使我的模型与我的数据库状态(这意味着表示所有NULLABLE数据库列并替换required导航属性optional)完全一致之后- 我正在使用Code First,所以有很多地方需要明确数据库 - 我已经设法让它工作.
这意味着您应该检查模型的商店级定义(取决于您使用的范例,基于设计器,或基于代码,它将是不同的地方)与您的数据库.
DefaultIfEmpty您在加入中使用。它的意思是
如果其中没有
entries与连接条件 (alarm.ListDetailId equals temp.ListDetailId) 匹配的项目,我希望您将类型的单个默认值ListDetail(即null)放入 中entries。
在这种情况下,EF 会生成一个LEFT JOIN. 事实上,这段代码是使用 Linq2Sql 或 EF 生成 a 的众所周知的方法LEFT JOIN。
如果表中没有行符合条件,则该LEFT JOIN语句将为表的所有列选择值。事实上,唯一重要的列是实体的 PK 列。EF 检查 PK 值是否为,确定不存在实体并放入。然后您将其作为结果的属性值。NULLJOINNULLnullentriesnullentry