数据库优先Scaffolding生成模型类未包含引用对象问题咨询
问题分析与解决办法
这其实是实体框架(EF)中导航属性加载机制的问题,不是你操作有误,而是对生成类的工作原理存在一点误解~
为什么直接访问myGroup.Persons会为空?
当你通过Scaffolding生成数据库优先的实体类时,默认情况下EF不会自动启用延迟加载。也就是说,当你获取myGroup对象时,EF只会查询Group表的数据,不会自动去关联查询Person表的相关数据,所以myGroup.Persons会是空集合。而你手动用context.Persons.Where(...)查询时,是主动发起了针对Person表的查询,自然能拿到数据。
解决办法
根据你的需求,有三种常见的方式可以让myGroup.Persons正确加载关联数据:
1. 启用延迟加载
延迟加载会在你首次访问导航属性(比如myGroup.Persons)时,自动从数据库加载关联数据。要启用它需要两步:
- 安装
Microsoft.EntityFrameworkCore.ProxiesNuGet包(如果你用的是EF Core) - 在你的DbContext配置中启用代理延迟加载:
同时确保你的protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseLazyLoadingProxies() // 启用延迟加载代理 .UseSqlServer("你的数据库连接字符串"); }Group和Person类是public且包含无参构造函数,生成的类一般默认满足这个条件。
2. 显式加载
如果你不想启用全局的延迟加载,可以在获取myGroup之后,手动触发导航属性的加载:
var myGroup = context.Groups.FirstOrDefault(g => g.Id == targetId); // 显式加载关联的Persons context.Entry(myGroup).Collection(g => g.Persons).Load(); // 此时myGroup.Persons就有数据了 var personsInGroup = myGroup.Persons.ToList();
3. 预先加载(Eager Loading)
在查询Group的时候,直接通过Include方法指定要一起加载的导航属性,这样查询时会一次性把Group和关联的Person数据都取回来:
var myGroup = context.Groups .Include(g => g.Persons) // 预先加载Persons导航属性 .FirstOrDefault(g => g.Id == targetId); var personsInGroup = myGroup.Persons.ToList(); // 此时直接就能拿到数据
额外验证
先确认一下生成的Group类是否包含导航属性,应该有类似这样的代码:
public virtual ICollection<Person> Persons { get; set; }
如果没有的话,可能是Scaffolding时没识别到外键关联,这时候需要检查你的数据库外键约束是否正确,或者重新执行Scaffold命令。
内容的提问来源于stack exchange,提问作者SørenHN
相关产品推荐
相关产品推荐

