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

数据库上下文:

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在模型本身上验证了这一点。

我错过了什么吗?

4

3 回答 3

6

您看到的效果称为关系修复

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

program.Programs当您访问和program.OwnerProgram导航属性时,这里也不会发生延迟加载(如果您禁用它并且甚至禁用动态代理,它确实不会发生) 。

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

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

Program program  = _dbContext.Programs.FirstOrDefault();

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

于 2013-05-04T14:05:40.940 回答
2

“EF 仍然加载 Program 类的 Programs 和 OwnerProgram 属性”

这是正确的行为,但不是懒惰地加载导航属性,而是急切地加载它们。

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

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

您可以运行一个SQL 探查器,例如,在调试代码时准确查看何时触发查询。

于 2013-05-04T12:34:02.127 回答
0

对于上面的示例,EF 仍然加载 Program 类的 Programs 和 OwnerProgram 属性。我尝试删除虚拟关键字,禁用代理创建,并验证模型本身的 LazyLoadingEnabled=false。

我错过了什么吗?

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

于 2013-05-04T12:41:50.497 回答