【发布时间】:2011-02-21 21:51:48
【问题描述】:
我注意到我的实体框架查询生成了一些非常丑陋的 SQL。当我检查 SQL 时,即使是非常简单的查询也会产生大量额外的 JOIN。
我创建了一个简单的模型:
订单
OrderID INT PK
订单日期日期时间
OrderHeaders
OrderID INT PK / FK
StatusID INT FK
状态类型
StatusID INT PK
说明 NVARCHAR(50)
从模型中,一个订单可以有 0 或 1 个订单标题。标头将具有 1 个状态类型。
我创建了以下查询:
var orders = from o in db.Orders
where o.OrderID == 1
select new
{
Order = o,
Status = o.OrderHeader.Status
};
由此生成的 SQL 如下所示:
SELECT
[Extent1].[OrderID] AS [OrderID],
[Extent1].[OrderDate] AS [OrderDate],
[Extent4].[StatusID] AS [StatusID],
[Extent4].[Description] AS [Description]
FROM [dbo].[Orders] AS [Extent1]
LEFT OUTER JOIN [dbo].[OrderHeaders] AS [Extent2] ON [Extent1].[OrderID] = [Extent2].[OrderID]
LEFT OUTER JOIN [dbo].[OrderHeaders] AS [Extent3] ON [Extent2].[OrderID] = [Extent3].[OrderID]
LEFT OUTER JOIN [dbo].[StatusTypes] AS [Extent4] ON [Extent3].[OrderID] = [Extent4].[OrderID]
WHERE 1 = [Extent1].[OrderID]
如您所见,查询中有两个不必要的左连接。为什么会这样生成 SQL?我问错了吗?我不应该在查询中使用导航属性吗?
我是否需要在查询本身中编写联接,这样它就不会为我生成额外的联接?当我使用连接编写查询时,生成的 SQL 没有任何额外的 JOIN,但是 LINQ to Entities 查询更丑陋/更冗长:
var orders = from o in db.Orders
join h in db.OrderHeaders on o.OrderID equals h.OrderID into orderHeader
from h in orderHeader.DefaultIfEmpty()
join s in db.StatusTypes on h.StatusID equals s.StatusID into statusType
from s in statusType.DefaultIfEmpty()
where o.OrderID == 1
select new
{
o,
s
};
这会在没有额外连接的情况下生成 SQL,但从 C# 方面看会更难看。
有人知道如何解决这个问题吗?
【问题讨论】:
标签: c# .net entity-framework-4 linq-to-entities