簡體   English   中英

使用字符串字段名稱動態構建帶層次結構的linq查詢?

[英]Dynamically build up a linq query with hierarchy using string field names?

我很難過..我需要取一個對象的平面列表,一些字段名稱數組作為字符串(分組,分類,選擇哪個)在運行時提供並以某種方式生成LINQ查詢返回JSON序列化的對象。

我在設置下面構建了一個示例repro。 OrderBy很簡單,我只是使用GetType()。GetProperty()來查找正確的屬性,並將orderby字段迭代到菊花鏈.OrderBy調用。 這一切都在GroupBy上崩潰,因為每個人都將結果包裝在IEnumerable>中。

有沒有辦法做到這一點? 我在網上找到的所有東西都讓人們訴諸於良好的舊遞歸程序代碼。 LINQ必須有辦法做到這一點,但我迷路了。 我嘗試的一切都不會編譯,類型只是不匹配..

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Linq.Dynamic;

namespace linqtest2
{
    class Program
    {
        static void Main(string[] args)
        {
            var products = new List<Product>
                {
                    new Product("Food", "Fruit", "Apple"),
                    new Product("Food", "Fruit", "Banana"),
                    new Product("Food", "Fruit", "Orange"),
                    new Product("Food", "Vegetables", "Carrot"),
                    new Product("Food", "Vegetables", "Pea"),
                    new Product("Drink", "Soft Drink", "Orange Juice"),
                    new Product("Drink", "Soft Drink", "Lemonade"),
                    new Product("Drink", "Alcoholic", "Bitter"),
                    new Product("Drink", "Alcoholic", "Lager"),
                    new Product("Drink", "Alcoholic", "Vodka")
                };

            string[] select = new[] { "Category", "Name" };
            string[] orderBy = new[] { "Name", "Category" };
            string[] groupBy = new[] { "Category", "Subcategory" };
        }
    }

    public class Product
    {
        public string Name { get; set; }
        public string Category { get; set; }
        public string Subcategory { get; set; }

        public Product(string category, string subcategory, string name)
        {
            Category = category;
            Subcategory = subcategory;
            Name = name;
        }
    }
}

請檢查Dynamic Linq庫,它提供了一種使用字符串而不是lambdas的方法。

使用動態linq,您可以編寫:

products.OrderBy("Category").ThenBy("Name")

還有很多其他的可能性。

編輯:

更新解決方案以使其更具動態性

IQueryable<Product> query = products;
bool firstOrderBy = true;
foreach(var orderExpression in orderBy)
{
    if (firstOrderBy)
    {
        query = query.OrderBy(orderExpression);
        firstOrderBy = false;
    }
    else
    {
        query = query.ThenBy(orderExpression);
    }
}

正如我建議的那樣,驗證庫,探索它並根據您的需要進行調整。 您也可以使用它來進行GroupBySelect

還要檢查@dkackman提出的解決方案,看看哪種解決方案更適合您的需求,您需要做一些解決方案來滿足您的需求。

Linq語法實際上是在編譯時知道數據的靜態結構。 底層System.Linq.Expressions命名空間具有創建運行時的巨大功能,而不是編譯時綁定,但是在使用時它是相當費力的。

為了支持輸入和輸出的動態類型,最好通過使用一些庫來實現。

動態Linq作為@Sergio建議是一種選擇。

SqlLinq是另一個。 使用SqlLinq,您將以字符串形式動態構建整個查詢,並執行如下操作:

var products = new List<Product>
    {
        new Product("Food", "Fruit", "Apple"),
        new Product("Food", "Fruit", "Banana"),
        new Product("Food", "Fruit", "Orange"),
        new Product("Food", "Vegetables", "Carrot"),
        new Product("Food", "Vegetables", "Pea"),
        new Product("Drink", "Soft Drink", "Orange Juice"),
        new Product("Drink", "Soft Drink", "Lemonade"),
        new Product("Drink", "Alcoholic", "Bitter"),
        new Product("Drink", "Alcoholic", "Lager"),
        new Product("Drink", "Alcoholic", "Vodka")
    };

var results = products.Query<Product, dynamic>("SELECT category, subcategory, count(*) AS cnt FROM this GROUP BY category, subcategory ORDER BY category, subcategory");

foreach(dynamic d in results)
{
    Debug.WriteLine("{0} {1} {2}", (string)d.category, (string)d.subcategory, (int)d.cnt);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM