1

テーブルにアクセスするために linq クエリ (私は EF CodeFirst を使用しています) を構築するためのより良い方法があるかどうか疑問に思っています。現在、次のクエリが生成されます。

exec sp_executesql N'SELECT 
[Project4].[Id] AS [Id], 
[Project4].[First] AS [First], 
[Project4].[Last] AS [Last], 
[Project4].[Email] AS [Email]
FROM ( SELECT 
    [Project3].[Id] AS [Id], 
    [Project3].[First] AS [First], 
    [Project3].[Last] AS [Last], 
    [Project3].[Email] AS [Email],
    CASE WHEN ([Extent5].[Id] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C1]
    FROM   (SELECT 
        [Project2].[Id] AS [Id], 
        [Project2].[First] AS [First], 
        [Project2].[Last] AS [Last], 
        [Project2].[Email] AS [Email]
        (SELECT 
            SUM([Extent4].[Data]) AS [A1]
            FROM [dbo].[EventHistory] AS [Extent4]
            WHERE [Project2].[Id] = [Extent4].[UserId]) AS [C1]
        FROM ( SELECT 
            [Extent1].[Id] AS [Id], 
            [Extent1].[First] AS [First], 
            [Extent1].[Last] AS [Last], 
            [Extent1].[Email] AS [Email]
            (SELECT 
                SUM([Extent3].[Data]) AS [A1]
                FROM [dbo].[EventHistory] AS [Extent3]
                WHERE [Extent1].[Id] = [Extent3].[UserId]) AS [C1]
            FROM [dbo].[User] AS [Extent1]
            WHERE ( EXISTS (SELECT 
                1 AS [C1]
                FROM [dbo].[EventHistory] AS [Extent2]
                WHERE [Extent1].[Id] = [Extent2].[UserId]
            )) AND ([Extent1].[Id] = @p__linq__0)
        )  AS [Project2]
        WHERE [Project2].[C1] >= @p__linq__1 ) AS [Project3]
    LEFT OUTER JOIN [dbo].[EventHistory] AS [Extent5] ON [Project3].[Id] = [Extent5].  [UserId]
    WHERE [Project3].[C1] <= @p__linq__2
)  AS [Project4]
ORDER BY [Project4].[Id] ASC, [Project4].[C1] ASC',N'@p__linq__0 int,@p__linq__1 int,@p__linq__2 int',@p__linq__0=1717,@p__linq__1=300,@p__linq__2=400

...そして、これは私にはかなり恐ろしいように思えます。なぜ、これらすべての異なるサブセレクトが作成されるのでしょうか? -私にとって、それは本当に次のようなものを生成する必要があります:

select u.id, first, last, email, e.*
from user u 
left join eventhistory e
    on e.userid = u.id
   and e.data <= @param1
   and e.data >= @param2
   and u.id = @id

私のコードは次のようになります。

IQueryable<User> query = from users in this.DataContext.Users.Include("EventHistoryList") 
                         where users.EventHistoryList.Any()
                         select users;

if (playerId.HasValue)
    query = query.Where(u => u.Id == playerId.Value);

if (dataLow.HasValue)
    query = query.Where(u => u.EventHistoryList.Sum(p => p.Data) >= dataLow.Value);

if (dataHigh.HasValue)
    query = query.Where(u => u.EventHistoryList.Sum(p => p.Data) <= dataHigh.Value);

query = query.OrderByDescending(orderBy).Skip(startEntity).Take(pageSize).ToList();

どんな助けでも大歓迎です。ありがとう!

4

1 に答える 1

1

サブ選択の 1 つがページングを処理しているように見えますが、0..* 関係を持つテーブルに対して集計関数を適用しているため、他の選択が必要です。クエリの見栄えを良くすることができると確信していますが、不必要に非効率的だとは思いません。

生成する必要があると思われるクエリは、データベースから結果セット全体を取得し、集計関数を適用するためにサブセレクトも必要とします。データベースから結果セット全体を取得し、後でページングを行うのは非常に非効率的です。

于 2012-05-29T16:37:52.777 に答える