Varlık Çerçevesi - Birden Çok Özellik Seviyesi Dahil Et


376

Include () yöntemi nesnelerdeki Listeler için oldukça iyi çalışır. Peki ya iki seviye derine inmem gerekirse? Örneğin, aşağıdaki yöntem, burada gösterilen özelliklerle ApplicationServers döndürür. Ancak ApplicationsWithOverrideGroup, diğer karmaşık nesneleri tutan başka bir kapsayıcıdır. Bu mülk üzerinde de bir Include () yapabilir miyim? Veya bu mülkün tamamen yüklenmesini nasıl sağlayabilirim?

Şimdi olduğu gibi, bu yöntem:

public IEnumerable<ApplicationServer> GetAll()
{
    return this.Database.ApplicationServers
        .Include(x => x.ApplicationsWithOverrideGroup)                
        .Include(x => x.ApplicationWithGroupToForceInstallList)
        .Include(x => x.CustomVariableGroups)                
        .ToList();
}

Application (Özel) veya CustomVariableGroup özelliklerini (aşağıda) değil, yalnızca Enabled özelliğini (aşağıda) doldurur. Bunu nasıl yapabilirim?

public class ApplicationWithOverrideVariableGroup : EntityBase
{
    public bool Enabled { get; set; }
    public Application Application { get; set; }
    public CustomVariableGroup CustomVariableGroup { get; set; }
}

Merhaba, bir istisna olsun Neden Expression must be a member expressionbu çalıştığınızda: Bir toplama ve ardından bir koleksiyon bir düzey aşağı dahil etmek için: query.Include(e => e.Level1Collection.Select(l1 => l1.Level2Collection)).
Joe.wang

1
@BobHorn, ben de aynı sorun var .. Benim durumumda, yuvalama birden fazla katman derin iner, ben işaret bir dahil başardı. Oluşturulan SQL'de, tüm sütunların c1, c2 gibi farklı bir adla döndüğünü görebiliyordum. Benim sorum, nasıl benim dahil tüm iç içe bir DTO koleksiyonu oluşturabilirim :( .. Belki yukarıdaki örnek kendisi alabilir, biz herhangi bir özel DTO olmadan tüm sütunları iade (ki kendisi DTO's koleksiyonu olan) )
TechQuery

Yanıtlar:


704

EF 6 için

using System.Data.Entity;

query.Include(x => x.Collection.Select(y => y.Property))

Bir lambda alır using System.Data.Entity;sürümü almak için eklediğinizden emin olun Include.


EF Core için

Yeni yöntemi kullan ThenInclude

query.Include(x => x.Collection)
     .ThenInclude(x => x.Property);

1
Include () üzerinde ApplicationsWithOverrideGroup yapamam. Zekice görünmez.
Bob Horn

Düzenlemenizi kullanamıyorum çünkü ApplicationsWithOverrideGroup bir Liste. Uygulama, listenin kendisinde değil, listedeki her öğenin bir özelliğidir.
Bob Horn

1
Ahhhh, ama sağladığınız bağlantı cevabı veriyor gibi görünüyor. Bunu deneyeyim: Bir koleksiyon ve ardından bir seviye aşağıya koleksiyon eklemek için: query.Include (e => e.Level1Collection.Select (l1 => l1.Level2Collection)).
Bob Horn

60
System.Data.Entity'i kullanıcılara dahil etmeyi unutmayın. Aksi takdirde Intellisense size yalnızca yöntemin Ekle (dize yolu) sürümünü verir.
OJ Raqueño

5
@Adeem Includeher bir tesis için aramanız gerekiyor :Db.States.Include(state => state.Cities.Select(city => city.Customers).Include(state => state.Cities.Select(city => city.Vendors)
Diego Torres

72

Seni doğru anlarsam, iç içe özellikler eklemeyi soruyorsun. Öyleyse :

.Include(x => x.ApplicationsWithOverrideGroup.NestedProp)

veya

.Include("ApplicationsWithOverrideGroup.NestedProp")  

veya

.Include($"{nameof(ApplicationsWithOverrideGroup)}.{nameof(NestedProp)}")  

6
Teşekkürler, deneyebilirim. Ben güçlü bir şekilde yazılmış şeyler tutmak ve dize değişmezleri önlemek umuyordu. Ama eğer böyle yapılması gerekiyorsa ...
Bob Horn

1
Yakındın. ApplicationsWithOverrideGroup bir liste olduğu belli olmayabilir. Yardım için teşekkürler!
Bob Horn

@Judo, ben de aynı sorun var .. Benim durumumda, yuvalama birden fazla katman derin iner, ben işaret bir dahil başardı. Oluşturulan SQL'de, tüm sütunların c1, c2 gibi farklı bir adla döndüğünü görebiliyordum. Benim sorum, nasıl benim dahil tüm iç içe bir DTO koleksiyonu oluşturabilirim :( .. Belki yukarıdaki örnek kendisi alabilir, biz herhangi bir özel DTO olmadan tüm sütunları iade (ki kendisi DTO's koleksiyonu olan) )
TechQuery

