5

LINQ to SQLを使用するプロジェクトがあります。このプロジェクトでは、クライアントがandまたはanまたは検索を実行するかどうかを選択できるように、いくつかの検索ページを書き直す必要があります。

PredicateBuilderを使用してLINQクエリをやり直すことについては考えましたが、これはかなりうまく機能していると思います。私は事実上、述語を含むクラスを持っています。例:

internal static Expression<Func<Job, bool>> Description(string term)
{
    return p => p.Description.Contains(term);
}

検索を実行するために私はこれを行っています(簡潔にするためにいくつかのコードは省略されています):

public Expression<Func<Job, bool>> ToLinqExpression()
{
    var predicates = new List<Expression<Func<Job, bool>>>();
    // build up predicates here

    if (SearchType == SearchType.And)
    {
        query = PredicateBuilder.True<Job>();
    }
    else
    {
        query = PredicateBuilder.False<Job>();
    }

    foreach (var predicate in predicates)
    {
        if (SearchType == SearchType.And)
        {
            query = query.And(predicate);
        }
        else
        {
            query = query.Or(predicate);
        }
    }
    return query;
}

私はこれにかなり満足していますが、2つの懸念があります。

  1. SearchTypeプロパティを評価するif/elseブロックは、潜在的なコードの臭いである可能性があるように感じます。
  2. クライアントは現在、'/'または'ではない'検索を実行できることを主張しています。

ポイント2に対処するために、私は自分の表現を書き直すだけでこれを行うことができると思います。

internal static Expression<Func<Job, bool>> Description(string term, bool invert)
{
    if (invert)
    {
        return p => !p.Description.Contains(term);
    }
    else
    {
        return p => p.Description.Contains(term);
    }
}

ただし、これはちょっとした悩みの種のように感じます。これは通常、より良い解決策があることを意味します。誰かがこれをどのように改善できるかをお勧めできますか?私は動的LINQを知っていますが、LINQの強い型付けを失いたくありません。

4

1 に答える 1

9

より少ない行を探している場合は、if/elseを三項演算子に置き換えることができます。

query = SearchType == SearchType.And ? PredicateBuilder.True<Job>() : PredicateBuilder.False<Job>();

   foreach (var predicate in predicates)
   {
        query = SearchType == SearchType.And ? query.And(predicate) : query.Or(predicate);
   }

その'and not' / 'or not'部分については、!オペレーターがトリックを行う必要があります。

PD:パーツが正しく述語を設定していることをテストしましたforeachか?後で実行される式を作成していることを覚えている限り、最後に設定された述語だけを文字通り参照している可能性があります反復。そのため、各反復の値を保存するには一時変数を使用する必要があります。

編集: プログラマティックな式を否定したい場合、それはトリッキーなものです、あなたは次のようなことを試すことができます:

internal static Expression<Func<Job, bool>> Description(string term, bool invert)
        {
           return NegateExp<Func<Job, bool>>(p => p.Description.Contains(term), invert);
        }

また、NegateExpメソッドは次のようになります。

public static Expression<TDelegate> NegateExp<TDelegate>(Expression<TDelegate> expression, bool inverse)
        {
            if (inverse)
            {
                return Expression.Lambda<TDelegate>(Expression.Not(expression.Body), expression.Parameters);
            }
            return expression;
        }

その他の例については、この質問を参照してください。述語を否定する方法はありますか?

于 2010-06-16T17:31:19.677 に答える