動的クエリと条件を準備する方法と、関数を使用してそれらの一部を構築する方法があります。構文も読みやすく、質問の「単純な」部分に適しています。Linq 式を組み合わせることで可能です。これを行う方法についてはいくつかの記事がありますが、新しいアプローチを思いついたと思います。少なくとも私はウェブ上で見つけられませんでした。
続行するには、3 つの単純な関数のライブラリが必要です。System.Linq.Expressions.ExpressionVisitor
式を動的に変更するために使用します。重要な機能は、同じ名前を持つ 2 つのパラメーターが同一になるように、式内のパラメーターを統合することです ( UnifyParametersByName
)。残りの部分は、名前付きパラメーターを指定された式 ( ReplacePar
) とヘルパー メソッド ( NewExpr
) に置き換えています。このライブラリは、github: LinqExprHelperで MIT ライセンスで利用できますが、自分で何かをすばやく作成することもできます。
最初にいくつかのメソッドを定義します。これは後で動的クエリの作成に使用できます。
public class Store
{
...
public static Expression<Func<Store, bool>>
SafeSearchName(string sWhat)
{
return LinqExprHelper.NewExpr(
(Store s) => s.Name != null && s.Name.ToLower().Contains(sWhat)
);
}
public static Expression<Func<Store, bool>>
SafeSearchDesc(string sWhat)
{
return LinqExprHelper.NewExpr(
(Store s) => s.Description != null && s.Description.ToLower().Contains(sWhat)
);
}
}
次に、次の方法でクエリを実行します。
// Define a master condition, using named parameters.
var masterExpr = LinqExprHelper.NewExpr(
(Store s, bool bSearchName, bool bSearchDesc)
=> (bSearchName && bSearchDesc));
// Replace stub parameters with some real conditions.
var combExpr = masterExpr
.ReplacePar("bSearchName", Store.SafeSearchName("b").Body)
.ReplacePar("bSearchDesc", Store.SafeSearchDesc("p").Body);
// Sometimes you may skip a condition using this syntax:
//.ReplacePar("bSearchDesc", Expression.Constant(true));
// It's interesting to see how the final expression looks like.
Console.WriteLine("expr: " + combExpr);
// Execute the query using combined expression.
db.Stores
.Where((Expression<Func<Store, bool>>)combExpr)
.ToList().ForEach(i => { Console.WriteLine(i.Name + ", " + i.Description); });
これはまだ本番環境では使用していませんが、いくつかの簡単なテストには合格しています。このようにクエリを組み合わせることに制限はありません。より多くのパラメーターが必要な場合は、結合の追加レベルを追加できます。この方法の利点は、読みやすいインライン ラムダ式と、非常に優れた動的な式の作成および合成を使用できることです。
やっぱり「シンプル」?Linq のメソッド構文が単純であると考えれば、これはほぼ単純です。カスタム Linq 関数を作成することはできませんが、同等の機能が提供されます。