2
System.Data.Entity'i kullanıcılara dahil etmeyi unutmayın . Aksi takdirde Intellisense size yalnızca Include(string path)yöntemin sürümünü verecektir .
AlexMelw

52

EF Çekirdeği: Birden fazla düzeyi yüklemek için "ThenInclude" işlevini kullanma: Örneğin:

var blogs = context.Blogs
    .Include(blog => blog.Posts)
        .ThenInclude(post => post.Author)
        .ThenInclude(author => author.Photo)
    .ToList();

53
Bu sadece EF Çekirdek gibi görünüyor
Chris Marisic

27
FYI: VS2017 intellisense .thenInclude için çalışmıyordu. Sadece olması gerektiğini düşündüğünüz yere yazın ve hata vurgulama ortadan kalkacaktır.
JohnWrensby

4
@JohnWrensby'nin yorumunu vurgulamak istiyorum, Intellisense bazen bu ThenInclude'u işlemek için özellikle uzun sürebilir, bu yeni kullanıcılar için oldukça kafa karıştırıcı olabilir. Ben sadece basit bir Include lambda ifadesi, sadece onu yazın ve derlemek kadar VS gösterilen "hataları" yok sayılan kadar düzgün ele alındığı durumlar vardı.
Pac0

@ Pac0 günümü kurtardın. çocuk eşyaları görmek için mücadele ve göremedim.
Bendram

28

Entity Framework 6 (.Net Core stili) için alt varlıkları güzel bir şekilde dahil etmek için biraz yardımcı oldum.

Şimdi NuGet'te: Install-Package ThenInclude.EF6

using System.Data.Entity;

var thenInclude = context.One.Include(x => x.Twoes)
    .ThenInclude(x=> x.Threes)
    .ThenInclude(x=> x.Fours)
    .ThenInclude(x=> x.Fives)
    .ThenInclude(x => x.Sixes)
    .Include(x=> x.Other)
    .ToList();

Paket GitHub'da mevcuttur .


merhaba, ben çalışma zamanında bir istisnası var, IncludableQueryable <observablecollection> IncludableQueryable <genericcollection> için döküm olamaz
user2475096

ilk db kullanıyorum ve tüm varlıkları için ObservableCollections almak için tt dosyasını değiştirdik, herhangi bir yardım açığız.
user2475096

2
@ lenny32 bu uzantı ile dikkat edilmesi gereken bir şey var mı?
Aaron Hudon

Gittiğiniz özellik, gittiğiniz DbSet ile bire bir ise gerekli değildir DbSet<One>().Include(x => x.Two.Three.Four.Five.Six)ve tek bir dezavantajı, kartezyen bir ürünü hesaplarken ve potansiyel olarak artan bant genişliğiyle zincirleyebilirsiniz .
John Zabroski

23

Daha MSDN üzerindeki EFCore örnekler size bazı oldukça karmaşık şeyler yapabilirsiniz göstermek IncludeveThenInclude .

Bu, ne kadar karmaşık olabileceğinize iyi bir örnektir (hepsi bir ifadedir!):

viewModel.Instructors = await _context.Instructors

      .Include(i => i.OfficeAssignment)

      .Include(i => i.CourseAssignments)
        .ThenInclude(i => i.Course)
            .ThenInclude(i => i.Enrollments)
                .ThenInclude(i => i.Student)

      .Include(i => i.CourseAssignments)
        .ThenInclude(i => i.Course)
            .ThenInclude(i => i.Department)

      .AsNoTracking()
      .OrderBy(i => i.LastName)
      .ToListAsync();

