更新 这可能已经修复:http://entityframework.codeplex.com/workitem/486
...
针对我的实体的相当简单的 LINQ 语句导致了不必要的复杂 SQL。稍后会详细介绍,这是设置:
表
出版物
收据
LINQ
var query = from r in context.Receipts.Include("Publication")
where r.DateInserted < lagDate
&& r.ReceiptId > request.AfterReceiptId
&& r.Publication.TopicId == topicEntity.TopicId
&& r.Publication.ReceiptCount > 1
select r;
SQL
exec sp_executesql N'SELECT TOP (25)
[Project1].[ReceiptId] AS [ReceiptId],
[Project1].[PublicationId] AS [PublicationId],
[Project1].[DateInserted] AS [DateInserted],
[Project1].[DateReceived] AS [DateReceived],
[Project1].[PublicationId1] AS [PublicationId1],
[Project1].[PayloadId] AS [PayloadId],
[Project1].[TopicId] AS [TopicId],
[Project1].[BrokerType] AS [BrokerType],
[Project1].[DateInserted1] AS [DateInserted1],
[Project1].[DateProcessed] AS [DateProcessed],
[Project1].[DateUpdated] AS [DateUpdated],
[Project1].[PublicationGuid] AS [PublicationGuid],
[Project1].[ReceiptCount] AS [ReceiptCount]
FROM ( SELECT
[Extent1].[ReceiptId] AS [ReceiptId],
[Extent1].[PublicationId] AS [PublicationId],
[Extent1].[DateInserted] AS [DateInserted],
[Extent1].[DateReceived] AS [DateReceived],
[Extent3].[PublicationId] AS [PublicationId1],
[Extent3].[PayloadId] AS [PayloadId],
[Extent3].[TopicId] AS [TopicId],
[Extent3].[BrokerType] AS [BrokerType],
[Extent3].[DateInserted] AS [DateInserted1],
[Extent3].[DateProcessed] AS [DateProcessed],
[Extent3].[DateUpdated] AS [DateUpdated],
[Extent3].[PublicationGuid] AS [PublicationGuid],
[Extent3].[ReceiptCount] AS [ReceiptCount]
FROM [dbo].[Receipt] AS [Extent1]
INNER JOIN [dbo].[Publication] AS [Extent2] ON [Extent1].[PublicationId] = [Extent2].[PublicationId]
LEFT OUTER JOIN [dbo].[Publication] AS [Extent3] ON [Extent1].[PublicationId] = [Extent3].[PublicationId]
WHERE ([Extent2].[ReceiptCount] > 1) AND ([Extent1].[DateInserted] < @p__linq__0) AND ([Extent1].[ReceiptId] > @p__linq__1) AND ([Extent2].[TopicId] = @p__linq__2)
) AS [Project1]
ORDER BY [Project1].[ReceiptId] ASC',N'@p__linq__0 datetime,@p__linq__1 int,@p__linq__2 int',@p__linq__0='2012-09-05 19:39:21:510',@p__linq__1=4458824,@p__linq__2=90
问题
出版物被加入两次:
.Include("Publication")
where
. 如果我从 SQL 中完全删除 [Extent2],并将 WHERE 位更改为使用 [Extent3],则会得到相同的结果。由于我没有在实体上使用延迟加载,因此我必须
.Include("Publication")
……有什么解决办法吗?我正在使用 EF4,但从 NuGet 中获取了 EF5 以查看它是否已修复,但它产生了相同的结果(尽管我不知道如何判断我的 EDMX 是否真的在使用 EF5)。
最佳答案
但是,有一个解决方法。它可能不是最优雅的解决方案,但它完全符合您的要求;它只生成一个连接。
改变:
var query = from r in context.Receipts.Include("Publication")
where r.DateInserted < lagDate
&& r.ReceiptId > request.AfterReceiptId
&& r.Publication.TopicId == topicEntity.TopicId
&& r.Publication.ReceiptCount > 1
select r;
成为:
var query = from r in context.Receipts
join pub in context.Publication on r.PublicationId equals pub.PublicationId
where r.DateInserted < lagDate
&& r.ReceiptId > request.AfterReceiptId
&& pub.TopicId == topicEntity.TopicId
&& pub.ReceiptCount > 1
select new {
Receipt = r,
Publication = pub
};
请注意,我们已经删除了 Include 并且我们不再使用 r.Publication。??在 where 子句中。相反,我们正在使用 pub.??
现在,当您循环查询时,您将看到 r.Publication 不为空:
foreach ( var item in query)
{
//see that item.Publication is not null
if(item.Receipt != null && item.Receipt.Publication != null)
{
//do work based on a valid Publication
}
else
{
//do work based on no linked Publication
}
}
关于linq - Entity Framework 似乎不必要地两次加入同一个表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12289070/