2016-09-20 30 views
6

EF6 kullanıyorum ve bir nesnenin tüm yapısını almaya hevesli olmaya çalışıyorum. Sorun şu ki miras kullanıyorum.EF Eager türetilen sınıf getiriliyor

Bu derslere sahip olduğumu söyleyelim.

DBContext

DbSet<A> A { get; set; } 

Örnek sınıfları

public class A 
{ 
    public string Id { get; set; } 
    public IList<Base> Bases { get; set; } 
} 

public abstract class Base 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
} 

public abstract class Base1 : Base 
{ 
    public SomeClass SomeClass { get; set; } 
} 

public class Base2 : Base1 
{ 

} 

public class Base3 : Base1 
{ 
    public SomeOtherClass SomeOtherClass { get; set; } 
} 

i almak hatadır:

The Include path expression must refer to a navigation property defined on the type. 
Use dotted paths for reference navigation properties and the Select operator for collection navigation properties. 

neden aşağıdaki çalışmak gelmiyor.Fark?

public IEnumerable<A> GetAll(string id) 
    { 

     return _ctx.A 
       .Include(x => x.Bases.OfType<Base1>().Select(y=>y.SomeClass)) 
       .Where(x => x.Id.Equals(id)).ToList(); 
    } 

Yeni örnek

public IEnumerable<A> GetAll(string id) 
{ 

    var lists = _dbContext.A.Where(x => x.Id == id); 
    lists.SelectMany(a => a.Bases).OfType<Base1>().Include(e=>e.SomeClass).Load(); 
    lists.SelectMany(b => b.Bases).OfType<Base3>().Include(e => e.SomeOtherClass).Load(); 

    return lists; 
} 

DÜZENLEME: iş gibi görünüyor yeni bir örnek eklendi.

+0

Eğer 'dahil eder ("SomeOtherClass")' kullanılarak denedi yardımcı olacaktır

var details = _ctx.A .Where (t=>t.Id ==something) .Select(a => new { Id = a.Id, // ... other A properites , Bases = _ctx.Bases.OfType<Base1>().Select(m=> new { Id = m.Id, Name = m.Name, SomeClass = m.SomeClass }); } 

Umut? –

+0

Someclass başka bir kuruluştur. SomeClass henüz – Henrik

+0

çalışmadığı için SomeOtherClass denedim, bu 'Include (" SomeClass ")' ı denediniz demektir ve işe yaramaz mı? –

cevap

2

Kısaca, kutudan çıkması mümkün değildir. Ben önerebilirsiniz

tek geçici çözüm, daha sonra ana sorgu sonucunu hayata usta sorgusu ile aynı filtre kullanarak gerekli Includes ile birkaç OfType sorguları yürütmek ve EF navigasyon özelliği Fixup temel almaktır.

O Base sınıfında ters navigasyon özelliği gerektirir

:

public abstract class Base 
{ 
    // ... 
    public A A { get; set; } 
} 

Sonra böyle bir şey kullanabilirsiniz:

public IEnumerable<A> GetAll(string id) 
{ 
    var a = _ctx.A.Where(x => x.Id == id).ToList(); 
    _ctx.Base.OfType<Base1>().Include(e => e.SomeClass).Where(e => e.A.Id == id).Load(); 
    _ctx.Base.OfType<Base3>().Include(e => e.SomeOtherClass).Where(e => e.A.Id == id).Load(); 
    return a; 
} 

aynı fikri ters navigasyon özelliği w/o kullanılabilir ancak döndürülmüş taban Ids kullanarak filtre olarak kullanma:

public IEnumerable<A> GetAll(string id) 
{ 
    var a = _ctx.A.Include(e => e.Bases) 
     .Where(x => x.Id == id).ToList(); 

    var baseIds = a.SelectMany(e => e.Bases.OfType<ModelA.Base1>().Select(b => b.Id)); 
    db.Base.OfType<Base1>().Include(e => e.SomeClass) 
     .Where(e => baseIds.Contains(e.Id)).Load(); 

    baseIds = a.SelectMany(e => e.Bases.OfType<Base3>().Select(b => b.Id)); 
    db.Base.OfType<Base3>().Include(e => e.SomeOtherClass) 
     .Where(e => baseIds.Contains(e.Id)).Load(); 

    return a; 
} 
+0

Teşekkürler :) İlk örnek denedim, ama ters navigasyon özelliği olmadan (A ref in Base) ve Base1 ve Base3 hem de Nerede sahip olmadan? Gönderiyi güncelledim. Örneğim tam olarak sizinki gibi mi, yoksa fark nedir? – Henrik

+0

@Henrik İyi yakalama! Aslında aynı temel fikri kullanan üçüncü yol. Bu benim ilk yaklaşımımın bir varyasyonu ve 3 yaklaşımın tümü işe yarıyor olsa da, böyle bir senaryo için en iyisi bu gibi görünüyor. –

+0

Okey, teşekkürler. :-) – Henrik

1

Yo Eğer kendi sorgunuzdan kaldırmaya çalışırsanız ve sorgunuzu tekrar çalıştırırsanız, bu sorun Select(y=>y.SomeClass) kendinde değil, aynı sorunu alacaksınız. Devralınan türünü çocuk olarak sorgulayamazsınız ve varlık çerçevesinden her şeye dikkat etmesini beklersiniz.

Veritabanınıza bakarsanız, tablo Base, A'dan Base'ye 1-çok ilişkisi olan A numaralı başvuruya sahiptir.

yapabilirsiniz ya olsun A.Id = something, sınıfta Base bir seyir özelliği A eklemeye ve DBContext içinde ederek DbSet<Base> Bases{get;set;} sonra sorgu bu

var details = _ctx.Bases.OfType<Base1>() 
         .Include(t=>t.Box) 
         .Include(t=>t.SomeClass) 
         .Where(t=>t.Box.Id ==something); 

Diğer seçenek gibi bakacağız eklediğiniz tüm Base kişiler, DTO kullanmak için aşağıdaki örnekte Anonymous türünü kullandım, ancak gereksinimlerinizi karşılamak için yazdığınız DTO'yu oluşturabilirsiniz.Bu size