2011-10-28 96 views
0

我有一個相當複雜的查詢,我需要寫。如果可能,我希望使用Linq to Sql來完成它。該數據庫是這樣的:用動態LINQ查詢子表到sql?

客戶(第一,最後,ID,性別)
訂單(日期,數量,重量,ITEMNAME,價格)
地址(城市,州,郵編)

該查詢將讓用戶通過任何這些字段進行搜索,並且在數字字段的情況下,按照他們的期望搜索<,=,或>。

像這樣的事情將是我需要實現簡單的查詢:

查詢1: 選擇客戶,其中第一名稱=「約翰」,並至少有一個訂單與(重量> 40或數量> 10或價格> 5)和郵政編碼= 12345

問題2: 選擇客戶其中第一名稱=「約翰」和具有至少一個以便與重量< 20和ITEMNAME =「插件」和數量= 10)和zipcode = 12345.

我可以得到搜索的基本部分f或客戶,但我堅持搜索訂單表,用戶可以用OR方式指定<> =。

query = Context.Customers.AsQueryable(); 
if (searchingFirstName) query = query.Where(cust => cust.First == firstName); 
if (searchingLastName) query = query.Where(cust => cust.Last == lastName); 
if (searchingZip) query = query.Where(cust => cust.Address.Zip == zip); 

// using dynamic Linq 
if (searchingGender) query = query.Where("Gender == @0", gender); 

// how do I search the Orders? The dynamic linq functions appear 
// to only work on the top level table 

回答

1

你可以從LinqKit使用PredicateBuilder。它增加了一些新的擴展方法,lambda表達式斷言:

var predicate = PredicateBuilder.True<Customer>(); 

if (searchingFirstName) 
{ 
    predicate = predicate.And(cust => cust.First == firstName); 
} 

if (searchingOrders) 
{ 
    // Some code to unify the .And() and .Or() cases 
    Expression<Func<Order, bool>> subpredicate; 
    Func<Expression<Func<Order, bool>>, Expression<Func<Order, bool>>, Expression<Func<Order, bool>>> joiner; 
    if (orderMethodAny) 
    { 
     subpredicate = PredicateBuilder.True<Order>(); 
     joiner = PredicateBuilder.And; 
    } 
    else 
    { 
     subpredicate = PredicateBuilder.False<Order>(); 
     joiner = PredicateBuilder.Or; 
    } 

    if (searchingOrderDate) 
    { 
     // ... 
    } 

    if (searchingOrderWeight) 
    { 
     switch (orderOp) 
     { 
      case Op.Less: 
       subpredicate = joiner(subpredicate, ord => ord.Weight < orderWeight); 
       break; 
      case Op.LessEqual: 
       subpredicate = joiner(subpredicate, ord => ord.Weight <= orderWeight); 
       break; 
      case Op.Equal: 
       subpredicate = joiner(subpredicate, ord => ord.Weight == orderWeight); 
       break; 
      case Op.GreaterEqual: 
       subpredicate = joiner(subpredicate, ord => ord.Weight >= orderWeight); 
       break; 
      case Op.Greater: 
       subpredicate = joiner(subpredicate, ord => ord.Weight > orderWeight); 
       break; 
      case Op.NotEqual: 
       subpredicate = joiner(subpredicate, ord => ord.Weight != orderWeight); 
       break; 
     } 
    } 

    if (searchingOrderQuantity) 
    { 
     // ... 
    } 

    if (searchingOrderItemName) 
    { 
     // ... 
    } 

    if (searchingOrderPrice) 
    { 
     // ... 
    } 

    predicate = predicate.And(cust => cust.Orders.Any(subpredicate)); 
} 

if (searchingZipCode) 
{ 
    predicate = predicate.And(cust => cust.ZipCode == zipCode); 
} 

var query = Context.Customers.Where(predicate); 

您可能需要將它們作爲參數,或.AsExpandable()上可查詢前呼籲謂詞.Expand(),如果您使用的是實體框架。

+0

非常感謝。很好的答案。我不得不在subpredicate上調用.Compile()。 (cust => cust.Orders.Any(subpredicate.Compile());不幸的是,我意識到現在我的問題並不完全正確。 – David

+0

.Compile()會將表達式轉換爲委託。系統在客戶端而不是數據庫上執行過濾 –

+0

在重寫它以使用實際查詢之後,我不再需要任何Expand(),AsExpandable()或Compile(),但它的工作非常精美。 – David