Asp.net MVC多对多连接表DbContext返回Null,不改设计能否解决?
不用改数据库设计就能解决!多对多连接表查询返回Null的排查方案
我之前也碰到过Asp.NET MVC里EF多对多关联查询返回Null的问题,完全不用动数据库设计就能搞定,你可以按下面的步骤一步步排查解决:
一、先确认实体关系配置是否正确
从你说的连接表有Id字段来看,这应该是一个独立的实体类(不是EF自动生成的无实体连接表),这种情况下必须在DbContext里正确配置外键关系,否则EF没法识别关联:
假设你的实体类大概是这样的:
public class Stationery { public int Id { get; set; } // 其他业务属性 public ICollection<StationeryUOM> StationeryUOMs { get; set; } } public class UOM { public int Id { get; set; } // 其他业务属性 public ICollection<StationeryUOM> StationeryUOMs { get; set; } } public class StationeryUOM { public int Id { get; set; } public int Stationery_Id { get; set; } public int UOM_Id { get; set; } public Stationery Stationery { get; set; } public UOM UOM { get; set; } }
那一定要在DbContext的OnModelCreating方法里配置关联:
protected override void OnModelCreating(DbModelBuilder modelBuilder) { // 配置连接表的主键 modelBuilder.Entity<StationeryUOM>() .HasKey(su => su.Id); // 配置与Stationery的一对多关系 modelBuilder.Entity<StationeryUOM>() .HasRequired(su => su.Stationery) .WithMany(s => s.StationeryUOMs) .HasForeignKey(su => su.Stationery_Id); // 配置与UOM的一对多关系 modelBuilder.Entity<StationeryUOM>() .HasRequired(su => su.UOM) .WithMany(u => u.StationeryUOMs) .HasForeignKey(su => su.UOM_Id); }
如果跳过这一步,EF没法识别外键关联,查询时自然会返回Null。
二、查询时显式加载关联数据
就算配置对了关系,EF默认的延迟加载也可能导致关联实体为Null,推荐用Include显式加载更可控:
1. 如果需要同时获取连接表和关联的Stationery、UOM数据
var targetData = db.StationeryUOMs .Include(su => su.Stationery) // 显式加载关联的Stationery .Include(su => su.UOM) // 显式加载关联的UOM .FirstOrDefault(su => su.Id == 1 && su.Stationery_Id == 1 && su.UOM_Id == 1);
2. 如果只需要连接表本身的数据
直接查询即可,不用Include:
var targetData = db.StationeryUOMs .FirstOrDefault(su => su.Id == 1 && su.Stationery_Id == 1 && su.UOM_Id == 1);
如果这时候还是返回Null,先去数据库里跑个SQL确认数据是否存在:
SELECT * FROM StationeryUOM WHERE Id = 1 AND Stationery_Id = 1 AND UOM_Id = 1;
要是数据库里根本没这条数据,那查询自然返回Null,得先确认数据插入是否正确。
三、备选:检查延迟加载配置(不推荐依赖,但可以排查)
如果你想用延迟加载自动加载关联实体,需要满足两个条件:
- 实体的导航属性必须是
virtual的,比如:
public virtual Stationery Stationery { get; set; } public virtual UOM UOM { get; set; } public virtual ICollection<StationeryUOM> StationeryUOMs { get; set; }
- DbContext的延迟加载必须开启(默认是开启的,但如果手动关了要打开):
public class YourDbContext : DbContext { public YourDbContext() : base("YourConnectionString") { this.Configuration.LazyLoadingEnabled = true; } // DbSet定义... }
不过延迟加载容易导致N+1查询问题,还是用Include显式加载更稳妥。
内容的提问来源于stack exchange,提问作者Triple K
相关产品推荐
相关产品推荐

