Entity Framework 6多对多关系未自动生成中间表问题咨询
EF6未自动生成多对多中间表的解决方法
你创建了如下实体类与DbContext,预期Entity Framework 6会自动识别Samurai和Battle的多对多关系并生成BattleSamurai中间表,但数据库生成时未包含该关系:
实体类代码
Battle类
namespace SamuraiApp.Domain { public class Battle { public int BattleId { get; set; } public string Name { get; set; } public List<Samurai> Samurais = new List<Samurai>(); } }
Samurai类
namespace SamuraiApp.Domain { public class Samurai { public int Id { get; set; } public string Name { get; set; } public List<Quote> Quotes { get; set; } = new List<Quote>(); public List<Battle> Battles { get; set; } = new List<Battle>(); } }
DbContext代码
public class SamuraiContext:DbContext { public DbSet<Samurai> Samurais { get; set; } public DbSet<Quote> Quotes { get; set; } public DbSet<Battle> Battles { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlServer("Data Source= (localdb)\\MSSQLLocalDB; Initial Catalog=SamuraiAppData"); // si on a sqlLite on va écrire optionsBuilder.UseSqlLite("<chaine de connexion sqlite>") } }
解决方法
问题出在Battle类的导航属性定义上:
Samurai类里的Battles是带get/set访问器的属性,EF6可以识别;- 但
Battle类里的Samurais是无get/set的字段,EF6的约定仅识别属性作为导航关系的依据,因此无法自动识别多对多关系。
1. 修改Battle类为属性定义
将Samurais字段改为带get/set的属性,EF6就能自动识别多对多关系并生成中间表:
namespace SamuraiApp.Domain { public class Battle { public int BattleId { get; set; } public string Name { get; set; } // 改为属性并初始化 public List<Samurai> Samurais { get; set; } = new List<Samurai>(); } }
2. 可选:用Fluent API显式配置多对多(增强可控性)
如果需要自定义中间表名称或字段,可在SamuraiContext的OnModelCreating方法中显式配置:
protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity<Samurai>() .HasMany(s => s.Battles) .WithMany(b => b.Samurais) .Map(m => { m.ToTable("BattleSamurai"); // 指定中间表名称 m.MapLeftKey("SamuraiId"); // Samurai对应的外键 m.MapRightKey("BattleId"); // Battle对应的外键 }); }
3. 重新生成数据库
修改代码后,可通过以下方式更新数据库:
- 如果使用Code First迁移:运行
Add-Migration AddSamuraiBattleManyToMany和Update-Database命令; - 直接删除现有数据库,让EF6重新生成。
内容的提问来源于stack exchange,提问作者Mechi Walid
相关产品推荐
相关产品推荐

