首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Linq to Entities DefaultIfEmpty

Linq to Entities DefaultIfEmpty
EN

Stack Overflow用户
提问于 2012-10-31 04:47:20
回答 2查看 1K关注 0票数 1

我正在使用EF4通过第三方ADO.NET提供商进行PostgreSQL。在我的数据源中,我没有与基于此联接条件的项目相匹配的项目行。由于这个原因,我预计查询1会因为空引用异常而失败。但是,它完成了操作,并为il上的每个属性提供了缺省值类型。item_display_name是一个字符串,因此ilName被设置为null。ilStartDate设置为DateTime的默认值。x.il.item_id和x.il.item_line_no均为0。

代码语言:javascript
复制
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});

但是,如果我在选择之前通过对结果调用ToArray来强制执行,那么我就会得到空引用异常。

代码语言:javascript
复制
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应该返回该类型的默认值。我的类型显然是引用类型,那么为什么query 1不会失败呢?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-10-31 05:53:05

这是因为第一个查询被完全翻译成SQL。当涉及到空“对象”时,SQL与C#是不同的。在SQL中,完全可以编写类似这样的代码

代码语言:javascript
复制
SELECT o.Date, ol.Number FROM Order o LEFT JOIN OrderLine ol ON ... (etc.)

当存在没有OrderLine%s的Order%s时,它不会崩溃。在这里的ol上没有空引用异常。对于缺少订单行的ol.Number,SQL只输出null值。

因此,在SQLfirstSQL语句中,匿名类型是直接从从获得的值构建的。整个表达式x.il.item_display_nameDbDataReader的输出填充,如果不存在ilgroup,则输出为null。

在的第二个语句中,首先在内存中构建一个对象数组,由xil对组成,其中一些对没有il (il为null)。现在,匿名类型是从object数组构建的,表达式x.il.item_display_name尝试从一些不存在的对象中读取item_display_name

票数 2
EN

Stack Overflow用户

发布于 2012-10-31 04:53:01

这是Entity Framework的一个棘手的特性。当您执行整个查询时,实际上并没有命中数据库。EF只有在你执行ToArray、ToList等操作时才会访问数据库。

在第一个查询中,如果将ToArray()放在末尾,就应该得到NullReference。虽然您实际上并没有执行ToArray,但是当您执行ToList()或ToArray()时,您将只构造要运行的查询。

看看这篇文章:Am I hitting the database?

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13147341

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档