9

私はMicrosoftのEntityFrameworkをORMとして使用していますが、次の問題を解決する方法を考えています。コレクションから、今日よりも大きいProductオブジェクトをいくつか取得したいと思います。(これは問題全体の簡略版です。)ProductsProduct.StartDate

私は現在使用しています:

var query = dbContext.Products.Where(p => p.StartDate > DateTime.Now);

これを実行すると、ToList()たとえばクエリで使用した後、機能し、作成されたSQLは効果的に次のようになります。

SELECT * FROM Product WHERE StartDate > (GetDate());

ただし、保守性を高めるために述語を関数に移動したいので、これを試しました。

private Func<Product, bool> GetFilter()
{
  Func<Product, bool> filter = p => p.StartDate > DateTime.Now;
  return filter;
}
var query = dbContext.Products.Where(GetFilter());

これは、同じセットを返す限り、コードの観点からも機能しますProductが、今回作成されたSQLは次のようになります。

SELECT * FROM Product;

フィルタはSQLServerからクライアントに移動されるため、効率が大幅に低下します。

だから私の質問は:

  • なぜこれが起こっているのですか、なぜLINQパーサーはこれらの2つの形式をそれほど異なって扱うのですか?
  • フィルタを分離してサーバー上で実行することを利用するにはどうすればよいですか?
4

3 に答える 3

8

意図したとおりに機能させるには、を使用する必要がありExpression<Func<Product, bool>>ます。プレーンは、SQLではなくプログラムのMSILでFunc<Product, bool>実行するようにLINQに指示します。Whereこれが、SQLがテーブル全体をプルし、.NETコードがテーブル全体で述語を実行している理由です。

于 2012-01-23T08:55:36.283 に答える
4

を返しますがFunc、述語をSQLに挿入するには、LINQに式ツリーが必要です。メソッド(そしてもちろんローカル変数)の戻り値の型をに変更すると機能するはずですExpression<Func<Product, bool>>

于 2012-01-23T08:58:02.467 に答える
2

2番目のケースでは、フィルター関数が任意のLINQ to EFを解析できないため、フィルターをSQLに変換できず、クライアント側で解決する必要があります。

于 2012-01-23T08:56:35.820 に答える