EF6 Code First Lazy Load导致空集合

时间:2014-07-04 01:54:41

标签: entity-framework ef-code-first lazy-loading

因此创建了动态代理,但我无法弄清楚我做错了什么来防止延迟加载导航属性。以下是我为测试此问题而运行的确切代码。

的DbContext:

public class MyDbContext : DbContext
{
    public MyDbContext()
        : base("MyConnection")
    {
    }

    public DbSet<One> Ones { get; set; }

    public DbSet<Many> Manies { get; set; }
}

类:

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()
    {
    }
}

测试

    [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
    }

数据库:

enter image description here

我已经验证了正在插入数据库的正确信息。关系看起来很好。我确定我错过了一些明显的东西。

更新

这有效:

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);
}

这不是

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
}

因此,内置延迟加载需要相同的db上下文。

2 个答案:

答案 0 :(得分:3)

要触发延迟加载,您需要在处置上下文之前以某种方式访问​​该属性。

在离开上下文之前,您的测试代码不会访问该属性:

    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()

此时,您的上下文已被处理掉。如果您尝试访问Manies属性,则会收到错误消息,说明这一点。

    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(); 
    }

现在,如果您检查manies属性,它将可用。

延迟加载的想法是,当上下文可用时,第一次访问最初未加载的属性时,它将在那时加载。

请参阅此文章,了解使用EF加载实体的不同方式(渴望,懒惰,明确):

Loading Related Entities

答案 1 :(得分:0)

parent2 = db.Ones.Include(o=>o.Manies).FirstOrDefault(o=>o.Id == parent1.Id);