【发布时间】:2019-01-09 21:14:37
【问题描述】:
问题
我有一个使用Include 包含一些导航属性的LINQ 查询(针对实体框架)。其中一个属性使用ThenInclude 来包含它自己的属性集合。当我运行查询时,第一级属性包含在主对象中,但子集合(使用 ThenInclude 的那个)始终为空。
但是,如果我将查询更改为使用 Fluent API 表单,则查询可以正常工作,并且实际上包含子集合。为什么这适用于 Fluent 表单而不是普通的 LINQ 查询?
示例
//FAIL - This returns Benefits but Benefits.Dates.Count = 0 on all Benefits
var list1 = (from s in _context.Subscribers
.Include(s => s.Dates)
.Include(s => s.Benefits)
.ThenInclude(b => b.Dates)
where s.Id == 13643
select new { benefits = s.Benefits }).ToList();
//SUCCESS - This returns Benefits and Benefits.Dates.Count is > 0 on the ones with Dates
var list2 = _context.Subscribers
.Include(s => s.Dates)
.Include(s => s.Benefits)
.ThenInclude(b => b.Dates)
.Where(s => s.Id == 13643)
.Select(s => new { benefits = s.Benefits}).ToList();
我误认为这些查询应该给出相同的输出吗?
更新
我刚刚尝试使用 LINQ 手动链接事物,我能够获得包括福利日期 - 当然,它不是苹果对苹果,因为结果集不同,但重点是 Include(b => b.Dates) 在这种情况下似乎有效.
var list3 = (from s in _context.Subscribers.Include(s => s.Dates)
join b in _context.Benefits.Include(b => b.Dates) on s.Id equals b.SubscriberId
select new {benefits = b}).ToList();
我开始怀疑ThenInclude() 是否可以在何时/何地使用更严格一些?
更新 2
我刚刚在我的调试输出窗口中注意到一个警告,该警告将我引导至this link about ignored includes。这似乎是在正确的轨道上,因为调试输出清楚地表明这些包含被忽略了。
不过,没有意义的是,我实际上在两个示例中都选择了匿名,而其中只有一个似乎忽略了包含。为什么是一个而不是另一个?
【问题讨论】:
-
很可能是一个错误,但只是想知道,您为什么选择匿名对象而不是
s => s.Benefits?此外,Dates的第一个Include被省略,因为它没有被使用。你可以使用_context.Benefits.Include(x => x.Dates).Where(x => x.SubscriberId == 13643).ToList() -
所以我所追求的查询要复杂得多,但是当它不起作用时,我开始将其简化为只需要包含的部分。所以,虽然我现在没有使用
Subscriber.Dates,但一旦我解决了这个简单的模型,我就会使用它。 (选择匿名也是如此——在我的示例中不是必需的,但在最终查询中是必需的) -
使用 EF 编写复杂查询时要记住的一点是性能... EF 将您的 linq 查询转换为 SQL,但它可能不如您自己的 SQL 高效。就我个人而言,我不会使用 LINQ to SQL 来编写复杂的查询……您可能会编写更高效的 SQL。见点#3 here
标签: c# linq ef-core-2.1