延迟加载启用设置似乎在 EF 5 中不起作用



我首先使用EF模型与POCO实体和自定义DbContexts。我的问题是设置LazyLoadingEnabled=false不影响任何东西,导航属性仍然加载。下面是我的简化示例。

实体程序。一个程序可以是其他程序的一部分:

namespace Domain.Entities
{
    using System;
    using System.Collections.Generic;
    public partial class Program
    {
        public Program()
        {
            this.Programs = new HashSet<Program>();
        }
        public int Id { get; set; }
        public string Title { get; set; }
        public string Description { get; set; }
        public System.DateTime StartDate { get; set; }
        public System.DateTime EndDate { get; set; }
        public Nullable<int> ProgramId { get; set; }
        public virtual ICollection<Program> Programs { get; set; }
        public virtual Program OwnerProgram { get; set; }
    }
}
DbContext

:

namespace Infrastructure.Model
{
    public class ProgramContext : DbContext
    {
        public ProgramContext()
            : base("name=MyContainer")
        {
            Configuration.LazyLoadingEnabled = false;
        }
        public DbSet<Program> Programs { get; set; }
    }
}

我是这样使用的:

private ProgramContext _dbContext = new ProgramContext();
// GET api/program
public IEnumerable<Program> GetPrograms()
{
    List<Program> list = _dbContext.Programs.ToList();
    return list;
}
在上面的示例中,EF仍然加载Program类的Programs和OwnerProgram属性。我已经尝试删除虚拟关键字,禁用代理创建,并且还验证了模型本身的LazyLoadingEnabled=false

我错过了什么吗?

你看到的效果叫做关系修复

实际上导航属性是而不是显式加载的。查询_dbContext.Programs.ToList()只从数据库加载整个Programs表。这只是一个简单的SQL查询(如SELECT * FROM ProgramsTable),没有任何WHERE子句,也没有任何JOIN到相关行。

当你访问program.Programsprogram.OwnerProgram导航属性时,这里也不会发生延迟加载(如果你禁用它,甚至禁用动态代理,它真的不能)。

导航属性在查询结果具体化时被填充,因为您的查询(加载所有程序)将加载导航属性可以引用的所有程序。EF检测到那些相关的实体已经在内存中,并自动将它们放入导航属性中。

如果您不加载所有程序,而只加载一个程序,您可以验证这一点:

Program program  = _dbContext.Programs.FirstOrDefault();

现在,program.Programsprogram.OwnerProgram将是null -除非加载的program是它自己的program.OwnerProgram集合的一部分或它自己的OwnerProgram

"EF仍然加载程序的Programs和OwnerProgram属性阶级"

这是正确的行为,但它不是惰性加载导航属性,而是主动加载。

这意味着检索导航属性值所需的数据库查询将在检索Program实体并填充导航属性时立即执行。

LazyLoadingEnabled被设置为true时,这些查询不会被触发,直到您尝试访问导航属性。这也适用于当你将鼠标悬停在导航属性上并且附加了调试器时,这可能会导致你认为实体没有被惰性加载,而实际上它们是-调试器正在访问导航属性,因此实体框架加载它。

在调试代码时,您可以运行像这样的SQL分析器来准确地查看查询何时被触发。

在上面的示例中,EF仍然加载Programs和OwnerProgram类的属性。我试过移除虚拟关键字,禁用代理创建,还验证了LazyLoadingEnabled=false

我错过了什么吗?

您需要删除初始化这些属性的默认构造函数。

最新更新