EF6代码首次延迟加载导致空集合 [英] EF6 Code First Lazy Load results in null collection

查看:80
本文介绍了EF6代码首次延迟加载导致空集合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

课程:

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
    }

数据库:

我已验证数据库中已插入正确的信息.关系看起来不错.我确定我缺少明显的东西.

I've verified the correct information is being inserted in the database. The relationships look good. I'm sure I'm missing something obvious.

更新

这有效:

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
}

因此,内置延迟加载需要相同的数据库上下文.

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:

    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属性,则会显示一条错误消息.

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

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

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.

请参阅本文以了解使用EF加载实体的不同方式(急切,懒惰,显式):

Please, see this article to understand the different ways (eager, lazy, explicit) of loading entities with EF:

加载相关实体

这篇关于EF6代码首次延迟加载导致空集合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