2

データベースのクエリに使用している EF Code First Db コンテキストがあります。Aggregate Repository から sとしてクエリを渡すときにいくつかのパフォーマンスの問題に気付き、Func<Product, bool>さらに調査したところ、クエリが SQL クエリに変換されていないことが判明しました。

もう少し掘り下げた後、私は次のことを発見しました。

var results = _context.Products
            .Where(p => p.ProductCode.Contains("AAA"))
            .Where(p => p.CategoryId == 1)
            .ToList();

これは期待どおりに機能します。Where句を使用して、パラメータ化されたSQLを生成します。

================================================== ================

var results2 = _context.Products
            .Where(p => p.ProductCode.Contains("AAA") && p.CategoryId == 1)
            .ToList();

これも期待どおりに機能します。上記と同じSQLを生成します

================================================== ================

Func<Product, bool> pred = (p => p.ProductCode.Contains("AAA") && p.CategoryId == 1);

var results3 = _context.Products.Where(pred).ToList();

これは壊れています。SQL で where 句を生成するのではなく、すべてを返し、コードでフィルター処理します。

4

3 に答える 3

5

SQL に変換するには、Expression<...>ではなく である必要があるためFunc<...>です。

これはコンパイラによって自動的に行われます。Linq-to-SQL クラスのオーバーロードはデリゲートではなく式を取るため、コンパイラはコード (ラムダまたは匿名メソッドのように見えます) を式オブジェクトに自動的に変換します。そしてそれを渡します。

ただし、自分で関数を作成することに注意すると、コンパイラはこれを行うことができず、Linq-to-SQL は匿名メソッドを使用せず、式のみを使用します。

できることは、クエリの実行可能な部分を実行し、関数を介して結果をフィルター処理することですが、代わりに値の型を式に変更することだけを検討します。

于 2011-10-16T10:17:58.880 に答える
1

Where()この ReSharper を投稿するとすぐに、拡張メソッドのオーバーロード メソッド シグネチャが表示され、私の質問に答えることができました。

Func<T, bool>との両方が必要Expression<Func<T, bool>>です。述語を外部で宣言する場合、前者は SQL に変換されないため、式のバリエーションを使用する必要があります。

于 2011-10-16T10:16:59.257 に答える
0

クエリがテーブル全体を読み取る理由は次のとおりです。

の代わりにaFuncを使用するExpressionと、コンパイラは。System.Linq.Enumerableの代わりに-のメソッドを選択しますSystem.Linq.Queryable。メソッドが式ツリーを構築している間、メソッドはEnumerableソースコレクションを(時には怠惰に)繰り返します。Queryable

toの呼び出しWhereは式ツリーの一部ではないため、SQLジェネレーターはクエリの変換中にそれを認識しません。

于 2011-10-16T11:49:50.230 に答える