Linq到实体DefaultIfEmpty [英] Linq to Entities DefaultIfEmpty
问题描述
我正在通过第三方ADO.NET提供程序将EF 4用于PostgreSQL.在我的数据源中,没有任何根据该连接条件匹配项目的项目行.出于这个原因,我希望查询1基于空引用异常而失败.但是,它完成了,并为il上的每个属性提供了默认的值类型. item_display_name是一个字符串,因此ilName设置为null. ilStartDate设置为DateTime的默认值. x.il.item_id和x.il.item_line_no均为0.
I'm using EF 4 to PostgreSQL using a 3rd party ADO.NET provider. In my data source, I have no item lines that match items based on this join condition. For this reason I expect query 1 to fail based on a null reference exception. However, it completes and gives me value type defaults for each of the properties on il. item_display_name is a string so ilName is set to null. ilStartDate is set to DateTime's default. x.il.item_id and x.il.item_line_no are both 0.
var query1 =
_db.items
.GroupJoin(_db.item_line.Where(x => x.start_date == selectedStartDate), x => x.item_id, il => il.item_id, (x, ilgroup) => new { x, ilgroup })
.SelectMany(x => x.ilgroup.DefaultIfEmpty(), (x, il) => new { x.x, il })
.Select(x =>
new
{
itemId = x.x.item_id,
ilName = x.il.item_display_name,
ilStartDate = x.il.start_date,
ilItemId = x.il.item_id,
orderLine = x.il.item_line_no});
但是,如果我通过在Select之前对结果调用ToArray来强制执行,则会得到空引用异常.
However, if I force execution by calling ToArray on my results before the Select, I then get my null reference exception.
var query2 =
_db.items
.GroupJoin(_db.item_line.Where(x => x.start_date == selectedStartDate), x => x.item_id, il => il.item_id, (x, ilgroup) => new {x, ilgroup})
.SelectMany(x => x.ilgroup.DefaultIfEmpty(), (x, il) => new {x.x, il}).ToArray()
.Select(x =>
new
{
itemId = x.x.item_id,
ilName = x.il.item_display_name,
ilStartDate = x.il.start_date,
ilItemId = x.il.item_id,
orderLine = x.il.item_line_no});
据我了解,DefaultIfEmpty应该返回该类型的默认值.我的类型显然是引用类型,那么为什么查询1不会失败?
To my understanding, DefaultIfEmpty should return the default for that type. My type is clearly a reference type, so why won't query 1 fail?
推荐答案
这是因为第一个查询已完全转换为SQL.对于空的对象",SQL与C#不同.在SQL中,完全可以写类似
This is because the first query is completely translated into SQL. SQL is different than C# when it comes to null "objects". In SQL it is perfectly OK to write something like
SELECT o.Date, ol.Number FROM Order o LEFT JOIN OrderLine ol ON ... (etc.)
当有Order
个不带OrderLine
的时,它不会崩溃.此处ol
上没有空引用异常. SQL只会为缺少订单行的ol.Number
输出空值.
It won't crash when there are Order
s without OrderLine
s. No null reference exception on ol
here. SQL just outputs null values for ol.Number
where order lines are missing.
因此,在 first 语句中,匿名类型是直接从从SQL获取的值中构建的.整个表达式x.il.item_display_name
由DbDataReader
的输出填充,当不存在ilgroup
时为空.
So in the first statement the anonymous type is built directly from values obtained from SQL. The whole expression x.il.item_display_name
is populated by output from a DbDataReader
, which is null when no ilgroup
is present.
在 second 语句中,首先在内存中构建一个对象数组,该对象数组由x
和il
对组成,其中一些对不包含il
(il
为空) .现在,匿名类型是从对象数组构建的,表达式x.il.item_display_name
试图从一些不存在的对象中读取item_display_name
.
In the second statement, first an array of objects is built in memory, consisting of x
and il
pairs, some which have no il
(il
is null). Now the anonymous type is built from the object array and the expression x.il.item_display_name
tries to read item_display_name
from some non-existing objects.
这篇关于Linq到实体DefaultIfEmpty的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!