var statusId = db.WorkOrder.Where(w => w.OrderType.Name == "ReadAudit" && w.WorkOrderMapping.MeterOldTag == meterTag && w.OrderStatusId != 80)
.OrderByDescending(w => w.CreationDatetime)
.Select(r => r.OrderStatusId)
.FirstOrDefault();
这产生了这个疯狂的SQL:
SELECT TOP (1)
[Project1].[OrderStatusId] AS [OrderStatusId]
FROM ( SELECT
[Filter1].[OrderStatusId] AS [OrderStatusId],
[Filter1].[CreationDatetime] AS [CreationDatetime]
FROM (
SELECT [Extent1].[OrderStatusId] AS [OrderStatusId],
[Extent1].[CreationDatetime] AS [CreationDatetime],
[Extent3].[MeterOldTag] AS [MeterOldTag]
FROM [dbo].[WorkOrder] AS [Extent1]
INNER JOIN [dbo].[OrderType] AS [Extent2] ON [Extent1].[OrderTypeKey] = [Extent2].[OrderTypeKey]
LEFT OUTER JOIN [dbo].[WorkOrderMapping] AS [Extent3] ON [Extent1].[WorkOrderKey] = [Extent3].[WorkOrderMappingKey]
WHERE (80 <> [Extent1].[OrderStatusId])
AND (N'ReadAudit' = [Extent2].[Name])
) AS [Filter1]
WHERE ([Filter1].[MeterOldTag] = @p__linq__0) OR (([Filter1].[MeterOldTag] IS NULL) AND (@p__linq__0 IS NULL))
) AS [Project1]
ORDER BY [Project1].[CreationDatetime] DESC
我告诉说它很难打到数据库:
表&#39; WorkOrder&#39;。扫描计数30,逻辑读取84403
表&#39; WorkOrderMapping&#39;。扫描计数9,逻辑读取16516
EF查询看起来并不复杂。有没有办法让生成的SQL更有效?
答案 0 :(得分:0)
这就是实体框架的工作原理。
如果您想要更多控制权,可以通过Entity Framework Raw Queries自己编写查询,请参阅here以及(不完整)示例下面的查询结果。
DbRawSqlQuery<Int32> query = db.Database.SqlQuery<Int32>("SELECT OrderStatusId FROM ... ");
var statusId = query.FirstOrDefault();
修改强>
另请参阅为此查询执行的实际查询计划,以查找相关表中是否存在相应的索引。
考虑将常量RealAudit
和80
移动到变量,如下所示:
var orderType = "RealAudit";
var orderStatusId = 80;
var statusId = db.WorkOrder.Where(w => w.OrderType.Name == orderType
&& w.WorkOrderMapping.MeterOldTag == meterTag
&& w.OrderStatusId != orderStatusId
)
.OrderByDescending(w => w.CreationDatetime)
.Select(r => r.OrderStatusId)
.FirstOrDefault();
通过这样做,这些将在查询中显示为SQL参数,如:
@p__linq__1 <> [Extent1].[OrderStatusId])
AND (@p__linq__2 = [Extent2].[Name])
这允许单个查询计划可以用于此查询的所有变体,而现在您可以获得MeterOldTag
参数的单独值的查询计划。
答案 1 :(得分:0)
关于SQL Query的唯一“疯狂”是关于MeterOldTag的谓词。它是这样编写的,因为默认情况下,EF会编写查询来模拟LINQ查询的C#比较语义。如果要在数据库中进行简单的相等比较,请为DbContext设置UseDatabaseNullSemantics。