Entity framework core 在子查询中使用FirstOrDefault

Entity framework core 在子查询中使用FirstOrDefault,entity-framework-core,ef-core-2.2,Entity Framework Core,Ef Core 2.2,我们的一些LINQ到SQL查询存在重大性能问题 我们有一个案例表,在CaseStatus上有一对多关系(关系表是CaseStatus) 尽管我们希望跟踪一个案例的所有状态,但只有最后一个状态才真正有价值 我们正在构建一个如下所示的查询: IQueryable<Case> results = Repository.GetFullList(); // Returns a Queryable if(filter.OnlyOpen){ results = results

我们的一些LINQ到SQL查询存在重大性能问题

我们有一个案例表,在CaseStatus上有一对多关系(关系表是CaseStatus) 尽管我们希望跟踪一个案例的所有状态,但只有最后一个状态才真正有价值

我们正在构建一个如下所示的查询:

IQueryable<Case> results = Repository.GetFullList(); // Returns a Queryable

if(filter.OnlyOpen){
   results = results
      .Where(c => c.CaseCaseStatusses.Any() 
               && c.CaseCaseStatusses.OrderByDescending(cs => cs.Timestamp).FirstOrDefault().Status.IsClosed != true);
}

results.Select(x => Dto(x)).ToList();
IQueryable results=Repository.GetFullList();//返回一个可查询的
如果(过滤器。仅限打开){
结果=结果
.Where(c=>c.caseStatuses.Any()
&&c.caseStatuses.OrderByDescending(cs=>cs.Timestamp.FirstOrDefault().Status.IsClosed!=true);
}
results.Select(x=>Dto(x)).ToList();
基本上,我们想知道最后一个状态是否有一个属性“IsClosed==true”

当我通过SQL事件探查器监视数据库时,我可以看到在点击Select语句时(而不是之前)正在查询数据库。(如预期) 但在执行查询时,我可以看到针对每个案例的select查询:

SELECT [cs0].[Id], [cs0].[CaseId], [cs0].[Note], [cs0].[ShowOnClientPage], [cs0].[StatusId], [cs0].[TimestampUTC], [cs.Status0].[IsClosed] 
FROM [CaseCaseStatusses] AS [cs0] 
INNER JOIN [CaseStatusses] AS [cs.Status0] ON [cs0].[StatusId] = [cs.Status0].[Id]
WHERE [cs0].[CaseId] = <CaseId>
选择[cs0].[Id],[cs0].[CaseId],[cs0].[Note],[cs0].[shownclientpage],[cs0].[StatusId],[cs0].[timestastUTC],[cs.Status0].[IsClosed]
从[CaseStatuses]到[cs0]
在[cs0].[StatusId]=[cs.Status0].[Id]上将[CaseStatuses]作为[cs.Status0]的内部联接
其中[cs0].[CaseId]=
因为我们的案例表中有8000多条记录,所以它会执行8000条以上的select语句。。。而我们希望执行一个查询。在EFCore中,这种行为发生了变化吗?我可以发誓我以前做过,它会输出一个查询(当然,这是一个大的不可读的查询,而不是EFCore)


有没有其他(更好的)方法来执行此类查询?

尝试此查询,它应该适用于任何EF版本

var结果=
从r到结果
从r.CaseSes中的c
.OrderByDescending(cs=>cs.Timestamp)
.采取(1)
c!=null&&c.Status.IsClosed!=真的
选择r;

您首先想做什么<代码>子查询中的第一个或默认值是您认为解决实际问题的方式,而不是问题本身。子查询中的
选择TOP 1
也不一定是基于第一个或最后一个值进行筛选的最有效方法。最后,调用
caseStatuses.Any()
c.caseStatuses….
是自相矛盾的。并且
IsClosed!=如果结果可能为
NULL,则为true
将导致更多问题幸运的是,答案取决于EF核心版本。1.x/2.x使用客户机评估,在许多情况下会遇到前面提到的N+1查询问题。从3.x/5.x中的另一面来看,它可能只是拒绝转换并抛出异常。所以没有一般性的建议。LINQ-to-WhateVerdabase既不是魔术,也不是SQL的替代品。这意味着使用ORM进行查询更容易。反过来,ORM的作用是加载对象,而不是像您尝试执行的那样执行报告查询。在SQL中,您可以使用(…)上的
first\u value()或
last\u value()获取结果集中的第一个或最后一个值。如果您想查找最后状态未关闭的记录,您可以使用
last\u VALUE(IsClosed)OVER(ORDER BY Timestamp desc)
@PanagiotisKanavos您多次分享这一观点,我不同意。LINQ和SQL都是查询语言,LINQtoSomeDB应该是强类型面向对象SQL的替代品。一些实现未能做到这一点的事实并没有改变这一想法。它还意味着与数据库无关,这对于您作为示例给出的特定于SQL的函数来说是不可能的。LINQ translator的工作是将描述“有序子集中的最后一项”的LINQ构造转换为相应的db/SQL构造。@Shadowfox您的目标是什么确切的EF核心版本,什么数据库和提供程序。此外,您还可以提供repo(例如),因为使用EFC 2.2.6的类似查询的简单测试将转换为单个SQL查询并执行(顺便说一句,Linq to SQL是完全不同的框架。以及EF6。不要将它们用作可互换的),