1

と の両方で操作できる拡張メソッドがIEnumerableありIQueryableます。このメソッドは、最後に入力と呼び出しを解析しますSkip().Take()

public static IEnumerable<T> SelectRange<T>(
    this IEnumerable<T> target,
    RangeHeaderValue range
    )

このメソッドは で機能しIQueryableますが、 を返しますIEnumerable。したがって、変換する別のメソッドを追加し、最初のメソッドを呼び出して再度変換します。

public static IQueryable<T> SelectRange<T>(
    this IQueryable<T> target,
    RangeHeaderValue range
    )
{
    return target.AsEnumerable().SelectRange(range).AsQueryable();
}

このようにチェーン変換しても安全ですか? IQueryable代わりにメモリ内コレクションでメソッドを実行して、プロバイダーに干渉するのではないかと心配しています。レイジー/イーガー ローディングの基本は理解していますが、これは非常に複雑なトピックであり、うまくいくとは限りません。


注:IQueryableチェーンの危険性については受け入れられた回答は正しいですが、メソッドを実装してメソッドから呼び出すことIEnumerable(単に物事を切り替えるだけ)は安全であることを追加したいと思います。

4

2 に答える 2

8

いいえ; それは良い考えではありません。

を呼び出すAsEnumerable()と、クエリ全体が具体化され、クライアント上で実行Skip()Take()れます。

IQueryable<T>サーバー上でクエリを実行できるように、クエリ可能なメソッドのみを呼び出して返すメソッドの別の (かつ同一の) バージョンを作成する必要があります。

于 2013-08-12T11:48:32.353 に答える
1

短い答え:たぶん

AsEnumerable() あなたのクエリを具体化するかもしれません。これを確認する最も簡単な方法は、SQL Server Express Profilerとデバッグを並べて取得して、クエリが呼び出された正確なタイミングを確認することです。実際、IQueryableから継承していIEnumerableます。

さらに、デバッグ時: 何が起こっているのかを確認しようとすると、IDE はそれをマテリアライズして、Nice VS フローティング GUI デバッグ ツールで表示することがあります。

AsEnumerable()私の経験では、 からへの前後のジャンプは、 、または から継承する他のものAsQueryable()を呼び出すまで実現しませんが、グラフと同様に計算をメモリ内に保持することに注意してください。したがって、DataBase に対してクエリを実行していることを実際に確認できなくても、メモリが低いレベルでは、パフォーマンス コストがいくらか発生している可能性があります。ToArray()ToList()ICollectionIQueryable

あなたと同じように、特にページネーションに関しては、リポジトリパターンで重複が生成されないようにしようとしていました:

public static class Paginate
{
    public static IEnumerable<T> Enumerable<T>(int records, int iPage, IEnumerable<T> input) where T : class { return input.Skip(records * iPage).Take(records); }

// My internal OCD hates this dup >.o
    public static IQueryable <T> Queryable <T>(int records, int iPage, IQueryable <T> input) where T : class { return input.Skip(records * iPage).Take(records); }
}

しかし、私は、神に見捨てられたバグを追いかけて、壁に貼り付けられた「私は言ったあなたはそう」

于 2013-12-18T21:08:03.003 に答える