このLINQ SQLを動的クエリとして(文字列を使用して)書き込む方法は?
-
22-09-2019 - |
質問
必要に応じて「特定の質問」にスキップします。いくつかの背景:
シナリオ: DDLSが入力された「ドリルダウン」フィルター(クエリオブジェクト)を備えた一連の製品があります。各プログレッシブDDL選択により、製品リストとDDLSのオプションがさらに制限されます。たとえば、ツールからハンマーを選択すると、製品のサイズがハンマーサイズのみを表示するように制限されます。
現在のセットアップ: クエリオブジェクトを作成し、リポジトリに送信し、各オプションをSQL「テーブル値関数」に供給し、ヌル値が「すべての製品を取得」を表します。
私はこれを良い努力だと考えていますが、DDDとはほど遠いものです。 SQLでの「プログラミング」を避けたいと思います。このトピックに関するコメントをいただければ幸いです。
具体的な質問:
このクエリをaとして書き直すにはどうすればよいですか 動的クエリ?のようなものへのリンク 101 linqの例 素晴らしいですが、動的なクエリスコープがあります。私は本当にこの方法に渡したいと思っています。
from p in db.Products
group p by p.ProductSize into g
select new Category {
PropertyType = g.Key,
Count = g.Count() }
各DDLオプションには「選択(21)」があり、(21)はその属性を持つ製品の量です。オプションを選択すると、他のすべての残りのDDLは、残りのオプションとカウントで更新されます。
編集:追加メモ:
.OrderBy("it.City") // "it" refers to the entire record
.GroupBy("City", "new(City)") // This produces a unique list of City
.Select("it.Count()") //This gives a list of counts... getting closer
.Select("key") // Selects a list of unique City
.Select("new (key, count() as string)") // +1 to me LOL. key is a row of group
.GroupBy("new (City, Manufacturer)", "City") // New = list of fields to group by
.GroupBy("City", "new (Manufacturer, Size)") // Second parameter is a projection
Product
.Where("ProductType == @0", "Maps")
.GroupBy("new(City)", "new ( null as string)")// Projection not available later?
.Select("new (key.City, it.count() as string)")// GroupBy new makes key an object
Product
.Where("ProductType == @0", "Maps")
.GroupBy("new(City)", "new ( null as string)")// Projection not available later?
.Select("new (key.City, it as object)")// the it object is the result of GroupBy
var a = Product
.Where("ProductType == @0", "Maps")
.GroupBy("@0", "it", "City") // This fails to group Product at all
.Select("new ( Key, it as Product )"); // "it" is property cast though
私がこれまでに学んだことはです linqpad 素晴らしいですが、それでも答えを探しています。最終的に、このような完全にランダムな研究が私が推測するでしょう。笑。
編集:
ジョン・スキートには素晴らしいアイデアがありました:私が必要とするものをキャストする IGrouping<string, Product>
. 。 Jon Skeetに感謝します!オブジェクトをキャストしたら、セットに列挙して、結果を別のリストに送ることができます。
解決
(上記のように)クエリ構文を使用してこれを行う方法はわかりませんが、メソッド構文を使用して、式を使用できます
using System;
using System.Linq;
using System.Linq.Expressions;
namespace LinqResearch
{
public class Program
{
[STAThread]
static void Main()
{
string columnToGroupBy = "Size";
// generate the dynamic Expression<Func<Product, string>>
ParameterExpression p = Expression.Parameter(typeof(Product), "p");
var selector = Expression.Lambda<Func<Product, string>>(
Expression.Property(p, columnToGroupBy),
p
);
using (LinqDataContext dataContext = new LinqDataContext())
{
/* using "selector" caluclated above which is automatically
compiled when the query runs */
var results = dataContext
.Products
.GroupBy(selector)
.Select((group) => new {
Key = group.Key,
Count = group.Count()
});
foreach(var result in results)
Console.WriteLine("{0}: {1}", result.Key, result.Count);
}
Console.ReadKey();
}
}
}
他のヒント
あなたが見ているなら C#ビット, 、著者は、動的データを使用してカスケードフィルターを作成する方法について説明します。動的なデータを使用しているようには聞こえませんが、彼はあなたに役立つかもしれない素敵な表現ビルダーを持っています。 BuildQueryBody、次にiQueryableの拡張メソッドの次のセクションを参照してください。
動的データを使用していないため、「MetaForeignkeycolumn」オブジェクトにアクセスできないことに対処する必要がありますが、彼のアプローチがあなたの質問に役立つと思います。
これが役立つことを願っています。