2015-12-01 10 views
7

は、そのアーキテクチャを想定してくださいエンティティタイプによって含めます)入れ子になっているすべてのエンティティ:EF条件は

var query = myContext.Mammals 
    .IncludeIfTypeIs<Dog>(d => d.Tail) 
    .IncludeIfTypeIs<Bat>(b => b.Wing) 
    .IncludeIfTypeIs<Buffalo>(b => b.Horns) 
    ... 
    ... 
; 

私は別にそれを行うことができると知っていますが、私は多くのエンティティを持っているので、データベースの要求を最小限に抑える必要があります。

これは、多くのデータベース要求も行うため、遅延読み込みを使用したくないです。

これを達成する方法は?

public static class Extensions 
{ 
    public static IQueryable<Mammal> IncludeExtraEntities<Mammal,T>(this IQueryable<Mammal> query, T derivedType) where T :Mammal 
    { 
     if (derivedType is Dog) 
      return query.Include("Tail"); 
     if (derivedType is Bat) 
      return query.Include("Wing"); 
     return query; 
    } 
} 

その後、あなたのデシベルの呼び出しで:

var query = myContext.Mammals.IncludeExtraEntities(typeof(Dog)); 

多分これが動作します

+0

を、私は、コレクションの作品が含まれてこれができないと思うし、それに基づいてそれはクエリを準備し、SQLジョインを実行しますが、あなたのケースでは、私は完全にlinqの目的をSQLに敗北させると思う 'Mammal'の個々のインスタンスで動作しているようです。 –

+0

あなたのコメントをありがとうが、私はlinq SQLの目的を敗北させるとは思わない。私はそれぞれのママの種類ごとに1つのクエリを作成し、それをすべて呼び出すことが義務付けられています。それは遅れてしまい、アプリケーションを複雑にします。私のアプリケーションでは、例えば、さまざまなプロパティを持つHornのタイプを持つことができます。これらのプロパティを条件付きでロードすることもできます... –

+0

すべてのmamalsを繰り返し処理し、そのタイプをチェックし、それはそのタイプの場合のみ....? –

答えて

0

あなたはこのような何かを試すことができます。

+0

同じクエリー内のすべての型に対してネストされたエンティティをロードする必要があるため、これは機能しません。 –

+1

しかし、どのようにタイプを取得しますか?あなたのクエリによって取り出される 'Mammal'のタイプを意味しますか?したがって、哺乳動物の1つが犬である場合、その結果のために尾をロードし、別のバットがバットであれば、その結果のために翼をロードしますか? –

+2

Afaik異なる派生型のエンティティを読み込むことはできません –

0

式を作成して式のリストを含めることができます。 (または、おそらく拡張メソッド)。

public static IQueryable<Mammal> GetMammals(params Expression<Func<T, Object>>[] includeExps) 
{ 
    var query = context.Mammals.AsQueryable(); 
    if (includeExps != null) 
     query = includeExps.Aggregate(query, (current, exp) => current.Include(exp)); 

    return query; 

} 

そして、あなたのコード内で:

//Bat and Dog will be included here 
var mammals = GetMammals(i => i.Bat, i => i.Dog); 

はそれが役に立てば幸い!

+0

これは動作しません。私はあなたのタイプTが哺乳動物であると仮定します(あなたはそれを指定しません)。だから、私がGetMammalsを呼び出すと、これは哺乳動物(犬とバットは哺乳類のタイプであり、財産ではない)のプロパティを待ちます。たとえばm => m.Wingを実行しようとすると、MammalがWingというプロパティを持っていないため、コンパイルされません(Batはこのプロパティを持っています)。したがって、条件付きインクルードは、インクルードする前にファイルタイプを変換する必要があります。 –

+0

ああ、私は誤解しました。だから、私は@アレキサンダーDerckのようにそれが可能ではないと信じて、 –

0

問題は、基本クラスのDbSetだけを使用して遅延読み込みを行わずに、派生型のプロパティをどのように読み込むのですか?私はこれが不可能ではないかと思います。

あなたはしかし、これを行うことができます:

public class MyContext : DbContext 
{ 
    public DbSet<Mammal> Mammals { get; set; } 
    public DbSet<Dog> Dogs { get; set; } 
    public DbSet<Bat> Bats { get; set; } 
} 

あなたは、単に

public static class Extensions 
{ 
    public static IQueryable<Dog> IncludeExtraEntities<Dog>(this IQueryable<Dog> query) where Dog : Mammal 
    { 
      return query.Include("Tail"); 
    } 

    public static IQueryable<Bat> IncludeExtraEntities<Bat>(this IQueryable<Bat> query) where Bat: Mammal 
    { 
      return query.Include("Wing"); 
    } 
} 

次に、あなたのタイプごとに1つの方法は、型固有の実装ができ、あなたは簡単に呼び出すことができます。

myContext.Dogs.IncludeExtraEntities(); 

あなたのタイプに応じてメソッドが呼び出されます。

+0

ありがとう、しかし、私が欲しいものではありません。私が必要とするのは、Mammals.IncludeForDog()。IncludeForBuff()。IncludeForBuffalo()... –

+0

ですから、私は犬、バット、バッファローの婚姻リストを作成します。 –

0

Includeから多すぎると思われます。 Includeに入力するラムダ式は、あまりにも知的に見える文字列プロバイダに過ぎません。フードの下では、メンバーの表現を解剖してプロパティの名前を取得します。それだけです。名前は、文字列パラメータを受け取るIncludeメソッドに入力されます。その方法は実際の作業を行います。

ラムダ式は、IQueryableの型のナビゲーションプロパティを指し示す必要があります。

myContext.Mammals.Include(d => d.Tail) 

... Tailは基本タイプのプロパティではありません。あなただけ

myContext.Mammals.OfType<Dog>().Include(d => d.Tail) 

あなたが得ることができる最高のことは、あなたがnull参照の例外を心配する必要はありませんすべてがSQLに翻訳されているので

from m in context.Mammals 
let tail = (m as Dog).Tail 
let wing = (m as Bat).Wing 
let horns= (m as Buffalo).Horns 
select new { Mammal = m, tail, wing, horns } 

ようなものです...行うことができます。

0

私はそれを解決する方法ここではそのような問題に直面して:

public IEnumerable<OrderLine> GetAllOrderLinesData() 
    { 
     var _StockOrderLines = appContext.OrderLines.OfType<StockOrderLine>() 
      .Include(p => p.Order).Include(p => p.Product); 

     var _AnnualOrderLines = appContext.OrderLines.OfType<AnnualOrderLine>() 
      .Include(p => p.Order).Include(p => p.Customer); 

     return _StockOrderLines.ToList<OrderLine>().Union<OrderLine>(_AnnualOrderLines.ToList<OrderLine>()); 
    } 

あなたはあなた としてクラスを変更することができます:)