Entity Framework and lazy loading
Entity Framework and virtual properties
Some of you may have come across a situation where you’ve created your model and found that one of the properties is null when you were expecting a value.
Here’s a simple setup that would produce the error:
public class Person {
public int PersonID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public PersonDetail Details { get; set; }
}
public class PersonDetail {
public int PersonDetailID { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public DateTime DOB { get; set; }
public string About { get; set; }
}
Person owner = db.People.Single(p => p.PersonID == 1);
output(owner.Details);
owner.Details would be null here due to LazyLoading. This allows us to have an object with many different objects that are only loaded when needed rather than loaded when a parent object is loaded. This is especially helpful if you have something like a Comments property as part of the user. Without LazyLoading the comments collection would be loaded whenever you wanted to grab just the First Name. A downside to LazyLoading is that each navigation performed requires a separate query to the data source. (Unless that object has already be loaded)
To allow for LazyLoading you need to mark related object properties as virtual.
public class Person {
public int PersonID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public virtual PersonDetails Details { get; set; }
}
In addition you must supply a navigation property in your context:
public class Database : DbContext {
public DbSet<Person> People { get; set; }
public DbSet<PersonDetail> PersonDetails { get; set; }
}
Doing the above will allow entity framework to generate proxy classes that allow for lazy loading. Other requirements for these proxy classes to be generated:
- A class must be public.
- A class cannot be marked as sealed (or NotInheritable).
- A class cannot be marked as abstract (or MustInherit).
- A class must have a parameterless constructor that is public or protected.
- A class must not implement IEntityWithChangeTracker or IEntityWithRelationships interfaces because the EF generated proxies already implement them.
- The ObjectContext property ProxyCreationEnabled must be set to true. (default)