简体   繁体   English

建立动态LINQ查询的最佳方法是什么?

[英]What is the best approach to build dynamic LINQ queries?

Thanks to those who answered my last couple questions, I got the following code to work which allows you to send a collection of Where clauses to a method which are all attached to a LINQ query. 感谢那些回答了我最后几个问题的人,我使以下代码可以正常工作 ,它使您可以将Where子句集合发送到方法,这些子句都附加到LINQ查询中。 This is going to work for the case at hand that I need. 这将适用于我需要的手头案例。

However, what is the best approach to extend this so that: 但是,最好的扩展方法是:

  • OrderBy clauses can be sent 可以发送OrderBy子句
  • Where clauses can be combined with "OR" logic and not only with "AND" logic where子句可以与“ OR”逻辑结合,而不仅可以与“ AND”逻辑结合
  • other options can be sent dynamically, eg what fields are included in the object sent back (eg so that it does not always have to be Customer, in the example below) 其他选项可以动态发送,例如,在发送回的对象中包含哪些字段(例如,在下面的示例中,它不必总是客户)

Basically, the background of this is to be able to dynamically build a LINQ query from this form a parsed configuration file or from user input. 基本上,这样做的背景是能够从此形式以解析的配置文件或用户输入动态构建LINQ查询。

The task reminds me of building classes which could dynamically produce SQL statements based on parameters, but that involved building a string (SQL Statement) which was more straight-forward than dynamically building a LINQ query. 该任务使我想起了构建可以根据参数动态生成SQL语句的类,但是涉及到构建一个字符串 (SQL语句),该字符串比动态构建LINQ查询更直接。

There are many Stackoverflow questions and blog posts about this topic, but they each seem to be individual solutions to individual problems, but is there an API or library that is emerging as a standard for building dynamic LINQ queries, eg so I can easily take a DSL syntax and translate it into LINQ, eg "FirstName startswith 'a' and (state='co' or state='ca')"? 关于此主题有很多Stackoverflow问题和博客文章 ,但是它们似乎都是针对单个问题的单独解决方案,但是是否有API或库正在逐渐成为构建动态LINQ查询的标准,例如, 因此我可以轻松地采用DSL语法并将其转换为LINQ,例如“ FirstName以'a'和(state ='co'或state ='ca')开头”吗?

using System;
using System.Collections.Generic;
using System.Linq;

namespace TestDynamicLinq2343
{
    public class Program
    {
        static void Main(string[] args)
        {
            List<Customer> customers = Customer.GetCustomers();

            List<Func<Customer, bool>> whereClauses = new List<Func<Customer, bool>>();
            whereClauses.Add(c => c.LastName.ToUpper().Contains("A"));
            whereClauses.Add(c => c.FirstName.ToUpper().Contains("O"));
            whereClauses.Add(c => c.FirstName.ToUpper().Contains("E"));

            foreach (var customer in Customer.GetFilteredCustomers(customers, whereClauses))
            {
                Console.WriteLine(customer.LastName);
            }

            Console.ReadLine();
        }
    }

    public class Customer
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Street { get; set; }
        public string Location { get; set; }
        public string ZipCode { get; set; }

        public static List<Customer> GetCustomers()
        {
            List<Customer> customers = new List<Customer>();
            customers.Add(new Customer { FirstName = "Jim", LastName = "Jones" });
            customers.Add(new Customer { FirstName = "Joe", LastName = "Adams" });
            customers.Add(new Customer { FirstName = "Jake", LastName = "Johnson" });
            customers.Add(new Customer { FirstName = "Angie", LastName = "Reckar" });
            customers.Add(new Customer { FirstName = "Jean", LastName = "Anderson" });
            return customers;
        }

        public static List<Customer> GetFilteredCustomers(List<Customer> customers, List<Func<Customer, bool>> whereClauses)
        {
            IEnumerable<Customer> dbCustomers = customers;
            foreach (var whereClause in whereClauses)
            {
                dbCustomers = dbCustomers.Where(whereClause);
            }
            return dbCustomers.ToList();
        }
    }
}

Dynamic query building is somehow tedious task. 动态查询构建是一个繁琐的任务。 Please visit PredicateBuilder . 请访问PredicateBuilder You can get insights on how dynamic quires are built. 您可以了解如何构建动态查询。

I can certainly second the suggestion of PredicateBuilder as a useful tool, and is the best way around the OR problem. 我当然可以将PredicateBuilder的建议作为有用的工具,这是解决OR问题的最佳方法。 There is also the Microsoft Dynamic LINQ library which I have used occasionally, and might work with your suggestion of passing clauses from a config file. 还有我偶尔使用的Microsoft Dynamic LINQ库 ,它可能与您建议从配置文件传递子句一起使用。

In most cases when I have needed some element of dynamic querying I have usually ended up coding for particular problems directly much as you have done above. 在大多数情况下,当我需要动态查询的某些元素时,我通常会像上面所做的那样直接结束对特定问题的编码。 I have a couple of quite complex functions in live systems that start with a basic root query, and then add a number of extra Where and OrderBy clauses dependant on the parameters passed to the function. 我在实时系统中有几个非常复杂的功能,这些功能从基本的根查询开始,然后根据传递给函数的参数添加一些额外的WhereOrderBy子句。

Although most of the LINQ examples seem to show relatively simple queries, the LINQ libraries are pretty powerful allowing you to gradually build up your query step by step, and then only generating the actual query when it is executed, hence I tend to favour just using chained operators rather than the query comprehension syntax. 尽管大多数LINQ示例似乎都显示了相对简单的查询,但是LINQ库功能非常强大,可让您逐步建立查询,然后仅在执行查询时才生成实际查询,因此我倾向于只使用链式运算符,而不是查询理解语法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM