EF Core中是否应为所有关联属性启用懒加载?机制解析
EF Core 懒加载相关问题解答
1. 是否需要配置懒加载?具体操作是什么?
- 场景一(User与多对多角色):需要配置懒加载。因为并非所有查询场景都需要角色数据,懒加载能避免不必要的数据库查询,节省性能开销。
- 场景二(Article关联Creator):不需要配置懒加载。所有查询Article的场景都需要Creator信息,直接用
Include(x => x.Creator)做预加载更高效,能避免额外的数据库请求。
配置懒加载的两种常用方式:
方式一:代理懒加载(推荐)
- 安装NuGet包:
Microsoft.EntityFrameworkCore.Proxies - 在DbContext的
OnConfiguring方法中启用代理:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseLazyLoadingProxies() .UseSqlServer("你的数据库连接字符串"); }
- 修改实体类的导航属性为
virtual:- User类:
public virtual List<UserRole> UserRoles { get; set; } - UserRole类:
public virtual User User { get; set; }、public virtual Role Role { get; set; } - Article类:
public virtual User? Creator { get; set; }(若启用全局懒加载需修改,场景二可忽略)
- User类:
方式二:无代理懒加载
若不想使用代理类,可通过ILazyLoader实现:
- 给实体类注入
ILazyLoader,并在导航属性的getter中触发加载:
public class User : IUser { private readonly ILazyLoader _lazyLoader; private List<UserRole> _userRoles; public User(ILazyLoader lazyLoader) { _lazyLoader = lazyLoader; } // 其他属性省略... public List<UserRole> UserRoles { get => _lazyLoader.Load(this, ref _userRoles); set => _userRoles = value; } }
这种方式无需给导航属性加virtual,但需要依赖注入支持。
2. EF Core懒加载的工作机制
EF Core默认不开启懒加载,开启代理懒加载后:
- 查询User时,EF Core仅查询
User表数据,返回一个继承自User的代理类实例。 - 当你第一次访问
User.UserRoles导航属性时,代理类会自动触发EF Core执行数据库查询,获取关联的UserRole和Role数据,再赋值给UserRoles。 - 整个过程要求DbContext实例未被释放,因为需要上下文执行数据库操作。
- 关联数据不会提前加载或缓存,只有在被主动访问时才会发起查询。
3. 未使用Include时,数据是否会加载到内存?
分两种情况:
- 未开启懒加载:导航属性为
null(若构造函数初始化过集合则为空集合),不会从数据库加载任何关联数据,内存中仅保存主实体(如User)的信息。 - 已开启懒加载:只有当你主动访问导航属性(如
user.UserRoles)时,EF Core才会查询数据库并将数据加载到内存;若从未访问该属性,关联数据不会被加载,也不会占用内存。
内容的提问来源于stack exchange,提问作者Muhammet İkbal
相关产品推荐
相关产品推荐

