Let's first discuss why we even need Explicit Loading.
Problem with lazy loading: Lazy loading causes an n+1 issue, meaning that to load N entities and their related entities, we end up with N+1 query requests to the database, which is bad for the performance of the software. In lazy loading, with each iteration, a new request goes to the database, which is obviously not good.
Problem with eager loading: To avoid the n+1 issue, we may use eager loading where we eagerly include the related entities along with the main entity, such that the main entity, along with the related entities, gets loaded into the memory. Later, when we fetch them from memory, no further request goes to the database; thus, it resolves the N+1 issue by sending a single request to the database. But there is a drawback, i.e., if we use multiple include() operators or the include operator contains multi-level related data, it leads to a complex, giant query, and believe me, a giant complex query is worse than multiple query requests to the database.
So, if you want to achieve the following:
- Fewer requests to the database
- Lighter query
Then, you need to use the Explicit Loading. Explicit loading, as the name suggests, loads the entity explicitly, so it is completely in our hands how many requests we want to send to the database. To load an entity, we just need to use the Load() method at the end of the query.
You Don't Need Collection(), Reference() or Entry()
Although there are several operators like Collection(), Entry(), and Reference() that you will find in other blog posts or even in MSDN documents while searching for Explicit loading, believe me, they are of no use, and you can simply achieve the same result with just the Load() method.
Example: Display all comments on Post 1.
var post = db.Posts.Where(p=>p.PostId==1).Single();
db.Entry(post).Collection(c=>c.Comments).Load(); //Loads comment collection explicitly
Console.WriteLine("PostTitle:{0}",Post.PostTitle);
foreach(var comment in post.comments)
{
Console.WriteLine("{0},comment.CommentBody);
}
Example: Display category name of Post 1.
var post = db.Posts.Where(p=>p.PostId==1).Single();
db.Entry(post).Reference(c=>c.Category).Load(); //Loads category
You can see in the above examples, methods like Collection(), Entry(), and Reference() have been used, but the same could be achieved without using any of them, as shown below:
var post = db.Posts.Where(p => p.PostId == 1).Single();
db.Posts.Where(p => p.PostId == post.PostId).Select(c=>c.Comments).Load(); //Load all comments with post
Moreover, the methods like Collection(), Entry(), and Reference() only work when we move either from a single object to a collection, like Post 1 to all related comments, or a single object to a single related entity, like Post 1 to a category entity. However, you can't use them to load a collection of entities and their related entities explicitly, nor can you filter them by a related entity's property.
Example: Display all the categories and related posts where the post title is Post1.
This can't be achieved with the above technique, so instead of remembering all those methods, remember the Load() method, and you can explicitly load any related entity as shown below:
var categories = db.Categories.ToList(); //One request to the database
db.Categories.Select(x=>x.Posts.Where(p=>p.Title=="Post1")).Load(); //Load related posts.
foreach (var cat in categories)
{
Console.WriteLine(cat.CategoryName);
foreach (var post in cat.Posts)
{
Console.WriteLine(post.Body);
}
}