Comment inclure l'objet enfant d'un objet enfant dans Entity Framework 5

138

J'utilise Entity Framework 5 code firstet ASP.NET MVC 3.

J'ai du mal à faire peupler l'objet enfant d'un objet enfant. Voici mes cours.

Classe d'application;

public class Application
{
     // Partial list of properties

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

Classe enfant:

public class Child
{
     // Partial list of properties

     public int ChildRelationshipTypeId { get; set; }

     public virtual ChildRelationshipType ChildRelationshipType { get; set; }
}

Classe ChildRelationshipType:

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

     public string Name { get; set; }
}

Partie de la méthode GetAll dans le référentiel pour renvoyer toutes les applications:

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

La classe Child contient une référence à la classe ChildRelationshipType. Pour travailler avec les enfants d'une application, j'aurais quelque chose comme ceci:

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

J'obtiens ici une erreur indiquant que le contexte de l'objet est déjà fermé.

Comment spécifier que chaque objet enfant doit inclure l' ChildRelationshipTypeobjet comme je l'ai fait ci-dessus?

Brendan Vogt
la source
Double

Réponses:

256

Si vous incluez la bibliothèque, System.Data.Entityvous pouvez utiliser une surcharge de la Include()méthode qui prend une expression lambda au lieu d'une chaîne. Vous pouvez alors Select()sur les enfants avec des expressions Linq plutôt que des stringchemins.

return DatabaseContext.Applications
     .Include(a => a.Children.Select(c => c.ChildRelationshipType));
Ryan Amies
la source
6
Comme l'a dit GraemeMiller, les classes fortement typées sont meilleures pour la maintenabilité que l'utilisation de chaînes
Ryan Amies
Quelle version la méthode lamba est-elle disponible? Je suis coincé sur une base de code EF 4.0 ... et je ne peux pas faire fonctionner les lamdas. Merci pour toute contribution.
grenadeCoder
5
Cela fonctionnera dans EF 4, assurez-vous simplement d'ajouter une référence àSystem.Data.Entity;
Ryan Amies
5
FYI - Dans EF 6, l'espace de noms estMicrosoft.Data.Entity
Brad
En utilisant EF 5, je n'ai pas pu obtenir .Select (x => x.Child) mais cela a fonctionné - Entities.UserProfile stockéProfile = 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

Avec EF Core dans .NET Core, vous pouvez utiliser le mot clé ThenInclude:

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

Inclure les enfants de la collection pour enfants:

return DatabaseContext.Applications
 .Include(a => a.Childrens).ThenInclude(cs => cs.ChildRelationshipType1)
 .Include(a => a.Childrens).ThenInclude(cs => cs.ChildRelationshipType2);
Hayha
la source
6
Merci!!! Très utile! Parfois, vous pourriez vous tromper d'intellisense, ignorez-le et construisez! :)
muhihsan
Gentil, je cherchais .net core :)
Andy Clarke
1
Et si Children est une collection et que je dois y inclure des propriétés?
dodbrian
J'ai trouvé une surcharge pour ça. Ce n'était pas évident au début.
dodbrian
1
@dodbrian Quelle était la surcharge? J'essaye d'imbriquer .ThenInclude, où l'enfant est une collection.
Greg Hardin
22

J'ai fini par faire ce qui suit et cela fonctionne:

return DatabaseContext.Applications
     .Include("Children.ChildRelationshipType");
Brendan Vogt
la source
76
La méthode fortement typée est meilleure. Les cordes magiques ne sont pas bonnes pour la refactorisation
GraemeMiller
2

Un bon exemple d'utilisation du modèle de référentiel générique et d'implémentation d'une solution générique pour cela pourrait ressembler à ceci.

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

{

    foreach (var include in includeProperties)
     {

        query = query.Include(include);
     }

        return query.ToList();
}
gcoleman0828
la source
Comment appeler la méthode ci-dessus? pourriez-vous donner un exemple
Jamee
@Jamee -List <Expression <Func <PersonObject, object >>> includes = new List <Expression <Func <PersonObject, object >>> (); include.Add (x => x.FirstName); Get <PersonObject> (inclus);
gcoleman0828
1
Et la requête vient de ...?
Doug Beard
Désolé @DougBeard, ne suit pas votre question.
gcoleman0828
1
@ gcoleman0828 La variable de requête dans votre extrait de code ci-dessus. Est-il instancié par magie? D'où est ce que ça vient?
Doug Beard