LINQ - присоединяется к динамическому запросу - PullRequest
3 голосов
/ 12 мая 2009

Из-за некоторых бизнес-решений мне нужно немного изменить то, что я делал. Ты меня. :)

В настоящее время у меня есть:

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)

Ответы [ 3 ]

6 голосов
/ 12 мая 2009

Уч. Да, это сложное требование. Вы знаете, что лямбды являются кумулятивными, поэтому вы можете сделать это намного проще, если будете использовать последовательные выражения 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");
}
0 голосов
/ 12 августа 2009

Попробуйте использовать Spolty Framework . Это помогает делать динамический запрос для Linq To SQL и Entity Framework. Вы можете динамически создавать левое / внутреннее соединение, добавлять условия, упорядочения и другие вещи. Если вы используете Spolty Framework, ваш код будет выглядеть следующим образом:

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>();
}
0 голосов
/ 12 мая 2009

У меня нет хорошего «ответа» для вас, но больше в стороне. Проверьте LINQPad . Вы также можете увидеть рекламу в правой части этой страницы. Это очень удобно для написания запросов LINQ. Это может помочь в написании и проверке этого и любого другого будущего запроса LINQ, который вы напишите.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...