1

多くの AND/OR コンポーネントを含む複雑なステートメントは読みにくく、エラーが発生しやすくなります。通常の IF ステートメントでは、メソッド呼び出しを使用して is ステートメントを簡素化することがあります。たとえば、次のようになります。

        if (((user == myUser || user == yourUser) && user != Admin)
            && Something > SomethingElse
            && (thresholdDate > item.itemDate || (item.itemDate == null && item.itemType == itemIsDated))
            )
        {
            DoStuff();
        }

ユーザー部分と日付部分をリファクタリングして、読みやすくすることができます。

        if (
            UserValid(user)
            && Something > SomethingElse
            && DateIsValid(thresholdDate, item)
           )
        {
            DoStuff();
        }

ネストされた IF を単純化するために、LINQ クエリで何ができますか?

たとえば、次のようなものがあるとします。

        var someResults = DataManager.Things
                                        .Where(item => (item.UserName == currentUser.UserName
                                                        || item.ParentUsername == currentUser.UserName)
                                                       && (item.ItemType == (int) ItemType.MyType
                                                           || item.ItemType == (int) ItemType.YourType)
                                                       && item.Result == null
                                                       && (
                                                              (item.Status == null
                                                               && (item.ItemDate < thresholdDate
                                                                   || item.ItemType == (int) ItemType.YourType)
                                                              )
                                                              ||
                                                              (item.Status != null &&
                                                               item.Status != "Rejected")
                                                          )
            )

** 実際のコードではありません - 単純化された一般的な例です。

ロジックの一部をメソッドに抽出したり、他の方法で AND / OR の混乱を分離したりして、何が起こっているのかを明確にしたいと考えています。

「アイテム」にメソッドを追加して、ある種の IsValidType(typeOptions) メソッドのロジックを実行しようとしました - これは正常にコンパイルされますが、LINQ は実行時にメソッドを認識しないと不平を言います。

アイテムでプロパティを使用できますが、コンテキスト情報を渡すことができません (使用が制限されます)。

この種のクエリを読みやすくするにはどうすればよいでしょうか。

4

3 に答える 3

0

3 つの非常に異なるオプション:

  • Resharperを使用します。これには、if ステートメントを減らしたり、冗長な述語を指摘したりするための、多数のコード インスペクションとリファクタリングが含まれています。
  • linq-to-sql では、ほとんどのチェックをスキップできますnull。これは、式が SQL に変換され、SQL では null 参照の例外がないためです。のような linq (to sql) 句は、ない場合にwhere a.Name == "x"生成されます。linq-to-objects では、これは null 参照例外をスローします。falsea
  • 非常に頻繁に行われる比較については、計算列をデータベース テーブルに追加することを検討してください。IsRejectedを評価する列のようにStatus = 'Rejected'。に削減されるlinqではwhere !item.IsRejected
于 2012-11-21T14:18:32.853 に答える
0

Tim がコメントで述べたように、ほとんどの LINQ-to-something 実装でメソッドを使用できます。結果は次のようになります。

.Where(item => CheckUserName(item)
    && CheckItemType(item)
    && CheckItemResult(item)
    && CheckItemStatus(item));

LINQ to SQL、LINQ to Entities、またはその他のリモートで実行される実装の場合、少なくともクエリの最適化を利用して、すべて&&を個別のWhere呼び出しに書き直すことができます。これらは同等であるためです。

.Where(item => item.UserName == currentUser.UserName
    || item.ParentUsername == currentUser.UserName)
.Where(item => item.ItemType == (int) ItemType.MyType
    || item.ItemType == (int) ItemType.YourType)
.Where(item => item.Result == null)
.Where(item => (item.Status == null
    && (item.ItemDate < thresholdDate
        || item.ItemType == (int) ItemType.YourType))
    || (item.Status != null
        && item.Status != "Rejected"));

結果のクエリは、where 句を 1 つの列挙子に結合します。

于 2012-11-21T13:07:10.987 に答える
0

コードで直接行うことはできないと思います。もちろん、同様の条件がたくさんある場合は、それらの式を動的に生成できます。しかし、パフォーマンスを損なわない単一の大きな Where 条件でできることはほとんどありません =(.

より適切であると考える場合は、単一の大きな条件をいくつかの結果の Where() 呼び出しに分割できます。SQL に変換するときの LINQ ツリーは、条件をマージして単一選択を生成します。DBMS は、生成された SQL を最適化して効率を最大化することもできます。そのため、場合によっては、読みやすくするために意図的に最適化されていないクエリを記述し、自動最適化に頼ることができます。ただし、注意して、特定の条件が実際にマージされ、期待どおりに最適化されるかどうかを確認してください。

このコードを SQL ストアド プロシージャに移動できる場合は、必要なときにこのプロシージャを呼び出すように LINQ to SQL を構成できます。これにより、呼び出しコードが簡素化されますが、複雑さが SQL に移行します。Where 句を使用して、条件の一部を SQL 関数に抽出し、それらを呼び出すこともできると思います。正直なところ、私はそれを使用したことはありませんが、可能性について読んでください. 詳細と例については、次の記事を参照してください: http://weblogs.asp.net/zeeshanhirani/archive/2008/05/21/table-valued-functions-in-linq-to-sql.aspx

于 2012-11-21T13:17:59.787 に答える