2011-07-05 9 views
4

ので、最初に私のエンティティボトルネック使用してエンティティフレームワークの継承

Entities

私はすべての物語のタイトルを持つページを持ちたい問題とその種類

3階建てLongStoryCoOpStoryGenericStoryがあります

一般的なストーリーは、一般的なストーリーのタイプとしてStoryTypeに関連付けられています

または私はすべてのエンティティを取得し、それがその後、何かを LongStoryであれば、エンティティの種類を確認する必要が CoOpStory、私は方法がわからない私は物語があるかどうかを確認したいとき

は、私は2つの問題

最初のを持っていますいくつかのデータ[タイトルのみ]を取得してタイプを確認する

私はすべてのストーリータイトルとそのタイプのページを持っていたいと言ったように私は多くのことをせずにそれを行う方法を知らないクエリのうち、私はに関連付けられている必要があるので、StoryTypeテーブルに参加することはできません。最初にすべてのストーリーを取得してから、毎回追加のクエリを実行しますGenericStoryタイプを取得する

答えて

4

あなたはOfTypeConcat拡張メソッドを探しています。

はあなただけで呼び出す必要があるだけLongStoryのインスタンスを取得するには:

var longStories = context.Stories.OfType<LongStory>().ToList(); 

は、それが少し複雑です、あなたの大きなクエリを取得するには。

var allStories = context.Stories 
         .OfType<GenericStory>() 
         .Include("StoryType") // I'm not sure how this works with concat 
         .Concat(
          context.Stories.OfType<LongStory>.Concat(   
            context.Stories.OfType<CoOpStory>())); 

それとも、投影を行うことができます:あなたが試すことができますいずれか

var allStories = context.Stories 
         .OfType<GenericStory>() 
         .Select(s => new { s.Title, s.StoryType.Name }) 
         .Concat(
          context.Stories 
            .OfType<LongStory> 
            .Select(s => new { s.Title, "LongStory" }) 
            .Concat(   
             context.Stories 
               .OfType<CoOpStory>() 
               .Select(s => new { s.Title, Type }))); 
+0

私はちょうど書き込みを停止しました:) 'allStories'クエリは実際にはDBへの3回のラウンドトリップですか?私も 'Concat'を念頭に置いていましたが、パラメータは' IQueryable'ではなく 'IEnumerable'です。私たちが3つのラウンドリップを取得するかどうかはわかりませんでした。 'context.Stories。(context.Stories.OfType ()) 'は' context.Stories.Where(s =>!(sはGenericStory)) 'に圧縮される可能性があります。 – Slauma

+0

'Concat'は' UNION ALL'に変換され、 'Union'は単にUNIONに変換されます。そうでなければ、linq-to-entitiesで組合を行う方法がありません。その圧縮はクールだ:)私は2つの連結を回避する方法について考えたが、これは私の心に来ていない。 –

+0

'Concat'の翻訳方法を知っておいてよかったです!最後に、質問の最初の部分について、醜い(しかし働いている)何かを見つけました。これは本当に簡単な方法では不可能かと思います。 – Slauma

3

ラディスラフの答えはあなたの2番目の質問です。あなたの最初の質問には、可能な解決策があります。

私が見る限り、投影で型を直接照会することはできません(たとえばGetType()を使用すると、LINQ to Entitiesでは機能しません)。 Typeプロパティは、このクエリでカスタム文字列としてタイプを表しますが、匿名オブジェクトのリストを得るでしょう

var stories = context.Stories 
    .Select(s => new 
    { 
     Title = s.Title, 
     Type = (s is LongStory) ? "LongStory" : 
       (s is CoOpStory) ? "CoOpStory" : 
       (s is GenericStory) ? "GenericStory" : 
       (s is Story) ? "Story" : // forget this if Story is abstract 
       "Unknown" 
    }).ToList(); 

:あなたが唯一のタイトルとストーリーの種類を問い合わせる例えばしたい場合でも、次のように動作します。

新しいクラスを階層に追加するたびにこのクエリを変更する必要があったので、あまりいいことではありません。また、順序は重要です(ほとんどの派生クラスはTypeプロパティの最初の式でなければなりません)。しかし私は別の方法を知らない。

+0

申し訳ありませんが、両方の回答を本当に素晴らしい情報、感謝 –

-1

あなたはこれを試しましたか?

context.Stories.OfType<LongStory>.Where(...).Cast<Story>() 
.Union(context.Stories.OfType<GenericStory>.‌​Where(...).Include(s => s.StoryType).Cast<Story>()) 
.Union(context.Stories.OfType<CoOpStory>.Where(...).Cast<Story>()); 
+2

これは本当によく見え、異なるタイプのコレクションを連結する問題を解決します。残念ながら、EFは 'Include'パスが無効で、' StoryType'は 'Story'型の宣言されたプロパティではないと訴えています。 'OfType ()'が実際に適用される前に 'Include'が' DbSet 'に適用されているようです。 – Slauma