This may be a really elementry question but whats a nice way to include multiple children entities when writing a query that spans THREE levels (or more)?
i.e. I have 4 tables: Company
, Employee
, Employee_Car
and Employee_Country
Company has a 1:m relationship with Employee.
Employee has a 1:m relationship with both Employee_Car and Employee_Country.
If i want to write a query that returns the data from all 4 the tables, I am currently writing:
Company company = context.Companies
.Include("Employee.Employee_Car")
.Include("Employee.Employee_Country")
.FirstOrDefault(c => c.Id == companyID);
There has to be a more elegant way! This is long winded and generates horrendous SQL
I am using EF4 with VS 2010
Use extension methods. Replace NameOfContext with the name of your object context.
Then your code becomes
EF 4.1 to EF 6
There is a strongly typed
.Include
which allows the required depth of eager loading to be specified by providing Select expressions to the appropriate depth:The Sql generated in both instances is still by no means intuitive, but seems performant enough. I've put a small example on GitHub here
EF Core
EF Core has a new extension method,
.ThenInclude()
, although the syntax is slightly different:As per the docs, I would keep the extra 'indent' in the
.ThenInclude
to preserve your sanity.Obsolete Info (Don't do this):
The multiple grandchildren loading could be done in one step, but this requires a rather awkward reversal back up the graph before heading down the next node (NB: This does NOT work with
AsNoTracking()
- you'll get a runtime error):So I would stay with the first option (one Include per leaf entity depth model).
You might find this article of interest which is available at codeplex.com.
The article presents a new way of expressing queries that span multiple tables in the form of declarative graph shapes.
Moreover, the article contains a thorough performance comparison of this new approach with EF queries. This analysis shows that GBQ quickly outperforms EF queries.
How do you construct a LINQ to Entities query to load child objects directly, instead of calling a Reference property or Load()
There is no other way - except implementing lazy loading.
Or manual loading....