1

エンティティフレームワークを使用してMVCアプリケーションのデータベースを処理しています:開始フォームからいくつかのフィールドを使用してアプリケーションの検索エンジンを作成し、ユーザーロールから取得する特権を設定しているため、selectステートメントを作成するルーチンが増えています、だから時々私はこの状況になります。選択する前に:

  1. varorders = db.Orders.Where(ord => ord.Channel == 1 || ord.Channel == 2);

    ソースコードの後で、場合によっては、ユーザーのタイプ、フィルターの組み合わせなど、このフィルターを変更するか、この条件を削除する必要があります

  2. orders = db.Orders.Where(ord => ord.Channel == 1);

    これは単純な例です。この方法を実行すると、Linq式ツリーで実行した他のフィルターが失われ、機能の追加が頻繁に要求されるため、すべてのコードを再編成してすべての前提条件をテストすることは非常に困難です。式ツリーに条件を追加して、追加された後、SQLクエリでツリーが解析および変換される前に、linq式ツリーのステートメントを削除できるかどうかを知りたいです。

ルカ

4

1 に答える 1

1

私があなたの質問を正しく理解していると仮定すると、可能な最も簡単なアプローチは、クエリがどのように見えるかを知るために必要なすべてのデータを収集するまでクエリの作成を延期することです。つまり、この場合は、クエリのみを作成することを意味します。条件を実際に適用する必要があるかどうかをすでに知った後。

クエリの作成を延期することができない場合(私にはそれがあなたの言っていることのようです)、後でどの条件を削除する必要があるかを予測できる場合は、ブール値を導入することを検討しますクエリ内のセンチネル、たとえばクエリスニペットに基づく:

var orders = db.Orders.Where( ord => 
    (isFirstConditionRelevant && ord.Channel == 1) 
    || (isSecondConditionRelvant && ord.Channel == 2));

変数'isFirstConditionRelevant'および'isSecondConditionRelevant'は、最初はtrueに設定され、クエリ式によってキャプチャされますが、対応する条件が必要な場合は、後で(たとえば、クエリを実行する直前に)falseに設定できます。効果はありません。このアプローチでは、クエリのSQL変換には条件が含まれますが、サーバーによってクエリが実行されるときにブール論理を短絡する各センチネルのパラメーターも含まれることに注意してください。

また、条件内の定数(たとえば、「ord.Channel == 1」の「1」)は、SQLでは定数に変換されることにも注意してください。変数を使用することをお勧めします。これにより、SQLクエリにパラメーターが導入され、サーバーでクエリプランを再利用できる可能性が高くなります。

便利な別のアプローチは、クエリ内の式変数への参照のサポートを利用することです。たとえば、Expression>型の変数をWhere句に渡し、後で変数の値を正しい述語に置き換えることができます。 。私の記憶が正しければ、LINQ to Entitiesは、クエリ内のコレクションにAsQueryable演算子を適用することにより、ネストされたコレクションに対する述語条件として式変数を使用することをサポートしています。それ以外の場合は、LINQキットが提供するAsExpandableのサポートを利用できます。これに関する詳細情報、および式変数への参照の使用例については、LINQ Kitのホームページ(http://www.albahari.com/nutshell/linqkit.aspx )を参照してください。

私が検討する4番目の最も複雑なアプローチは、クエリを実行する前に、自分の訪問者(System.Linq.Expressions.ExpressionVisitorから派生したものなど)を使用してLINQ式ツリーを書き換える(この場合は述語から条件を削除する)ことです。 。そんなに便利なエクスプレッションビジターはいない。代わりに、問題のさまざまな部分を解決する記事へのいくつかのポインタを提供できます。

  1. StackOverflowのこのスレッドでは、式ビジターを使用してクエリの書き換えを行う方法について説明しています。LINQExpressionVisitorを使用して、プリミティブパラメーターをラムダ式のプロパティ参照に置き換えます
  2. Alex Jamesによるこのすばらしいブログ投稿では、クエリが実行される直前に式の書き換えビジターを呼び出すインターセプトクエリプロバイダーを作成する方法について説明しています。http://blogs.msdn.com/b/alexj/archive/2010/03/ 01/tip-55-how-to-extend-an-iqueryable-by-wrapping-it.aspx
  3. 次の記事では、ルールに基づいて式を書き換えるために使用できるライブラリについて説明します:http: //www.codeproject.com/Articles/24454/Modifying-LINQ-Expressions-with-Rewrite-Rules

お役に立てれば!

于 2013-01-09T22:16:31.407 に答える