【问题标题】:Dynamic WHERE clause in LINQLINQ 中的动态 WHERE 子句
【发布时间】:2010-10-25 07:22:04
【问题描述】:

将动态 WHERE 子句组合到 LINQ 语句的最佳方法是什么?

我在一个表单上有几十个复选框,并将它们作为: Dictionary> (Dictionary>) 传递回我的 LINQ 查询。

public IOrderedQueryable<ProductDetail> GetProductList(string productGroupName, string productTypeName, Dictionary<string,List<string>> filterDictionary)
{
    var q = from c in db.ProductDetail
            where c.ProductGroupName == productGroupName && c.ProductTypeName == productTypeName
            // insert dynamic filter here
            orderby c.ProductTypeName
            select c;
    return q;
}

【问题讨论】:

标签: c# linq dynamic where-clause


【解决方案1】:


(来源:scottgu.com

你需要这样的东西吗?使用the Linq Dynamic Query Library(下载包含示例)。

查看ScottGu's blog 了解更多示例。

【讨论】:

【解决方案2】:

我有类似的场景,我需要根据用户输入添加过滤器并链接 where 子句。

这里是示例代码。

var votes = db.Votes.Where(r => r.SurveyID == surveyId);
if (fromDate != null)
{
    votes = votes.Where(r => r.VoteDate.Value >= fromDate);
}
if (toDate != null)
{
    votes = votes.Where(r => r.VoteDate.Value <= toDate);
}
votes = votes.Take(LimitRows).OrderByDescending(r => r.VoteDate);

【讨论】:

  • 最适合我的需要并且易于使用。谢谢。
  • 绝妙的答案!!
【解决方案3】:

您还可以使用 LinqKit 中的 PredicateBuilder 使用 Or 或 And 链接多个类型安全的 lambda 表达式。

http://www.albahari.com/nutshell/predicatebuilder.aspx

【讨论】:

    【解决方案4】:

    如果您的列是简单类型(如字符串),则可以是一种简单的方法

    public static IEnumerable<MyObject> WhereQuery(IEnumerable<MyObject> source, string columnName, string propertyValue)
    {
       return source.Where(m => { return m.GetType().GetProperty(columnName).GetValue(m, null).ToString().StartsWith(propertyValue); });
    }
    

    【讨论】:

    • 我的应用程序抱怨无法将其转换为 SQL(我正在使用 Postgres 提供程序)。也许您的代码在内存中而不是在数据库中运行?这会导致在大型数据集上表现不佳。
    【解决方案5】:

    使用三元运算符动态决定是否包含条件似乎更简单更简单

    列出 productList = new List();

            productList =
                    db.ProductDetail.Where(p => p.ProductDetailID > 0 //Example prop
                    && (String.IsNullOrEmpty(iproductGroupName) ? (true):(p.iproductGroupName.Equals(iproductGroupName)) ) //use ternary operator to make the condition dynamic
                    && (ID == 0 ? (true) : (p.ID == IDParam))
                    ).ToList();
    

    【讨论】:

      【解决方案6】:

      我想出了一个即使我也能理解的解决方案...通过使用“包含”方法,您可以链接任意数量的 WHERE。如果 WHERE 是一个空字符串,它将被忽略(或评估为全选)。这是我在 LINQ 中连接 2 个表、应用多个 where 子句并填充要返回到视图的模型类的示例。 (这是全选)。

      public ActionResult Index()
          {
              string AssetGroupCode = "";
              string StatusCode = "";
              string SearchString = "";
      
              var mdl = from a in _db.Assets
                        join t in _db.Tags on a.ASSETID equals t.ASSETID
                        where a.ASSETGROUPCODE.Contains(AssetGroupCode)
                        && a.STATUSCODE.Contains(StatusCode)
                        && (
                        a.PO.Contains(SearchString)
                        || a.MODEL.Contains(SearchString)
                        || a.USERNAME.Contains(SearchString)
                        || a.LOCATION.Contains(SearchString)
                        || t.TAGNUMBER.Contains(SearchString)
                        || t.SERIALNUMBER.Contains(SearchString)
                        )
                        select new AssetListView
                        {
                            AssetId = a.ASSETID,
                            TagId = t.TAGID,
                            PO = a.PO,
                            Model = a.MODEL,
                            UserName = a.USERNAME,
                            Location = a.LOCATION,
                            Tag = t.TAGNUMBER,
                            SerialNum = t.SERIALNUMBER
                        };
      
      
              return View(mdl);
          }
      

      【讨论】:

      • 除了字符串还有可能做吗?
      【解决方案7】:

      您可以使用 Any() 扩展方法。以下似乎对我有用。

      XStreamingElement root = new XStreamingElement("Results",
                      from el in StreamProductItem(file)
                      where fieldsToSearch.Any(s => el.Element(s) != null && el.Element(s).Value.Contains(searchTerm))
                      select fieldsToReturn.Select(r => (r == "product") ? el : el.Element(r))
                  );
                  Console.WriteLine(root.ToString());
      

      其中 'fieldsToSearch' 和 'fieldsToReturn' 都是 List 对象。

      【讨论】:

        【解决方案8】:

        CodePlex 上的这个项目有你想要的。

        System.Linq.Dynamic - http://dynamiclinq.codeplex.com/

        项目描述

        扩展 System.Linq.Dynamic 以支持针对实体框架或任何支持 IQueryable 的提供程序执行在字符串中定义的 Lambda 表达式。

        由于它是您可以在 Scott Guthrie's Blog 上找到的源代码的扩展,因此您可以执行以下操作:

        还有这样的事情:

        【讨论】:

          【解决方案9】:

          如果有人感兴趣,这是我想出的解决方案。

          https://kellyschronicles.wordpress.com/2017/12/16/dynamic-predicate-for-a-linq-query/

          首先我们确定我们需要使用的单个元素类型(Of TRow As DataRow),然后确定我们正在使用的“源”并将标识符绑定到该源((source As TypedTableBase(Of TRow))。然后我们必须指定谓词,或者将要传递的 WHERE 子句(谓词 As Func(Of TRow, Boolean)),它将被返回为 true 或 false。然后我们确定我们希望返回的信息如何排序(OrderByField As String ). 然后我们的函数将返回一个 EnumerableRowCollection(Of TRow),我们的数据行集合满足我们的谓词 (EnumerableRowCollection(Of TRow)) 的条件。这是一个基本示例。当然,您必须确保您的订单字段不'不包含空值,或已正确处理这种情况并确保您的列名(如果您使用的是强类型数据源,请不要介意这一点,它会为您重命名列)是标准的。

          【讨论】:

          【解决方案10】:

          只是为了分享我对这个案例的想法。

          另一种解决方法是:

          
          public IOrderedQueryable GetProductList(string productGroupName, string productTypeName, Dictionary> filterDictionary)
          {
              return db.ProductDetail
                  .where
                  (
                      p =>
                      (
                          (String.IsNullOrEmpty(productGroupName) || c.ProductGroupName.Contains(productGroupName))
                          && (String.IsNullOrEmpty(productTypeName) || c.ProductTypeName.Contains(productTypeName))
                          // Apply similar logic to filterDictionary parameter here !!!
                      )
                  );  
          }
          

          这种方法非常灵活,允许任何参数都可以为空。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2023-03-29
            • 2012-02-25
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-01-15
            相关资源
            最近更新 更多