如何正确触发延迟加载的集合在实体框架5

本文关键字:实体 框架 集合 何正确 延迟加载 | 更新日期: 2023-09-27 18:03:54

我在我的应用程序中使用EF5(代码优先)。我有一个包含几个延迟加载字段的表。

public class TestEntity
{
    public int Id { get; set; }
    public virtual TestEntity2 SubEntity2 { get; set; }
    public virtual TestEntity3 SubEntity3 { get; set; }
    private ICollection<SubEntity4> _subEntities;
    public ICollection<SubEntity4> SubEntities
    {
        get { return _subEntities ?? (_subEntities = new Collection<SubEntity4>()); }
        protected set { _subEntities = value; }
    }
}

当我从数据库SubEntity2和SubEntity3读取这是加载很好,但SubEntities收集只是不会加载,它总是停留计数=0。所以我像这样强制加载:

db.Entry(queryResult).Collection(rr => rr.SubEntities).Load();

但是据我所知,这个集合应该在第一次调用期间由EF自动加载,就像SubEntity2和SubEntity3一样。为什么它在收集方面不起作用?

代码的例子,我正在使用读取数据库:

using (var db = new TestContext(_connection, false))
        {
            var query = from r in db.SubEntities
                        where r.Id == 10
                        select r;
            var queryRes = query.FirstOrDefault();
            if (queryRes != null)
            {
                if (queryRes.FederalRegion != null)
                {
                    // Do something
                }
                foreach (var dbEnt in queryRes.SubEntities)
                {
                    // Do something
                }
            }
        }

如何正确触发延迟加载的集合在实体框架5

为了使延迟加载工作,EF5必须做一些棘手的工作。在运行时,它们创建代理类,这些代理类派生自您的模型类。在这些代理类中,它们覆盖导航属性来实现延迟加载机制。

您的SubEntity2SubEntity3属性是虚拟的,因此它们可以被覆盖。你的SubEntities属性不是虚拟的- EF5不能覆盖这个属性来实现延迟加载。

当你将SubEntities属性设置为虚拟时,它应该可以工作。

你所描述的子实体(集合)本质上是惰性加载的。如果你不想让它们惰性加载,你应该使用.Include(x=> x.SubEntitiesCollectionName)扩展方法。

编辑

你的类应该是这样的:

public class TestEntity
{
    public int Id { get; set; }    
    public virtual TestEntity2 SubEntity2 { get; set; }
    public virtual TestEntity3 SubEntity3 { get; set; }    
    public virtual ICollection<SubEntity4> SubEntities { get; set; }
}

要启用延迟加载,您必须使您的字段virtual,这是真的。但你还有另一个问题。ICollection<SubEntity4>等于private。这使得映射器无法访问您的字段。我有类似的问题,并询问如何设置实体的私有字段为映射器可见。答案是"这是不可能的"!这是一个链接:

如何映射实体的私有属性

那么就像这样做:

   public virtual ICollection<SubEntity4> SubEntities {get;set};