我在使用EF时遇到了性能问题。
using (var context = new CustomDbContext())
{
var result = context.
TransactionLines
.Where(x =>
x.Transaction.TransactionTypeId == 1433 &&
(x.Transaction.Eob.EobBatchId == null || x.Transaction.Eob.EobBatch.Status == EobBatchStatusEnum.Completed)
)
.GroupBy(x => x.VisitLine.ProcedureId)
.Select(x => new
{
Id = x.Key,
PaidAmount = x.Sum(t => t.PaidAmount),
Code = context.Procedures.Where(h => h.Id == x.Key).Select(h => h.Code).FirstOrDefault()
}).ToArray();
}
EF会生成下一个SQL语句:
SELECT
1 AS [C1],
[Project6].[ProcedureId] AS [ProcedureId],
[Project6].[C2] AS [C2],
[Project6].[C1] AS [C3]
FROM ( SELECT
[Project5].[ProcedureId] AS [ProcedureId],
[Project5].[C1] AS [C1],
(SELECT
SUM([Extent7].[PaidAmount]) AS [A1]
FROM [dbo].[TransactionLines] AS [Extent7]
INNER JOIN [dbo].[Transactions] AS [Extent8] ON [Extent7].[TransactionId] = [Extent8].[Id]
LEFT OUTER JOIN [dbo].[Eobs] AS [Extent9] ON [Extent8].[EobId] = [Extent9].[Id]
LEFT OUTER JOIN [dbo].[EobBatches] AS [Extent10] ON [Extent9].[EobBatchId] = [Extent10].[Id]
LEFT OUTER JOIN [dbo].[VisitLines] AS [Extent11] ON [Extent7].[VisitLineId] = [Extent11].[Id]
WHERE (([Extent9].[EobBatchId] IS NULL) OR (1 = [Extent10].[Status])) AND ([Extent8].[TransactionTypeId] = 1433) AND (([Project5].[ProcedureId] = [Extent11].[ProcedureId]) OR (([Project5].[ProcedureId] IS NULL) AND ([Extent11].[ProcedureId] IS NULL)))) AS [C2]
FROM ( SELECT
[Project4].[ProcedureId] AS [ProcedureId],
[Project4].[C1] AS [C1]
FROM ( SELECT
[Project2].[ProcedureId] AS [ProcedureId],
(SELECT TOP (1)
[Extent6].[Code] AS [Code]
FROM [dbo].[Procedures] AS [Extent6]
WHERE [Extent6].[Id] = [Project2].[ProcedureId]) AS [C1]
FROM ( SELECT
[Distinct1].[ProcedureId] AS [ProcedureId]
FROM ( SELECT DISTINCT
[Extent5].[ProcedureId] AS [ProcedureId]
FROM [dbo].[TransactionLines] AS [Extent1]
INNER JOIN [dbo].[Transactions] AS [Extent2] ON [Extent1].[TransactionId] = [Extent2].[Id]
LEFT OUTER JOIN [dbo].[Eobs] AS [Extent3] ON [Extent2].[EobId] = [Extent3].[Id]
LEFT OUTER JOIN [dbo].[EobBatches] AS [Extent4] ON [Extent3].[EobBatchId] = [Extent4].[Id]
LEFT OUTER JOIN [dbo].[VisitLines] AS [Extent5] ON [Extent1].[VisitLineId] = [Extent5].[Id]
WHERE (([Extent3].[EobBatchId] IS NULL) OR (1 = [Extent4].[Status])) AND ([Extent2].[TransactionTypeId] = 1433)
) AS [Distinct1]
) AS [Project2]
) AS [Project4]
) AS [Project5]
) AS [Project6]
查询耗时约为3秒。如果直接使用Group By编写SQL查询,则查询时间为1.5秒,使用的CPU资源少一半。
SELECT sq.ProcedureId, SUM(sq.PaidAmount), (SELECT TOP(1) Procedures.Code From Procedures Where Procedures.Id = sq.ProcedureId) as Code
FROM(
SELECT [Extent5].[ProcedureId] AS [ProcedureId],[Extent1].PaidAmount as [PaidAmount]
FROM [dbo].[TransactionLines] AS [Extent1]
INNER JOIN [dbo].[Transactions] AS [Extent2] ON [Extent1].[TransactionId] = [Extent2].[Id]
LEFT OUTER JOIN [dbo].[Eobs] AS [Extent3] ON [Extent2].[EobId] = [Extent3].[Id]
LEFT OUTER JOIN [dbo].[EobBatches] AS [Extent4] ON [Extent3].[EobBatchId] = [Extent4].[Id]
LEFT OUTER JOIN [dbo].[VisitLines] AS [Extent5] ON [Extent1].[VisitLineId] = [Extent5].[Id]
WHERE (([Extent3].[EobBatchId] IS NULL) OR (1 = [Extent4].[Status])) AND ([Extent2].[TransactionTypeId] = 1433)
) sq
GROUP BY sq.ProcedureId
我写了不同的Linq,但仍然无法强制EF生成GroupBy而不是子查询。
理想情况下,我不想使用函数或手动编写SQL,因为在构建Linq逻辑时有很多条件。
是否有可能强制EF生成与Linq中编写的完全相同的SQL?