2011-05-30 42 views
2

このプロジェクトはEF4でセットアップされており、LINQ to Entitiesを使用してクエリを作成しています。LINQ to Entities - 条件付きwhere句付きの左外部結合

多くの条件付きwhere文節といくつかの左外部結合を含むクエリで何らかの問題が発生しています。

私は部分的に次の拡張方法(これは私が見つけたhere)で条件節を解決しました。

public static IQueryable<TSource> WhereIf<TSource>(this IQueryable<TSource> source, bool condition, Expression<Func<TSource, bool>> predicate) 
    { 
     if (condition) 
      return source.Where(predicate); 
     else 
      return source; 
    } 

私が今問題にしているのは、LINQ to Entitiesは、結合されたテーブルで使用するときに拡張メソッドを認識しないということです。

ここでは、クエリの一部です:

from p in context.Entities.OfType<Patient>() 
    .WhereIf(!string.IsNullOrEmpty(name), p => p.Name.Contains(name)) 
from c in context.Contacts 
    .Where(cp => cp.EntityID == p.EntityId).DefaultIfEmpty() 
    .WhereIf(timestamp != null, c => c.Timestamp > timestamp) 

私は部分的に、それは、このクエリでうまく初めて(患者名)を動作するために解決が、2番目の時間(タイムスタンプ)、それは私にこのエラーを与えると言います:

LINQ to Entities does not recognize the method 'System.Linq.IQueryable`1[x.Contact] WhereIf[Contact](System.Linq.IQueryable`1[x.Contact], Boolean, System.Linq.Expressions.Expression`1[System.Func`2[x.Contact,System.Boolean]])' method, and this method cannot be translated into a store expression. 

私はこれをどのように修正できるか知っていますか?

答えて

4

SelectManyの中にEFがWhereIfを認識できないという問題があります。メソッドの構文にクエリを書き換え(クエリが不完全である)このようなものが得られます。

context.Entities.OfType<Patient>() 
    .WhereIf(!string.IsNullOrEmpty(name), p => p.Name.Contains(name)) 
    .SelectMany(
    p => context.Contacts 
     .Where(cp => cp.EntityID == p.EntityId).DefaultIfEmpty() 
     .WhereIf(timestamp != null, c => c.Timestamp > timestamp), 
    (p, c) => new { p, c } 
) 

問題は最後WhereIfです。あなたは外に移動することができるはずSelectMany

context.Entities.OfType<Patient>() 
    .WhereIf(!string.IsNullOrEmpty(name), p => p.Name.Contains(name)) 
    .SelectMany(
    p => context.Contacts 
     .Where(cp => cp.EntityID == p.EntityId).DefaultIfEmpty(), 
    (p, c) => new { p, c } 
) 
    .WhereIf(timestamp != null, x => x.c.Timestamp > timestamp) 

あなたは方法ToTraceStringObjectQueryにクエリをキャストして呼び出すことによって、あなたが実際に欲しいものを得るかどうかを確認するために結果のSQLを調べることができます。

var query = context.Entities.OfType<Patient>() ... 
Console.WriteLine(((ObjectQuery) query).ToTraceString()); 
+0

これは機能しました。そのトリックは実際にSelectManyからWhereIfを移動させることでした。私は確かに生成されたSQLを実行しようとしました、そして、それは望ましい結果をもたらしました。どうもありがとう! – Eirik

0

どうすればいいですかWhere(timestamp == null || c.Timestamp > timestamp)