IncludeSonra bile nasıl zincirleme yapabileceğinizi görün ThenIncludeve bu da sizi en üst düzey varlığın seviyesine geri döndürür (Eğitmenler).

Aynı 'birinci seviye' koleksiyonunu (CourseAssignments) birden çok kez tekrarlayabilir ve ardından ThenIncludesfarklı alt öğelere ulaşmak için ayrı komutları takip edebilirsiniz .

Gerçek sorgunuzun Includeveya ThenIncludeszincirinin sonuna etiketlenmesi gerektiğini unutmayın . Aşağıdakiler ÇALIŞMAZ:

var query = _context.Instructors.AsQueryable();
query.Include(i => i.OfficeAssignment);

var first10Instructors = query.Take(10).ToArray();

Günlüğe kaydetmeyi ayarlamanızı ve birden fazla veya iki şey eklerseniz sorgularınızın kontrolden çıkmamasını önemle tavsiye ederim. Gerçekte nasıl çalıştığını görmek önemlidir - ve her bir 'dahil et' öğesinin, gereksiz verilerin döndürülmesini gerektiren büyük birleşmeleri önlemek için genellikle yeni bir sorgu olduğunu fark edeceksiniz.

AsNoTracking varlıkları gerçekten düzenlemeyi ve yeniden kaydetmeyi istemiyorsanız işleri hızlandırabilir.


Hem Kayıt hem de Bölümleri tekrar etmeden almanın bir yolu var mı? (Şimdiye kadar, Api .ThenInclude ile daha derine inebilir veya .Include ile en üst seviyeye geri dönebilir, ancak aynı seviyede kalmak için hiçbir şey yok mu?)
William Jockusch

Tembel yükleme yapmak istiyorsanız EF Core 2.1 blogs.msdn.microsoft.com/dotnet/2018/02/02/… için bizi izlemeye devam edin, ancak aynı seviyede daha fazla yükleme yapmak istiyorsanız bunun tasarım gereği olduğunu düşünüyorum. Ne düşündüğünüzden emin değilim - bunu yapmak için fazladan bir şey gerektirmez ve veritabanından geri gelenleri büyük ölçüde azaltır. Bir kuruluşta yalnızca bir veya iki 'aynı düzey' şey olabilir, ancak büyük bir proje için de 50 olabilir, açık olması uygulamanızı çok daha hızlı hale getirir.
Simon_Weaver

Bu, seviyenin tekrar başlangıç ​​seviyesine "sıfırlanması" kavramının iyi bir açıklamasıydı. Başımı dahil sisteminin heirarşisi etrafına dolamama yardımcı oldu. Şerefe!
AFM-Horizon

22

Ayrıca birden fazla içerme kullanmak zorunda kaldım ve 3. seviyede birden fazla özelliğe ihtiyacım vardı

(from e in context.JobCategorySet
                      where e.Id == id &&
                            e.AgencyId == agencyId
                      select e)
                      .Include(x => x.JobCategorySkillDetails)
                      .Include(x => x.Shifts.Select(r => r.Rate).Select(rt => rt.DurationType))
                      .Include(x => x.Shifts.Select(r => r.Rate).Select(rt => rt.RuleType))
                      .Include(x => x.Shifts.Select(r => r.Rate).Select(rt => rt.RateType))
                      .FirstOrDefaultAsync();

Bu birine yardımcı olabilir :)


1
Bu tekrar etmeden yapılabilir.Include(x => x.Shifts.Select(r => r.Rate).Select(rt => rt......
Multinerd

iyi, ne kadar derin gitmek istiyorsun
dnxit

7

Dize değişmezlerini kullanmak sakıncası yoksa, karşılık gelen ilişkilerin çokluğuna bakılmaksızın iç içe düzeyler eklemek için dize aşırı yükünü kullanabileceğinizi açıkça belirteyim:

query.Include("Collection.Property")

1
Bu yöntem, googling saatlerinden sonra herhangi bir yerde bulamadığım için bu VB'de nasıl kodlanabileceğini anlamaya yardımcı oldu.
Kodlayıcı

Bu benim için harika çalışıyor, bunu çok kullanıyorum !!! Hatta .SelectMany ifadeleri ile birlikte çalışır:query.SelectMany(x=>x.foos).Include("bar").Include("bar.docs")...
Ephie
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.