如果该行中的第一列为null,则实体框架为行返回null

时间:2012-04-18 15:37:23

标签: c# entity-framework null 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();

查询按列名称按字母顺序返回所有列。事实证明,对于结果集中的几行,此列为NULL。当我在调试器中展开rows变量时,我看到整行是空的!

编辑:一些澄清。

“第一列”是指第一行的第一列,即“SELECT A,B,C FROM ...”,我的意思是A.实际上,实体框架构建的查询返回联接结果集中的所有列按字母顺序排列,第一个按字母顺序排列可为空,对于某些行为空。

有问题的列不是主键;如果它是主键,则不能为空。

当Entity Framework将返回数据的行处理为对象时,它会查看每行中第一列的值。如果该列为null,则为该行返回null,而不是具有与该列对应的属性设置为null的对象。

我不相信这与左外连接有任何关系;只是我的查询使用了一个。但是,我没有做任何测试来验证这一点,所以这只是一个假设。

以前有人见过这个吗?有人有解决方法吗?

2 个答案:

答案 0 :(得分:6)

我可以确认我遇到了同样的问题:当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
}

如果我们采用另一个不会在第一列中生成null的条件,则t是正常的非null实体。

在我看来,这是EF中某种模糊的行为/错误。

<强>更新

经过几个小时的探索后,我发现了以下行为。对于在结果的第一列中具有null的entites,它确实返回NULL(这会破坏预期的行为),但它有几个关于在选择列表中首先放入哪一列的概念。因此,在使我的模型与我的数据库状态完全一致(这意味着表示所有NULLABLE数据库列并用required替换optional导航属性)之后 - 我正在使用Code First,所以'有很多地方要明确数据库 - 我已经设法让它发挥作用。

这意味着您应该检查模型的商店级定义(取决于您使用的范例,基于设计器,或基于代码,它将是不同的地方)与数据库。

答案 1 :(得分:1)

您在加入中使用DefaultIfEmpty。这意味着

  

如果entries中没有与加入条件(alarm.ListDetailId equals temp.ListDetailId)匹配的项目,我希望您输入一个类型ListDetail的默认值({{1} }}}进入null

在这种情况下,EF生成entries。实际上,这段代码是用Linq2Sql或EF生成LEFT JOIN的众所周知的方法。

如果表中没有行与LEFT JOIN条件匹配,LEFT JOIN语句会为表的所有列选择NULL值。实际上,唯一重要的列是实体的PK列。 EF检查PK值是否为JOIN,确定不存在实体并将NULL放入null。然后,您将此entries作为结果的null属性值。