179

I am using Entity Framework 5 code first and ASP.NET MVC 3.

I am struggling to get a child object's child object to populate. Below are my classes..

Application class;

public class Application
{
     // Partial list of properties

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

Child class:

public class Child
{
     // Partial list of properties

     public int ChildRelationshipTypeId { get; set; }

     public virtual ChildRelationshipType ChildRelationshipType { get; set; }
}

ChildRelationshipType class:

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

     public string Name { get; set; }
}

Part of GetAll method in the repository to return all the applications:

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

The Child class contains a reference to the ChildRelationshipType class. To work with an application's children I would have something like this:

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

I get an error here that the object context is already closed.

How do I specify that each child object must include the ChildRelationshipType object like what I did above?

1

4 Answers 4

294

If you include the library System.Data.Entity you can use an overload of the Include() method which takes a lambda expression instead of a string. You can then Select() over children with Linq expressions rather than string paths.

return DatabaseContext.Applications
     .Include(a => a.Children.Select(c => c.ChildRelationshipType));
Sign up to request clarification or add additional context in comments.

6 Comments

As GraemeMiller said, strongly typed classes are better for maintainability than using strings
Which version did the lamba method come available? I'm stuck on a EF 4.0 Codebase..and cant' get the lamdas to work. Thanks for any input.
It will work in EF 4, just make sure to add a reference to System.Data.Entity;
FYI - In EF 6 the namespace is Microsoft.Data.Entity
Using EF 5, I could not get .Select(x => x.Child) but this worked - Entities.UserProfile storedProfile = 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);
|
177

With EF Core in .NET Core you can use the keyword ThenInclude :

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

Include childs from childrens collection :

return DatabaseContext.Applications
 .Include(a => a.Childrens).ThenInclude(cs => cs.ChildRelationshipType1)
 .Include(a => a.Childrens).ThenInclude(cs => cs.ChildRelationshipType2);

7 Comments

Thanks!!! Really helpful! Sometimes you might get wrong intellisense, just ignore that and build! :)
Nice one, I was looking for .net core :)
And what if Children is a collection and I need to include properties under it?
Found an overload for that. Was not obvious at first.
@dodbrian What was the overload? I'm trying to nest .ThenInclude, where the child is a collection.
|
26

I ended up doing the following and it works:

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

3 Comments

The strongly typed way is better. Magic strings aren't good for refactoring
@GraemeMiller , you re right, it is a lot better when debugging, refactoring or changing the code in any way, but (sadly) "strongly typed" just does not work - for me. So I'm stuck with magic stings.
I will go with a solution using nameof expressions: string.join('.', nameof(Children), nameof(Children.ChildRelationshipType)) - at least I will be able to "FindAllReferences"
3

A good example of using the Generic Repository pattern and implementing a generic solution for this might look something like this.

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

{

    foreach (var include in includeProperties)
     {

        query = query.Include(include);
     }

        return query.ToList();
}

6 Comments

How would I call the above method? could you provide an example
@Jamee -List<Expression<Func<PersonObject, object>>> includers = new List<Expression<Func<PersonObject, object>>>(); includers.Add(x => x.FirstName); Get<PersonObject>(includers);
And query comes from...?
@gcoleman0828 The query variable in your code snippet above. Is it magically instantiated? Where does it come from?
@DougBeard: the query can be extracted via dbContext.Person.Where clause, a query builder, or from an IEnumerable in which you apply AsQueryable()
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.