1. | Entity Framework uses (by default) a feature called Lazy Loading. This means that when you load up a class which has related classes as members, it does not load up those related members until you actually need them. As an example, if you had a FormYear object representing a school class form, then it may contain many Pupil objects. When loading up one or more FormYear objects, the overhead in loading all the Pupil objects could become large. EF Lazy Loading means that the queries to fetch the related objects is deferred until you need to access them. This option is turned on in EF by default. |
2. |
So let's use the previous model of a school, and you need a Pupil and FormYear objects. You design the POCO objects in code.
using System; using System.Collections.Generic; using System.Linq; using System.Web; public class Pupil { [Key] [Required] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int PupilId { get; set; } [Required] [StringLength(100)] public string Name { get; set; } [Required] public DateTime DateOfBirth { get; set; } [StringLength(200)] public string PrimarySchool { get; set; } } public class FormYear { [Key] [Required] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int FormYearId { get; set; } [Required] [StringLength(100)] public string Name { get; set; } public virtual ICollection<Pupil> Pupils { get; set; } }You can see that the FormYear object contains a collection of Pupil objects and a single linked Teacher object. |
3. |
So let's turn off Lazy Loading in our Context:
using System.Data; using System.Data.Entity; using System.Data.EntityModel; namespace TestEF.Contexts { public class SchoolContext : DbContext { public DbSet<TestEF.Entity.Pupil> Pupils { get; set; } public DbSet<TestEF.Entity.FormYear> FormYears { get; set; } public SchoolContext() { this.Configuration.LazyLoadingEnabled = false; } } }Also, we set up the connection string and the database regeneration plan in global.asax as before. |
4. |
We open a context so we can populate the entities:
using (TestEF.Contexts.SchoolContext TheSchool = new TestEF.Contexts.SchoolContext()) { // create a couple of pupils Entity.Pupil p1 = new Entity.Pupil(); p1.Name = "John Curran"; p1.DateOfBirth = DateTime.Parse("25/01/1969"); p1.PrimarySchool = "St Denis"; Entity.Pupil p2 = new Entity.Pupil(); p2.Name = "Mark Milarvie"; p2.DateOfBirth = DateTime.Parse("19/07/1969"); p2.PrimarySchool = "St Denis"; // create a form Entity.FormYear f1 = new Entity.FormYear(); f1.Name = "5 Ogilvie"; // add a new list of pupils to the form, and add the pupils f1.Pupils = new List<TestEF.Entity.Pupil>(); f1.Pupils.Add(p1); f1.Pupils.Add(p2); // add the form to the DbContext, then save TheSchool.FormYears.Add(f1); TheSchool.SaveChanges(); }Because we've already been into the Pupils collection the entities are already loaded, so we need to close this context and open a new one. Now navigate from the first (and only) FormYear to the pupils collection: using (TestEF.Contexts.SchoolContext TheSchool = new TestEF.Contexts.SchoolContext()) { Entity.Form f1 = TheSchool.FormYears.First(); Entity.Pupil pupil = f1.Pupils.Single(p => p.Name == "John Curran"); }This throws an NullException error! The Pupils collection is empty, because Lazy Loading has been turned off! We have to explicitly load them if we want them. using (TestEF.Contexts.SchoolContext TheSchool = new TestEF.Contexts.SchoolContext()) { Entity.Form f1 = TheSchool.FormYears.First(); TheSchool.Pupils.Load(); Entity.Pupil pupil = f1.Pupils.Single(p => p.Name == "John Curran"); }If you need this level of fine control over the Lazy Loading, this is how you do it. |
And that's the basics of Entity Framework Lazy Loading. |