12

更新これは既に修正されている可能性があります: http://entityframework.codeplex.com/workitem/486

...

エンティティに対して非常に単純な LINQ ステートメントを使用すると、SQL が不必要に複雑になります。詳細は後述しますが、セットアップは次のとおりです。

テーブル

出版物

  • パブリケーション ID (pk)
  • TopicId (Topic テーブルへの fk)
  • ReceiptCount (クエリ パフォーマンスのために非正規化)
  • 挿入日

レシート

  • 領収書 ID (pk)
  • PublicationId (上の表の fk)
  • 挿入日

リンク

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

問題

パブリケーションが 2 回結合されます。

  1. LEFT OUTER JOINのため.Include("Publication")
  2. のためのINNER JOIN where

SQL から [Extent2] を完全に削除し、[Extent3] を使用するように WHERE ビットを変更すると、同じ結果が返されます。エンティティで遅延読み込みを使用していないため、.Include("Publication")...これに対する解決策はありますか?

私は EF4 を使用していましたが、NuGet から EF5 を取得して修正されたかどうかを確認しましたが、同じ結果が得られました (EDMX が本当に EF5 を使用しているかどうかを確認する方法はわかりません)。

4

3 に答える 3

0

以下のようにコードを変更することで、前の人の回答を最適化します。これにより、結合の必要がなくなるため、結合する必要がある列を知る必要がなく、結合条件が変更されたときに LINQ を変更する必要もありません。これは不要だったはずですが、MS は現在、SQL コード生成の修正に重点を置いていません。

    var query = from pub in context.Publications
                from r in pub.Reciepts
                where r.DateInserted < lagDate 
                && r.ReceiptId > request.AfterReceiptId 
                && pub.TopicId == topicEntity.TopicId 
                && pub.ReceiptCount > 1 
                select new {
                       Receipt = r,
                       Publication = pub
                };
于 2012-09-06T19:24:01.103 に答える