【问题标题】:Include not working in LINQ query but works in LINQ Fluent API包括不在 LINQ 查询中工作,但在 LINQ Fluent API 中工作
【发布时间】: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


【解决方案1】:

这只是一个猜测:由于您在SubscribersBenefits 中都有Datas,因此您可能没有查询到正确的模型/实体...您可以尝试确认实体类型如下所示(假设 Benefit 是您的实体类型)。

var list1 = (from s in _context.Subscribers
               .Include(s => s.Dates)
               .Include(s => s.Benefits)
               .ThenInclude(b => (b as Benefit).Dates)
               where s.Id == 13643
               select new { benefits = s.Benefits }).ToList();

var list2 = _context.Subscribers
           .Include(s => s.Dates)
           .Include(s => s.Benefits)
           .ThenInclude(b => (b as Benefit).Dates) // <-- I suggest renaming s to b
           .Where(s => s.Id == 13643)
           .Select(s => new { benefits = s.Benefits}).ToList();

【讨论】:

  • 抱歉,我确实在我的代码中使用了b,而不是s——我已经更新了我的代码以反映这一变化。我会尝试演员阵容,看看是否有什么不同。
  • 铸造 (b as Benefit) 没有帮助。我还尝试删除.Include(s =&gt; s.Dates)(订阅者日期),但这也无济于事。福利仍然会在没有日期的情况下返回。
  • Casting 在类似的情况下帮助我。
猜你喜欢
  • 2012-08-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-20
  • 1970-01-01
相关资源
最近更新 更多