Jak dołączyć obiekt podrzędny obiektu podrzędnego w Entity Framework 5

138

Używam Entity Framework 5 code firsti ASP.NET MVC 3.

Staram się, aby obiekt podrzędny obiektu podrzędnego został wypełniony. Poniżej moje zajęcia ..

Klasa aplikacji;

public class Application
{
     // Partial list of properties

     public virtual ICollection<Child> Children { get; set; }
}

Klasa dziecka:

public class Child
{
     // Partial list of properties

     public int ChildRelationshipTypeId { get; set; }

     public virtual ChildRelationshipType ChildRelationshipType { get; set; }
}

Klasa ChildRelationshipType:

public class ChildRelationshipType
{
     public int Id { get; set; }

     public string Name { get; set; }
}

Część metody GetAll w repozytorium, aby zwrócić wszystkie aplikacje:

return DatabaseContext.Applications
     .Include("Children");

Klasa Child zawiera odwołanie do klasy ChildRelationshipType. Aby pracować z dziećmi aplikacji, miałbym coś takiego:

foreach (Child child in application.Children)
{
     string childName = child.ChildRelationshipType.Name;
}

Otrzymuję tutaj błąd, że kontekst obiektu jest już zamknięty.

Jak określić, że każdy obiekt podrzędny musi zawierać ChildRelationshipTypeobiekt, tak jak to zrobiłem powyżej?

Brendan Vogt
źródło

Odpowiedzi:

256

Jeśli włączysz bibliotekę System.Data.Entity, możesz użyć przeciążenia Include()metody, która przyjmuje wyrażenie lambda zamiast ciągu. Następnie możesz Select()nad dziećmi używać wyrażeń Linq zamiast stringścieżek.

return DatabaseContext.Applications
     .Include(a => a.Children.Select(c => c.ChildRelationshipType));
Ryan Amies
źródło
6
Jak powiedział GraemeMiller, silnie wpisane klasy są lepsze ze względu na
łatwość
W której wersji była dostępna metoda lamba? Utknąłem w bazie kodu EF 4.0 i nie mogę zmusić lamd do pracy. Dzięki za wszelkie uwagi.
granadaCoder
5
Będzie działać w EF 4, po prostu upewnij się, że dodałeś odniesienie doSystem.Data.Entity;
Ryan Amies
5
FYI - W EF 6 przestrzeń nazw toMicrosoft.Data.Entity
Brad
Używając EF 5, nie mogłem uzyskać .Select (x => x.Child), ale to zadziałało - Entities.UserProfile storeProfile = db.UserProfiles .Include (s => s.ShippingAddress) .Include (st => st.ShippingAddress. StateProvince) .Include (b => b.BillingAddress) .Include (bs => bs.BillingAddress.StateProvince) .FirstOrDefault (x => x.UserId == userId);
Geovani Martinez
91

Z EF Core w .NET Core możesz użyć słowa kluczowego ThenInclude:

return DatabaseContext.Applications
 .Include(a => a.Children).ThenInclude(c => c.ChildRelationshipType);

Uwzględnij dzieci z kolekcji dla dzieci:

return DatabaseContext.Applications
 .Include(a => a.Childrens).ThenInclude(cs => cs.ChildRelationshipType1)
 .Include(a => a.Childrens).ThenInclude(cs => cs.ChildRelationshipType2);
Hayha
źródło
6
Dzięki!!! Naprawdę pomocny! Czasami możesz się pomylić z inteligencją, po prostu zignoruj ​​to i buduj! :)
muhihsan
Niezły, szukałem rdzenia .net :)
Andy Clarke
1
A co, jeśli Children to kolekcja i muszę uwzględnić w niej nieruchomości?
dodbrian
Znalazłem za to przeciążenie. Na początku nie było to oczywiste.
dodbryjski
1
@dodbrian Jakie było przeciążenie? Próbuję zagnieździć .ThenInclude, gdzie dziecko jest kolekcją.
Greg Hardin
22

W końcu wykonałem następujące czynności i to działa:

return DatabaseContext.Applications
     .Include("Children.ChildRelationshipType");
Brendan Vogt
źródło
76
Silnie wpisany sposób jest lepszy. Magiczne struny nie nadają się do refaktoryzacji
GraemeMiller
2

Dobry przykład użycia wzorca Generic Repository i zaimplementowania w tym celu ogólnego rozwiązania może wyglądać mniej więcej tak.

public IList<TEntity> Get<TParamater>(IList<Expression<Func<TEntity, TParamater>>> includeProperties)

{

    foreach (var include in includeProperties)
     {

        query = query.Include(include);
     }

        return query.ToList();
}
gcoleman0828
źródło
Jak nazwałbym powyższą metodę? czy możesz podać przykład
Jamee
@Jamee -List <Wyrażenie <Func <PersonObject, obiekt >>> obejmuje = new Lista <Wyrażenie <Func <PersonObject, obiekt >>> (); includeers.Add (x => x.FirstName); Pobierz <PersonObject> (w tym);
gcoleman0828
1
A zapytanie pochodzi z ...?
Doug Beard
Przepraszamy @DougBeard, nie podążam za twoim pytaniem.
gcoleman0828
1
@ gcoleman0828 Zmienna zapytania w powyższym fragmencie kodu. Czy jest magicznie utworzony? Skąd to pochodzi?
Doug Beard