EF6 Code First Lazy Load results in null collection
ef-code-first, entity-framework, lazy-loading
Solution
To trigger lazy loading you need to access the property in some way, before disposing of the context.
Your test code doesn't acces the property before leaving the context:
One parent2;
using (MyDbContext db = new MyDbContext())
{
db.Configuration.ProxyCreationEnabled = true;
db.Configuration.LazyLoadingEnabled = true;
parent2 = db.Ones.Find(parent1.Id);//parent2 is a dynamic proxy
}
// Context disposed: thsi would throw an exception:
var manies = parent2.Manies.ToList()
At this point, your context has been disposed. If you tried to access the `Manies` property you'd get an error stating this.
One parent2;
using (MyDbContext db = new MyDbContext())
{
db.Configuration.ProxyCreationEnabled = true;
db.Configuration.LazyLoadingEnabled = true;
parent2 = db.Ones.Find(parent1.Id);//parent2 is a dynamic proxy
// Context available: this sill lazy load the Manies entities
var manies = parent2.Manies.ToList();
}
Now, if you check the manies properties, it will be available.
The idea of lazy loading is that, while the context is available, the first time you access a property which wasn't loaded initially, it will be loaded at that moment.
Please, see this article to understand the different ways (eager, lazy, explicit) of loading entities with EF:
Loading Related Entities
Problem
So the dynamic proxy is created, but I can't figure out what I've done wrong to prevent navigation properties from lazy loading. Here is the exact code I've run to test the issue. DbContext: ``` public class MyDbContext : DbContext { public MyDbContext() : base("MyConnection") { } public DbSet<One> Ones { get; set; } public DbSet<Many> Manies { get; set; } } ``` Classes: ``` public class One { public int Id { get; set; } public virtual ICollection<Many> Manies { get; set; } public One() { Manies = new List<Many>(); } } public class Many { public int Id { get; set; } public string Value { get; set; } public int OneId { get; set; } public virtual One One { get; set; } public Many() { } } ``` Test: ``` [TestMethod] public void OneToManyTest() { One parent1 = new One(); parent1.Manies.Add(new Many() { Value = "child 1" }); parent1.Manies.Add(new Many() { Value = "child 2" }); using (MyDbContext db = new MyDbContext()) { db.Ones.Add(parent1); db.SaveChanges(); } Assert.IsTrue(parent1.Id > 0, "Id not set"); One parent2; using (MyDbContext db = new MyDbContext()) { db.Configuration.ProxyCreationEnabled = true; db.Configuration.LazyLoadingEnabled = true; parent2 = db.Ones.Find(parent1.Id);//parent2 is a dynamic proxy } Assert.AreEqual(parent1.Id, parent2.Id); /*parent2.Manies is null*/ Assert.AreEqual(parent1.Manies.Count, parent2.Manies.Count);//fails } ``` Database: I've verified the correct information is being inserted in the database. The relationships look good. I'm sure I'm missing something obvious. Update This works: ``` using (MyDbContext db = new MyDbContext()) { db.Configuration.ProxyCreationEnabled = true; db.Configuration.LazyLoadingEnabled = true; parent2 = db.Ones.Find(parent1.Id);//parent2 is a dynamic proxy Assert.AreEqual(parent1.Id, parent2.Id); Assert.AreEqual(parent1.Manies.Count, parent2.Manies.Count); } ``` This doesn't: ``` using (MyDbContext db = new MyDbContext()) { db.Configuration.ProxyCreationEnabled = true; db.Configuration.LazyLoadingEnabled = true; parent2 = db.Ones.Find(parent1.Id);//parent2 is a dynamic proxy } using (MyDbContext db = new MyDbContext()) { Assert.AreEqual(parent1.Id, parent2.Id); Assert.AreEqual(parent1.Manies.Count, parent2.Manies.Count);//parent2.Manies is null } ``` So the same db context is required for built in lazy loading.