How to eager load with Include() only if not null?

Viewed 9475

I am trying to do:

var abc = Context.PersonSet.Include(p=>p.Child).ToList();

But not all Persons have a Child. So I get:

Type Error I would like to get all Persons, and if the Child is not null, I want to Include it. It would be also ok to Include Child as null.

5 Answers

I don't know why people keep upvoting the solutions like this:

Include(p => p.NavProp ?? new List<NavPropType>())

Because that won't work, that is invalid for Include():

InvalidOperationException:

The Include property lambda expression p => (p.NavProp ?? value(System.Collections.Generic.List'1[NavPropType])) is invalid. The expression should represent a property access: t => t.MyProperty.

To target navigations declared on derived types, specify an explicitly typed lambda parameter of the target type, E.g. (Derived d) => d.MyProperty. For more information on including related data, see http://go.microsoft.com/fwlink/?LinkID=746393.

The solution: declare your property with a default value:

public class Foo
{
    public List<Bar> Bars { get; set; } = new List<Bar>();
}

This makes sure Bars won't be null when no related records are found.

return empty child instead of null

 Context.PersonSet.Include(a => ((a.Child == null) ? new Collection<Child>() : a.Child));

You can use GroupJoin to get all persons and load their children if they have any child: (consider that in this approach you should have DbSet of Children in your context)

Context.PersonSet.GroupJoin(Context.Children, p => p.Id, c => c.PersonId, (p, c) =>
                 new { Person = p, Child = c }).ToList();

The exception shouldn't be coming from that line. Include() should be using a LEFT JOIN which does exactly what you're asking for: "I would like to get all Persons, and if the Child is not null, I want to Include it". To confirm that, check the SQL that is generated from your LINQ.

To fix the issue, look at the code that is using the result of the query abc and see if it is processing the Child collection properly (i.e. checking if the collection is empty).

You can try the following approach:

var abc = Context.PersonSet.Include(p=>p.Child).Where(p=>p.Child!=null).ToList();
Related