Cómo incluir el objeto hijo de un objeto hijo en Entity Framework 5

138

Estoy usando Entity Framework 5 code firsty ASP.NET MVC 3.

Estoy luchando para que el objeto hijo de un objeto hijo se complete. Abajo están mis clases ...

Clase de aplicación;

public class Application
{
     // Partial list of properties

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

Clase de niño:

public class Child
{
     // Partial list of properties

     public int ChildRelationshipTypeId { get; set; }

     public virtual ChildRelationshipType ChildRelationshipType { get; set; }
}

Clase ChildRelationshipType:

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

     public string Name { get; set; }
}

Parte del método GetAll en el repositorio para devolver todas las aplicaciones:

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

La clase Child contiene una referencia a la clase ChildRelationshipType. Para trabajar con los hijos de una aplicación, tendría algo como esto:

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

Aquí aparece un error de que el contexto del objeto ya está cerrado.

¿Cómo especifico que cada objeto secundario debe incluir el ChildRelationshipTypeobjeto como lo hice anteriormente?

Brendan Vogt
fuente
Posible duplicado de Entity Framework - Incluir múltiples niveles de propiedades
Michael Freidgeim

Respuestas:

256

Si incluye la biblioteca System.Data.Entity, puede usar una sobrecarga del Include()método que toma una expresión lambda en lugar de una cadena. A continuación, puede Select()sobre los niños con expresiones Linq en lugar de stringrutas.

return DatabaseContext.Applications
     .Include(a => a.Children.Select(c => c.ChildRelationshipType));
Ryan Amies
fuente
66
Como dijo GraemeMiller, las clases fuertemente tipadas son mejores para la mantenibilidad que el uso de cadenas
Ryan Amies
¿En qué versión estuvo disponible el método lamba? Estoy atascado en una base de código EF 4.0 ... y no puedo hacer que las lamdas funcionen. Gracias por cualquier aportación.
granadaCoder
55
Funcionará en EF 4, solo asegúrese de agregar una referencia aSystem.Data.Entity;
Ryan Amies
55
FYI - En EF 6 el espacio de nombres esMicrosoft.Data.Entity
Brad
Usando EF 5, no pude obtener .Select (x => x.Child) pero esto funcionó - 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

Con EF Core en .NET Core puede usar la palabra clave ThenInclude:

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

Incluya niños de la colección para niños:

return DatabaseContext.Applications
 .Include(a => a.Childrens).ThenInclude(cs => cs.ChildRelationshipType1)
 .Include(a => a.Childrens).ThenInclude(cs => cs.ChildRelationshipType2);
Hayha
fuente
66
¡¡¡Gracias!!! ¡De mucha ayuda! A veces puedes equivocarte de inteligencia, ¡simplemente ignora eso y construye! :)
muhihsan
Agradable, estaba buscando .net core :)
Andy Clarke
1
¿Y qué pasa si Children es una colección y necesito incluir propiedades debajo de ella?
dodbrian
Encontró una sobrecarga para eso. No era obvio al principio.
dodbrian
1
@dodbrian ¿Cuál fue la sobrecarga? Estoy tratando de anidar. EntoncesIncluir, donde el niño es una colección.
Greg Hardin
22

Terminé haciendo lo siguiente y funciona:

return DatabaseContext.Applications
     .Include("Children.ChildRelationshipType");
Brendan Vogt
fuente
76
La forma fuertemente tipada es mejor. Las cuerdas mágicas no son buenas para refactorizar
GraemeMiller
2

Un buen ejemplo del uso del patrón de repositorio genérico y la implementación de una solución genérica para esto podría ser algo como esto.

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

{

    foreach (var include in includeProperties)
     {

        query = query.Include(include);
     }

        return query.ToList();
}
gcoleman0828
fuente
¿Cómo llamaría al método anterior? ¿Podría dar un ejemplo
Jamee
@Jamee -List <Expression <Func <PersonObject, object >>> includers = new List <Expression <Func <PersonObject, object >>> (); includers.Add (x => x.FirstName); Obtener <PersonObject> (incluidos);
gcoleman0828
1
¿Y la consulta proviene de ...?
Doug Beard
Lo siento @DougBeard, no sigo tu pregunta.
gcoleman0828
1
@ gcoleman0828 La variable de consulta en el fragmento de código anterior. ¿Es mágicamente instanciado? ¿De dónde viene?
Doug Beard el