LINQ:クエリフィルターの動的構築

確かに、遅かれ早かれ、各開発者は列などでソートできるデータテーブルを作成する必要がありました。私も例外ではありません。 このプロジェクトでは、ほぼすべてのページに同様のテーブルがあり、コンテンツの90%がそれらを通して表示されていると言えます。 もちろん、テーブルによる検索とソートは、ページをリロードすることなく機能します。







もちろん、APIコントローラーメソッドのセマンティクスを無限のシートに拡張することは絶対に非現実的であり、すべてのテーブルに共通のソリューションが必要でした。 反射と表現の木は彼を見つけるのに役立ちました。













クライアントでデータを取得し、JSONオブジェクトとしてサーバーに転送するためのフィルターを作成することは、要求ファクトリーに多数の条件を掛けるよりもはるかに便利であると判断しました。







どのように見えますか



ユーザーと彼が所有する車のモデルがあるとします。







public class User { public int Id { get; set; } public string Name { get; set; } public int Age { get; set; } public IEnumerable<Car> Cars { get; set; } } public class Car { public int CarId { get; set; } public string Model { get; set; } public int MaxSpeed { get; set; } }
      
      





名前がAで始まり、車の速度が300 km / hを超えるか、IDが0を超えるユーザーを取得し、IDの昇順で降順に並べ替えます。 これを行うには、次のオブジェクトを作成します。







 { "Where": { "OperatorType": "Or", "Operands": [ { "OperatorType": "And", "Operands": [ { "Field": "Name", "FilterType": "StartsWith", "Value": "A" }, { "Field": "Cars.MaxSpeed", "FilterType": "GreaterThan", "Value": 300 } ] }, { "Field": "Id", "FilterType": "GreaterThan", "Value": 0 } ] }, "OrderBy": [ { "Field": "Name", }, { "Field": "Flag", "Order": "Desc" } ], }
      
      





結果は、オペランドが無制限にネストされたオブジェクトであり、非常に大きなフィルターを作成できることがわかります。







このフィルターをデータ選択に適用することは残ります。 サーバーに転送し、小さなオブジェクトではなくペイントしないjsonオブジェクトをデシリアライズする方法。







 FilterContainer filter = ...; //   IQueryable<User> query = dataAccess.MyUsers; query = query.Request(filter); //  ////query = query.Where(filter.Where).OrderBy(filter.OrderBy);
      
      





これがサンプル全体です。







Entity FrameworkまたはLinq2SQLタイプのORMは、式ツリーを使用してデータソースへの構造化クエリを表すことを、多くの人が知っていますが、知りません。 クエリプロバイダーは、式ツリーのデータ構造を調べて、クエリ言語に変換できます。







リフレクションにより、フィルターコレクターはエンティティの対応するメンバーから再帰的にクエリツリーを構築します。







githubのプロジェクトでは、すべてのろ過方法とタイプが考慮されています。







PS原則として、私はこのタスクで発見者の役職に頼りませんでした。これは既に何らかの形で行われています。 いずれにせよ、それは素晴らしい経験でした。








All Articles