我正在使用EF Core 2.2.4
我有一个父表WorkOrders
和子表WorkOrderResponses
,我有以下查询来选择WorkOrders
,然后仅选择其WorkOrderResponses
的那些子IsFinalResponse
标志为真
var workItemID = 1018 // this is parent id for WorkOrder
var result = await _dbContext.WorkOrders
.Where(x => x.WorkOrderStatusID == 2 && x.WorkItemID == workItemID)
.Select(x => new
{
x.WorkOrderID,
x.WorkOrderStatusID,
// filter children
FinalResponse = x.WorkOrderResponses
.Where(r => r.IsFinalResponse)
.Select(r => r.Response)
.ToList(),
})
.ToListAsync();
它返回正确的结果,包括已过滤的子级。在SQL事件探查器中,它仅按预期生成2个SQL查询
查询1
exec sp_executesql N'SELECT [x].[WorkOrderID], [x].[WorkOrderStatusID]
FROM [WorkOrders] AS [x]
WHERE ([x].[WorkOrderStatusID] = 2) AND ([x].[WorkItemID] = @__workItemID_0)
ORDER BY [x].[WorkOrderID]',N'@__workItemID_0 int',@__workItemID_0=1018
查询2
exec sp_executesql N'SELECT [t].[WorkOrderID], [x.WorkOrderResponses].[Response], [x.WorkOrderResponses].[WorkOrderID]
FROM [WorkOrderResponses] AS [x.WorkOrderResponses]
INNER JOIN (
SELECT [x0].[WorkOrderID]
FROM [WorkOrders] AS [x0]
WHERE ([x0].[WorkOrderStatusID] = 2) AND ([x0].[WorkItemID] = @__workItemID_0)
) AS [t] ON [x.WorkOrderResponses].[WorkOrderID] = [t].[WorkOrderID]
WHERE [x.WorkOrderResponses].[IsFinalResponse] = 1
ORDER BY [t].[WorkOrderID]',N'@__workItemID_0 int',@__workItemID_0=1018
当我使用WorkOrderResponses
过滤子项.Where(r => r.IsFinalResponse)
时,我知道它将始终返回单个子项。因此,我将查询更改为使用SingeOrDefault
而不是ToList()
var result = await _dbContext.WorkOrders
.Where(x => x.WorkOrderStatusID == 2 && x.WorkItemID == workItemID)
.Select(x => new
{
x.WorkOrderID,
x.WorkOrderStatusID,
// filter children
FinalResponse = x.WorkOrderResponses
.Where(r => r.IsFinalResponse)
.Select(r => r.Response)
.SingleOrDefault(),
})
.ToListAsync();
但是,现在,如果运行sql profiler,它将为每个工作单创建sql。例如
exec sp_executesql N'SELECT TOP(2) [r0].[Response]
FROM [WorkOrderResponses] AS [r0]
WHERE ([r0].[IsFinalResponse] = 1) AND (@_outer_WorkOrderID = [r0].[WorkOrderID])',N'@_outer_WorkOrderID int',@_outer_WorkOrderID=2330
因此,对于给定的WorkItemID,我有1000个工作订单,那么将为每个工作订单生成1000次以上查询
如何选择“单身”或“第一个被过滤的孩子”?