In lazy loading related data isn't retrieved when entity is first read. These are automatically retrieved the first time when you attempt to access it.
IEnumerable products = productContext.Products;
foreach (var p in products.ToList()) //Query tblProduct
{
var reviews = p.Reviews; //Query tblReview related to Product p, which will mean this query will be executed for each products
}
Explicit loading is similar to Lazy loading except that related data retrieve doesn't happen automatically
productContext.Configuration.LazyLoadingEnabled = false;
IEnumerable products = productContext.Products;
foreach (var product in products.ToList()) //Query tblProduct
{
productContext.Entry(product).Collection(x=>x.Reviews).Load(); //Query tblReview related to Product p
productContainer.Entry(product).Collection(x=>x.Reviews).Query().Where(r=>r.Name.FirstName=="test").Load();
var reviews = p.Reviews;
}
These are also known as deferred loading.
Deferred loading can be used for cases where you have complex join or you are going to use related data only for subset of entity. Like you retrieve all product (may be 1000 in number) and display review only for the first product.
For lazing loading you have to make sure that the ObjectContext instance has not been disposed, otherwise you will get exception, so the following will not work
using (var productContainer = new ProductContainerCodeFirst())
{
products = productContainer.Products.ToList();
}
//The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.
foreach (var review in product.Reviews)
In Eager loading related data is retrieved when entity is read. This result in single join query that retrieve all the related data. This can be achieved by setting LazyLoadingEnabled = false or by removing virtual keyword when you declare the property.
productContext.Configuration.LazyLoadingEnabled = false;
products = productContainer.Products.Include(a => a.Reviews.Select(b => b.Address)).Include(a => a.Reviews.Select(b => b.Name)).ToList();
foreach (var p in products) //Query tblProduct and tblReview
{
var reviews = p.Reviews;
}
In general, if you know you need related data for every entity retrieved, eager loading offers the best performance, because a single query sent to the database is typically more efficient than separate queries for each entity retrieved. Also during serialization, you would want to turn lazy loading off as a serialize accesses all properties which will mean it will trigger a query for each navigation property that it accesses
The DbContext class performs lazy loading by default. To disable remove virtual keyword when you declare the property or set LazyLoadingEnabled to false.
Referenced POCO
[Table("tblProduct")]
public class Product
{
public string Name { get; set; }
public virtual List Reviews { get; set; }
}
[Table("tblReview")]
public class Review
{
public int Id { get; set; }
public string ReviewerName { get; set; }
public virtual Name Name { get; set; }
}
[Table("tblName")]
public class Name
{
public int Id { get; set; }
public string LastName { get; set; }
public string FirstName { get; set; }
}