2016-06-27 19 views
2

Entity Frameworkを使用して、私は同じテーブルにマップするクラスの階層を持っています。 Cat : AnimalDog : AnimalGoat : Animalのようなものです。エンティティフレームワークコードfirst - オブジェクトの型が定義済みのリスト内にあるテーブルからオブジェクトを選択します。

もちろん、EFは内部でDiscriminatorカラムを使用してそれらを処理します。 SQLは、LINQツー.GetType()をサポートしていないとして、当然のことながら

var houseAnimals = new List<Type>(new [] { typeof(Cat), typeof(Dog) }); 
this.dataRepository.Animals.Where(a => houseAnimals.Contains(a.GetType())); 

、これは動作しません。

は今、私のような何かを書きたいです。しかし、これは動作します:

this.dataRepository.Animals.Where(a => a is Cat); 

このリストは実行時に動的に構築されているので、私はa is Cat || a is Dogを行うにはしたくありません。

this postに基づいて、私はEFが 'Discriminator in'ステートメントを備えたSQLクエリに変換することを理解しています。それで、これは私が必要とすることができるという希望を与えてくれます。これは:

this.dataRepository.Animals.Where(a => a is **in** houseAnimals); 

いいえ、もちろんそのような構文はありません。

質問:私はこれを達成するためにどのような構文を使用できますか?私はここに何かを逃していますかこれはEFに欠けている機能ですか?このような質問をしたかった唯一の人になることはできません。

この例では、私が必要としていることを説明するために単純化しているので、私のアプローチとこのクエリの実行の必要性をciritizeしないでください。 .ToList()を行うこともオプションではありません。

+0

Discriminatorの列が私の場合は非常に疲れていて、本当に必要な場合にのみ使用します。 SQLにはプライマリキーと外部キーの関係があります。この種の継承マッピングを使用すると、さまざまな問題が発生する可能性があります。 –

+0

Discriminatorカラムは明示的に使用しません。 –

+1

さて、言い換えると、私はSQLでC#オブジェクトの継承マッピングを使用することに非常に疲れています。 –

答えて

2

EFでは、このような機能は使用できません。しかし、それはこのようなExpression.TypeIsExpression.OrElseの助けを借りて、動的述語を構築する独自の拡張メソッドを書くことは難しいことではありません。

public static class QueryableExtensions 
{ 
    public static IQueryable<T> OfType<T>(this IQueryable<T> source, IEnumerable<Type> types) 
    { 
     var parameter = Expression.Parameter(typeof(T), "a"); 
     var body = types 
      .Select(type => Expression.TypeIs(parameter, type)) 
      .Aggregate<Expression>(Expression.OrElse); 
     var predicate = Expression.Lambda<Func<T, bool>>(body, parameter); 
     return source.Where(predicate); 
    } 
} 

IQueryable<Animal>リポジトリ戻りを想定すると、使い方は次のようになります。

this.dataRepository.Animals.OfType(houseAnimals); 
+1

私は+1のようなコメントを避けるべきだと知っているが、これは印象的な解決策であり、それは私のために働いたと言う必要があります。 – chandler

+0

リポジトリは実際に 'IDbSet Animals'を公開しています。あなたのコードを使用するのに問題があります。「メソッドのオーバーロードがありません」OfTypeは1つの引数を取ります。 –

+1

1つの引数を持つ 'OfType'が答えのメソッドです。拡張メソッドが必要な場所に表示されていることを確認してください。すなわち、 '上記のクラスを含む名前空間を使用する}; –

関連する問題