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.
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:
At this point, your context has been disposed. If you tried to access the
Manies
property you'd get an error stating this.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