【问题标题】:LINQ - Joins in a dynamic queryLINQ - 加入动态查询
【发布时间】:2009-05-11 20:58:04
【问题描述】:

由于一些商业决策,我需要改变一些我正在做的事情。耶我。 :)

目前,我有:

public IOrderedQueryable<ProductDetail> GetProductList(string productGroupName, string productTypeName, Dictionary<string,List<string>> filterDictionary)
{
    string whereClause = "ProductGroupName='" + productGroupName + "' AND ProductTypeName='" + productTypeName + "'";
    string comma = "";
    foreach (KeyValuePair<string, List<string>> myKVP in filterDictionary)
    {
        comma = "";
        if (myKVP.Value.Count > 0)
        {
            whereClause = String.Format("{0} AND FieldName = {1} AND FieldValue IN (", whereClause, myKVP.Key);
            foreach (string value in myKVP.Value)
            {
                whereClause = String.Format("{0}{1}'{2}'", whereClause, comma, value);
                comma = ",";
            }
            whereClause = String.Format("{0})", whereClause);
        }
    }

    var q = db.ProductDetail
              .Where (whereClause)
              .OrderBy ("ProductTypeName");
    return q;
}

我现在需要通过其他 2 个表加入来正确应用过滤器,而不是直接使用它。我试图弄清楚如何正确加入动态 LINQ 查询。在 TSQL 中会是这样的:

SELECT pd.* 
  FROM ProductDetail pd
 INNER JOIN ProductFilterAssignment pfa ON pd.ProductID = pfs.ProductID
 INNER JOIN ProductFilter pf ON pfs.FIlterID = pf.FIlterID
 WHERE pf.FieldName = 'var1' AND pf.FieldValue IN ('var1a','var1b','var1c',etc)
   AND pf.FieldName = 'var2' AND pf.FieldValue IN ('var2a','var2b','var2c',etc)

【问题讨论】:

标签: linq dynamic join


【解决方案1】:

哎哟。是的,这是一个复杂的要求。你知道,lambdas 是累积的,所以如果你使用连续的 linq 表达式,你可以更简单地做到这一点。请注意,后续的 linq 表达式正在使用先前的表达式结果,并且整个表达式在迭代之前不会真正执行。

public IOrderedQueryable<ProductDetail> GetProductList(string productGroupName, string productTypeName, Dictionary<string,List<string>> filterDictionary)
{
    // Initial select on productGroupName and productTypeName
    var products = from product in db.ProductDetail
                   where product.ProductGroupName == productGroupName && product.ProductTypeName == productTypeName
                   select product;

    // Now add each filter item present.
    foreach (KeyValuePair<string, List<string>> myKVP in filterDictionary)
    {
        products = from product in products
                   join pfa in db.ProductFilterAssignment on product.ProductID equals pfa.ProductID
                   join pf in db.Product on pfa.FilterID equals pf.FilterId
                   where pf.FieldName == myKVP.Key && myKVP.Value.Contains(pf.FieldValue)
                   select product;
    }

    return products.OrderBy ("ProductTypeName");
}

【讨论】:

    【解决方案2】:

    我没有给你一个好的“答案”,但更多的是一个旁白。查看LINQPad。您甚至可能会在此页面的右侧看到广告。编写 LINQ 查询非常流畅。它可能有助于编写和验证此查询以及您编写的任何其他未来 LINQ 查询。

    【讨论】:

      【解决方案3】:

      尝试使用Spolty Framework。它有助于对 Linq To SQL 和实体框架进行动态查询。您可以动态创建左/内连接、添加条件、排序和其他内容。如果您使用 Spolty 框架,那么您的代码将如下所示:

      public IQueryable<ProductDetail> GetProductList(string productGroupName, string productTypeName, Dictionary<string, List<string>> filterDictionary)
      {
          // create root node 
          JoinNode productDetailNode = new JoinNode(typeof(ProductDetail));
          productDetailNode.AddConditions(new Condition("ProductGroupName", productGroupName),
                          new Condition("ProductTypeName", productTypeName));
      
          // if there are conditions than we create joins
          if (filterDictionary.Count > 0)
          {
              // create joinNode  
              // INNER JOIN ProductFilterAssignment pfa ON pd.ProductID = pfs.ProductID
              JoinNode productFilterAssignmentNode = new JoinNode(typeof(ProductFilterAssignment));
              productDetailNode.AddChildren(productFilterAssignmentNode);
      
              // create joinNode  
              // INNER JOIN ProductFilter pf ON pfs.FIlterID = pf.FIlterID
              JoinNode productFilterNode = new JoinNode(typeof(ProductFilter));
              productFilterNode.AddChildren(productFilterNode);
      
              foreach (KeyValuePair<string, List<string>> myKVP in filterDictionary)
              {
                  // create condition pf.FieldName = {1} And AND pf.FieldValue IN ('var1a','var1b','var1c',etc)
                  productFilterNode.AddConditions(new Condition("FieldName", myKVP.Key),
                                                  OrCondition.Create("FieldValue", myKVP.Value.ToArray()));
              }
          }
      
          // create result query by JoinNode productDetailNode
          QueryDesigner queryDesigner = new QueryDesigner(db, productDetailNode).
                                              OrderBy(new Ordering("ProductTypeName"));
      
          return queryDesigner.Cast<ProductDetail>();
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-10-16
        • 2011-06-13
        • 1970-01-01
        • 1970-01-01
        • 2011-07-05
        • 2021-11-16
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多