2011-10-28 9 views
0

私は書く必要があるかなり複雑な質問があります。私は可能な場合、SQLにLinqを使用してそれを行うことを望んでいます。データベースには、このようなものです:sqlに動的linqを使用して子テーブルを照会していますか?

お客様(最初、最後、ID、性別)
受注(日付、数量、重量、ItemNameの、価格)
住所(市、州、郵便番号)

クエリは、ユーザがこれらのフィールドのいずれかを検索し、数字フィールドの場合は、<、=、または>を検索させることになります。

このような何か私が実装するために必要だサンプルクエリのようになります。

クエリ1:最初の名前= 'ジョン を選択し、顧客と(体重> 40または量を有する少なくとも一つの順序を持​​っています>

クエリ2: 名前が「John」で、重量が<、商品名=「ウィジェット」、数量= 10の注文が1つ以上ある顧客を選択してください。また、郵便番号= 12345となります。 zipcode = 12345.

私はfの検索の基本部分を得ることができますまたは顧客であるが、ユーザーが< =をORで指定できるOrderテーブルを検索することに固執している。

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を使用することができます。これは、ラムダを述語ためにいくつかの新しい拡張メソッドを追加します。

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); 

あなたはEntity Frameworkのを使用している場合は、照会可能に引数として渡す、または.AsExpandable()前の述語の.Expand()を呼び出す必要があります。

+0

ありがとうございます。素晴らしい答え。私は副述語で.Compile()を呼び出さなければなりませんでした。残念ながら私の質問は正確に正しいとは思わなかった。 – David

+0

.Compile()は、式を代理人に変換する。 –

+0

実際のクエリを使用するためにそれを書き直した後、私はもはやExpand()、AsExpandable()、またはCompile()を必要としませんが、それは美しく働いています。 – David

関連する問題