2012-05-16 3 views
6

をサポートしていない私は、エンティティへのLINQで次のクエリを持っている:LINQは、Invoke

var query = from p in db.Products 
      where p.Price > 10M 
      select p; 

この時点でクエリが実行されていない、と私はベースの真/偽を返しますクエリを書きたいです

return query.Any(p => p.IsInStock && 
       (p.Category == "Beverage" || 
       p.Category == "Other")); 

これは問題なく動作します。しかし、私はコードからいくつかの再利用を取得したいと思います。

return query.Any(p => p.IsInStock && eligibleForDiscount(p)); 

Func<Product, bool> eligibleForDiscount = (product) => product.Category == "Beverage" || product.Category == "Other"; 

私は、デリゲートとインライン検査を代用したい:私はカテゴリが飲料またはその他の場合に基づいてフィルタリングする必要がある多くのメソッドを持っているので、私は、デリゲートを作成してみました

これはLINQ to EntitiesがInvokeをサポートしていないというエラーを表示します。なぜ私はこのようなデリゲートのインラインコードを置き換えることができないのですか?また、他の方法で再利用できる方法はありますか?

+1

可能[LINQ式ノードタイプの「起動」は、エンティティフレームワークでエンティティへのLINQでサポートされていない](HTTPの複製:// stackoverflowの

public IQueryable<Product> EligibleForDiscount(IQueryable<Product> products) { return products.Where(p => product.Category == "Beverage" || product.Category == "Other"); } 

は今、他の関数と同じようにそれを呼び出します。com/questions/8741667/the-linq-expression-node-type-in​​voke-is-in-lin-to-entities-in-e) –

+2

この質問には受け入れられた回答がなく、このPredicateBuilderのアイデアは、私はこの質問を重複とはみなしません。 – Dismissile

答えて

6

フードの下でLinq-to-{DATABASE}は、あなたが作成したIQueryableをSqlに変換していることを思い出してください。

あなたはそのようなインラインコードすることはできませんInvoke(あなたがFuncActionを呼び出すときに、実際に呼び出しているメソッドは)(あなたがを行うことができ、SQL文にそれを変換する一貫した方法がありませんので、そこで)。

var query = from p in db.Products 
      where p.Price > 10M 
      select p; 

query = query.Where(p => p.IsInStock); 
query = query.Where(p => p.Category == "Beverage" || p.Category == "Other"); 
return query.Any(); 

ものはIQueryable<Product>を取ると同じ(ただし、フィルタ処理)を返すメソッドに入れることができます両方:あなたはそれを分割することにより、部品を再利用することができた

。その後、あなたの心のコンテンツに再利用することができます!

+0

あなたの提案は、IQueryable を受け取り、デリゲートの代わりにIQueryable を返すメソッドを持つことです。私は彼らが同じことをしていると思います:) – Dismissile

+0

彼らはまったく同じことを行い、はるかに再利用可能です... IQueryableを受け取り、IQueryableを返すメソッドと関数は、とても強力です。 – Crisfole

+1

追加のボーナスとして、これはまた、IQuery可能なインターフェイスでquery.WhereIsInAnyCategory( "Beverage"、 "Other")(またはquery.WhereBeverageOrOther())型の構文を提供する拡張メソッドにすることもできます。 – MerickOWA

2

IQueryableは、RDBMSに渡すSQL式を生成する必要があり、すべてが不透明な述語である場合には実行できないという問題があります。以下のようになり

return query.Where(p => p.IsInStock).AsEnumerable().Any(eligibleForDiscount); 

少ない些細な方法は、次のとおりです:このメソッドが取る方法の代わりに、述語の

bool GotEligible(Expression<Func<Product,bool>> pred) { 
    return query.Where(p => p.IsInStock).Any(pred); 
} 

注意を

明白ですが非効率な方法は、次のようにクエリを書き直すことです述語式。これで、EFに対して透過的になり、問題なくSQLクエリーに変換できます。

+0

btw、 'Any'句で'(p) 'を取り除きたい場合 – Crisfole

+0

@ChristopherPfohlはい、そうです!ありがとう! – dasblinkenlight

+0

そして*おそらくあなたは 'GotEligible'を意味しました;) – Crisfole

0

限り、あなたはのIQueryableに固執として、あなたは関数内で再利用可能なquerysを維持することができます。

IQueryable<Product> query = (from p in db.Products 
           where p.Price > 10M 
           select p); 

    query = EligibleForDiscount(query);