そこで私は最近、式ではなく拡張メソッドにを指定するFunc<T, TResult>
ことで、EntityFrameworkがプロジェクションをSQLに変換しないように強制できることを発見しました。.Select()
これは、クエリされたデータを変換する場合に役立ちますが、その変換はデータベースではなくコードで行う必要があります。
たとえば、EF5の新しい列挙型サポートを使用してそれをDTOの文字列プロパティに投影しようとすると、失敗します。
results.Select(r => new Dto { Status = r.Status.ToString() })
これはうまくいくでしょう:
results.Select(new Func<Record, Dto>(r => new Dto { Status = r.Status.ToString() }));
最初の(式)の場合、EFはStatus.ToString()をSQLデータベースが実行できるものに変換する方法を理解できないためですが、この記事のとおり、Func述語は変換されません。
これが機能するようになったら、次の拡張メソッドを作成することはそれほど大きな飛躍ではありませんでした。
public static IQueryable<T> Materialize<T>(this IQueryable<T> q)
{
return q.Select(new Func<T, T>(t => t)).AsQueryable();
}
だから私の質問は-これを使用するときに注意すべき落とし穴はありますか?パフォーマンスに影響はありますか?この何もしないプロジェクションをクエリパイプラインに挿入するか、EFが.Where()
句をサーバーに送信しないようにして、すべての結果をネットワーク経由で送信することによってですか?
.Where()
サーバー上の結果をフィルター処理するメソッドを引き続き使用することを目的としていますが、プロバイダーがプロジェクションをSQLServerに変換しようとしないよう.Materialize()
に前に使用.Select()
します。
return Context.Record
.Where(r => // Some filter to limit results)
.Materialize()
.Select(r => // Some projection to DTO, etc.);