web-dev-qa-db-ja.com

LINQの動的WHERE句

動的なWHERE句をLINQステートメントにアセンブルする最良の方法は何ですか?

フォームには数十個のチェックボックスがあり、それらをLINQクエリにDictionary <string、List <string >>(Dictionary <fieldName、List <values >>)として返しています。

public IOrderedQueryable<ProductDetail> GetProductList(string productGroupName, string productTypeName, Dictionary<string,List<string>> filterDictionary)
{
    var q = from c in db.ProductDetail
            where c.ProductGroupName == productGroupName && c.ProductTypeName == productTypeName
            // insert dynamic filter here
            orderby c.ProductTypeName
            select c;
    return q;
}
52
Keith Barrows

alt text
(ソース: scottgu.com

このようなものが必要ですか? Linq Dynamic Query Library を使用します(ダウンロードにはサンプルが含まれています)。

他の例については、 ScottGuのブログ をご覧ください。

52
Thomas Stock

LinqKitのPredicateBuilderを使用して、OrまたはAndを使用して複数のタイプセーフなラムダ式をチェーンすることもできます。

http://www.albahari.com/nutshell/predicatebuilder.aspx

13
Linus

ユーザー入力に基づいてフィルターを追加し、where句をチェーンする必要がある同様のシナリオがあります。

サンプルコードを次に示します。

var votes = db.Votes.Where(r => r.SurveyID == surveyId);
if (fromDate != null)
{
    votes = votes.Where(r => r.VoteDate.Value >= fromDate);
}
if (toDate != null)
{
    votes = votes.Where(r => r.VoteDate.Value <= toDate);
}
votes = votes.Take(LimitRows).OrderByDescending(r => r.VoteDate);
12
Xavier John

単純なアプローチは、列が文字列のような単純型である場合です

public static IEnumerable<MyObject> WhereQuery(IEnumerable<MyObject> source, string columnName, string propertyValue)
{
   return source.Where(m => { return m.GetType().GetProperty(columnName).GetValue(m, null).ToString().StartsWith(propertyValue); });
}
8
Nitin Bourai

私も理解できるソリューションを思いつきました...「含む」メソッドを使用することで、好きなだけWHEREを連鎖できます。 WHEREが空の文字列である場合、それは無視されます(または全選択として評価されます)。 LINQで2つのテーブルを結合し、複数のwhere句を適用し、ビューに返されるモデルクラスにデータを入力する例を次に示します。 (これはすべて選択です)。

public ActionResult Index()
    {
        string AssetGroupCode = "";
        string StatusCode = "";
        string SearchString = "";

        var mdl = from a in _db.Assets
                  join t in _db.Tags on a.ASSETID equals t.ASSETID
                  where a.ASSETGROUPCODE.Contains(AssetGroupCode)
                  && a.STATUSCODE.Contains(StatusCode)
                  && (
                  a.PO.Contains(SearchString)
                  || a.MODEL.Contains(SearchString)
                  || a.USERNAME.Contains(SearchString)
                  || a.LOCATION.Contains(SearchString)
                  || t.TAGNUMBER.Contains(SearchString)
                  || t.SERIALNUMBER.Contains(SearchString)
                  )
                  select new AssetListView
                  {
                      AssetId = a.ASSETID,
                      TagId = t.TAGID,
                      PO = a.PO,
                      Model = a.MODEL,
                      UserName = a.USERNAME,
                      Location = a.LOCATION,
                      Tag = t.TAGNUMBER,
                      SerialNum = t.SERIALNUMBER
                  };


        return View(mdl);
    }
5
mike

同じ質問( linqのユーザー定義フィルター )があり、@ tvanfossonがDynamic Linq( http://code.msdn.Microsoft.com/csharpsamples )について教えてくれました。

2
TcKs

条件が含まれているかどうかを動的に決定するために三項演算子を使用する方がはるかに簡単に見える

リストproductList = new List();

        productList =
                db.ProductDetail.Where(p => p.ProductDetailID > 0 //Example prop
                && (String.IsNullOrEmpty(iproductGroupName) ? (true):(p.iproductGroupName.Equals(iproductGroupName)) ) //use ternary operator to make the condition dynamic
                && (ID == 0 ? (true) : (p.ID == IDParam))
                ).ToList();
1
Josué Camacho

Any()拡張メソッドを使用できます。次は私のために働くようです。

XStreamingElement root = new XStreamingElement("Results",
                from el in StreamProductItem(file)
                where fieldsToSearch.Any(s => el.Element(s) != null && el.Element(s).Value.Contains(searchTerm))
                select fieldsToReturn.Select(r => (r == "product") ? el : el.Element(r))
            );
            Console.WriteLine(root.ToString());

ここで、「fieldsToSearch」と「fieldsToReturn」は両方ともListオブジェクトです。

1
Todd DeLand

CodePlexのこのプロジェクトには、あなたが望むものがあります。

System.Linq.Dynamic- http://dynamiclinq.codeplex.com/

プロジェクトの説明

System.Linq.Dynamicを拡張して、Entity FrameworkまたはIQueryableをサポートするプロバイダーに対して文字列で定義されたLambda式の実行をサポートします。

これは Scott Guthrie's Blog にあるソースコードの拡張であるため、次のようなことができます。

enter image description here

そして、このようなもの:

enter image description here

1
Zignd

これは、誰かが興味を持っている場合に私が思いついた解決策です。

https://kellyschronicles.wordpress.com/2017/12/16/dynamic-predicate-for-a-linq-query/

まず、使用する必要がある単一の要素タイプ(Of TRow As DataRow)を特定し、次に使用している「ソース」を特定し、そのソースに識別子を結び付けます((source As TypedTableBase(Of TRow))。次に、述語、または渡されるWHERE句(述語As Func(Of TRow、Boolean))がtrueまたはfalseとして返され、返された情報の順序付け方法(OrderByField As String)を特定します。関数は、述語(EnumerableRowCollection(Of TRow))の条件を満たしたデータ行のコレクションであるEnumerableRowCollection(Of TRow)を返します。これは基本的な例です。もちろん、注文フィールドには、 null、またはその状況を適切に処理し、列名(これを気にせずに厳密に型指定されたデータソースを使用している場合、列の名前を変更する)が標準であることを確認してください。

1
KJM