2

Entity Frameworkを使用してサーバー側のページングを実装しており、次のコードがあります

 DbQuery<T> query = Context.Set<T>();

 query = IncludeNavigationProperties(query, includedProperties);

 var result =  query.OrderBy(arg => arg.DatabaseId)
                    .Skip((pageNumber - 1)*pageSize)
                    .Take(pageSize).ToList();

これにより、必要なデータのみを照会する SQL が生成されます (SQL Server Profiler で確認)

SELECT TOP (21) 
[Extent1].[DatabaseId] AS [DatabaseId], 
...[other props here]...
FROM ( SELECT [Extent1].[DatabaseId] AS [DatabaseId], ...[other props here]..., row_number() OVER (ORDER BY [Extent1].[DatabaseId] ASC) AS [row_number]
    FROM [dbo].[Table] AS [Extent1]
)  AS [Extent1]
WHERE [Extent1].[row_number] > 84
ORDER BY [Extent1].[DatabaseId] ASC

keySelector次に、このメソッドをより多くのシナリオで再利用し、extern 変数として渡すことにしました。

 DbQuery<T> query = Context.Set<T>();

 query = IncludeNavigationProperties(query, includedProperties);

 var result =  query.OrderBy(keySelector)
                    .Skip((pageNumber - 1)*pageSize)
                    .Take(pageSize).ToList();

どこ

Func<T, int> keySelector = arg => arg.DatabaseId;

しかし、突然次の SQL クエリが生成されます。

SELECT 
[Extent1].[DatabaseId] AS [DatabaseId], 
...[other props here]...
FROM [dbo].[Table] AS [Extent1]

私が理解しているように、テーブルからすべてのデータを照会し、サーバーで処理します。

だから、私は2つの質問があります:

  1. なぜクエリが変更されるのですか?
  2. どうすれば修正できますか (keySelector必要なデータのみを変更してクエリできるようにする)?
4

1 に答える 1

2

DbQuery<T>IQueryable<T>IEnumerable<T>クラスの両方から派生します。これらのクラスはどちらもOrderByメソッドを提供しますが、1 つの違いがあります。 OrderByonはパラメーターをIEnumerable取得しFunc<T1,T2>OrderByonIQueriableExpression<Func<T1,T2>>パラメーターを取得します。オブジェクトkeyselectorとしてメソッドに渡すと、コンパイラに次のように伝えますで定義されているメソッドを使用してくださいつまり、オブジェクトはキャストされません。これが、すべてのデータがクライアントにフェッチされ、さらに操作がメモリ内で行われる理由です。Func<T1,T2>OrderByOrderByIEnumerableDbQuery<T>IEnumerable<T>IQueriable<T>.

これを修正するには、タイプをkeyselectorfromFunc<T1,TKey>からExpression <Func<T1,TKey>>as に変更します。

public IQueriable<T> YourMethodName<T, TKey>(Expression<Func<T,TKey>> keyselector)
{
    DbQuery<T> query = Context.Set<T>();

     query = IncludeNavigationProperties(query, includedProperties);

     var result =  query.OrderBy(keySelector)
                        .Skip((pageNumber - 1)*pageSize)
                        .Take(pageSize).ToList();
     return result;
}
于 2013-09-23T13:47:28.550 に答える