我首先使用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.Programs
和program.OwnerProgram
导航属性时,这里也不会发生延迟加载(如果你禁用它,甚至禁用动态代理,它真的不能)。
导航属性在查询结果具体化时被填充,因为您的查询(加载所有程序)将加载导航属性可以引用的所有程序。EF检测到那些相关的实体已经在内存中,并自动将它们放入导航属性中。
如果您不加载所有程序,而只加载一个程序,您可以验证这一点:
Program program = _dbContext.Programs.FirstOrDefault();
现在,program.Programs
和program.OwnerProgram
将是null
-除非加载的program
是它自己的program.OwnerProgram
集合的一部分或它自己的OwnerProgram
。
"EF仍然加载程序的Programs和OwnerProgram属性阶级"
这是正确的行为,但它不是惰性加载导航属性,而是主动加载。
这意味着检索导航属性值所需的数据库查询将在检索Program
实体并填充导航属性时立即执行。
当LazyLoadingEnabled
被设置为true
时,这些查询不会被触发,直到您尝试访问导航属性。这也适用于当你将鼠标悬停在导航属性上并且附加了调试器时,这可能会导致你认为实体没有被惰性加载,而实际上它们是-调试器正在访问导航属性,因此实体框架加载它。
在调试代码时,您可以运行像这样的SQL分析器来准确地查看查询何时被触发。
在上面的示例中,EF仍然加载Programs和OwnerProgram类的属性。我试过移除虚拟关键字,禁用代理创建,还验证了LazyLoadingEnabled=false我错过了什么吗?
您需要删除初始化这些属性的默认构造函数。