.net 为什么EF在Include操作中抛出LastOrDefault错误,而在OrderByDescending操作中却没有?

hjzp0vay  于 2023-05-30  发布在  .NET
关注(0)|答案(2)|浏览(218)

我需要从Monitoring表中获取最后一条记录

return await _context.Applications
                .Include(s => s.Elements)
                .ThenInclude(d => d.Monitoring.LastOrDefault())
                .ToListAsync();

但是EF抛出一个错误:

System.InvalidOperationException: The expression 's.Elements.AsQueryable().LastOrDefault()' is invalid inside an 'Include' operation, since it does not represent a property access: 't => t.MyProperty'. 
To target navigations declared on derived types, use casting ('t => ((Derived)t).MyProperty') or the 'as' operator ('t => (t as Derived).MyProperty'). 
Collection navigation access can be filtered by composing Where, OrderBy(Descending), ThenBy(Descending), Skip or Take operations.

但是当我用OrderByDescending执行相同的请求时,它工作得很好。

return await _context.Applications
                .Include(s => s.Elements)
                .ThenInclude(d => d.Monitoring.OrderByDescending(c => c.Id))
                .ToListAsync();

谁能解释一下使用 OrderByDescendingLastOrDefault 之间的区别?
在这种情况下,如何获得最后一项是正确的?

e5nqia27

e5nqia271#

不同的是,支持一个是实施和另一个-是不是。这记录在EF核心文档中,用于筛选包括:
支持的操作包括:WhereOrderByOrderByDescendingThenByThenByDescendingSkipTake
因此,您可以:

return await _context.Applications
    .Include(s => s.Elements)
    .ThenInclude(d => d.Monitoring.OrderByDescending(c => c.Id).Take(1))
    .ToListAsync();

这将导致Monitoring最多有一个最大Id的元素。

rggaifut

rggaifut2#

异常几乎完美地描述了您的问题。IncludeThenInclude不能接受object,这是LastOrDefault()的结果。
当你调用OrderByDescending时,它仍然是一个属性访问器,可以通过EF转换为SQL代码--同时,它也是一个指向集合的指针。
尝试将代码直接转换为SQL代码,如何使用单行执行“JOIN”(这是LastOrDefault尝试执行的)?- 你不能
LastOrDefaultOrderByDescending之间的区别在于,第一个结果是一条记录,而另一个结果是一个集合,按您的偏好排序。

相关问题