In this post we will talk about Eager Loading. We will use Entity Framework Core 2.1 (although the concept of Eager Loading has been in the Entity Framework for a long time). In addition, we will have the following two models, with their respective tables:
public class Student { public int Id { get; set; } public string Name { get; set; } public List<Contact> Contacts { get; set; } } public class Contact { public int Id { get; set; } public string Name{ get; set; } public string Relationship { get; set; } public int StudentId { get; set; } public Student Student{ get; set; } }
As we can see there is a one-to-many relationship between students and contacts, where each student may have several contacts.
Eager Loading
Eager Loading is a mechanism by which we can load some records and their related records at the same time. The idea is that we can make a query to a table and, in that same query, request that we also get the records of a related table which we choose. When we do this, Entity Framework Core will build a query with a Join statement, in order to get the data from several tables. In the case of our Student and Contacts models, we can make a query where we ask for Students with their respective Contacts. For this we use the function Include.
The Include function is what allows us to say to EF Core that we want to load related data from another table through a navigation property. To the Include function we can pass as an argument the name of the navigation property, either as a string or as a lambda expression. If you are going to use it, you need to include the namespace Microsoft.EntityFrameworkCore. Let’s see an example:
using (var context = new ApplicationDbContext()) { // Option 1: Include with lambda expression var students = context.Students.Include(x => x.Contacts).ToList(); // Option 2: Include with string var students2 = context.Students.Include("Contacts").ToList(); }
If you execute the previous code in debugging mode, then you can see that within the above variables we have a list of students, and each student has their respective contacts (assuming you have data in the database). There is no difference in terms of queries generated in the previous options given. However, from a practical point of view, the first option has the advantage that if we use Visual Studio to rename the Contacts property of the Student class, then the Include of the first option will be renamed automatically, in the second option this It does not happen because it is a string.
How about we have two navigation properties in our Student model and we want to load the related records of both tables? Then we must do two Include‘s, one for each navigation property. Assuming that the new navigation property of the Student model is called Addresses, then to load the related data from the Contacts and Addresses tables, we can use the following code:
var students = context.Students .Include(student => student.Contacts) .Include(student => student.Addresses).ToList();
And what if our Contact model has a navigation property called Addresses and we want to load said data from a query to the Students table? In that case, after the Include (x => x.Contacts), we must use the ThenInclude function. The ThenInclude function allows us to load the related data of a navigation property. The order is important, so we must place the ThenInclude function after the corresponding Include:
var students = context.Students.Include(student => student.Contacts) .ThenInclude(contact => contact.Addresses).ToList();
Since Addresses is now a navigation property of Contacts, then the ThenInclude function (x => x.Address) is placed after the Include (x => x.Contacts).
Summary
Eager Loading allow us to ask for related data from the get go. If we want to delay the loading of related data, we can use Lazy Loading (which EF Core 2.1 supports)