【问题标题】:Dynamically build up a linq query with hierarchy using string field names?使用字符串字段名称动态构建具有层次结构的 linq 查询?
【发布时间】:2014-05-13 01:01:08
【问题描述】:

我很难过.. 我需要在运行时提供一个对象列表、几个字段名称数组作为字符串(分组依据、排序依据和选择),并且以某种方式生成一个 LINQ 查询以返回一个用于 JSON 序列化的对象。

我在设置下方构建了一个示例重现。 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;
        }
    }
}

【问题讨论】:

    标签: c# linq linq-to-objects


    【解决方案1】:

    请查看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 提出的解决方案,看看哪个解决方案更适合您的需求,您需要做一些工作来适应您的需求。

    【讨论】:

    • 我将如何动态执行此操作?我需要以某种方式迭代数组,然后一次添加这些..
    【解决方案2】:

    Linq 语法实际上是围绕在编译时了解数据的静态结构而构建的。底层System.Linq.Expressions 命名空间具有创建运行时的巨大能力,而不是编译时间、绑定,但这是一项相当劳动密集型的工作。

    为了支持输入和输出的动态类型,最好使用一些库。

    @Sergio 建议的动态 Linq 是一种选择。

    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);
    }
    

    【讨论】:

    • 好一个,我不知道。在您发现表达式树背后的力量之后,Linq 将不再一样。
    猜你喜欢
    • 1970-01-01
    • 2014-10-27
    • 1970-01-01
    • 1970-01-01
    • 2011-09-19
    • 1970-01-01
    • 2011-03-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多