2009-05-11 2 views
3

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

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

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) 
+0

Я также нашел эту ссылку, которая рассказывает о преобразовании SQL в LINQ. Это может быть полезно: http://blogs.msdn.com/vbteam/archive/tags/Converting+SQL+to+LINQ/default.aspx. Это для VB.NET, но материал там должен быть полезен для C#. –

ответ

6

Ouch. Да, это сложное требование. Вы знаете, 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"); 
} 
0

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

0

Попробуйте использовать 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>(); 
} 
Смежные вопросы