EF Core 5.x 如何配置两实体间多个带关联实体的多对多关系
实现方案
你可以利用EF Core的共享实体类型特性,仅定义一个通用关联类,同时映射为两个独立的数据库关联表,完全消除代码冗余。
步骤1:定义通用关联实体
public class GameCard { public int GameId { get; set; } public Game Game { get; set; } public int Order { get; set; } public int CardId { get; set; } public Card Card { get; set; } }
步骤2:调整业务实体属性
public class Game { [Key] public int Id { get; set; } // 直接使用通用关联类作为导航属性类型 public ICollection<GameCard> Deck { get; set; } public ICollection<GameCard> OnTable { get; set; } [Required] public int CardIndex { get; set; } [Required] public int PlayerId { get; set; } [Required] public Player Player { get; set; } } public class Card : IEntity { [Key] public int Id { get; set; } [Required] public Shape Shape { get; set; } [Required] public Fill Fill { get; set; } [Required] public Color Color { get; set; } [Required] public int NrOfShapes { get; set; } // 分别对应两组多对多关系的导航 public ICollection<GameCard> DeckCards { get; set; } public ICollection<GameCard> TableCards { get; set; } }
步骤3:配置模型映射
在OnModelCreating中把同一个GameCard类分别映射为两个不同的数据库实体,对应两张独立的关联表:
protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); // 配置第一组:牌堆关联,映射到DeckGameCards表 modelBuilder.Entity<GameCard>("DeckGameCard", builder => { builder.ToTable("DeckGameCards"); builder.HasKey(x => new {x.GameId, x.CardId}); builder.HasOne(gc => gc.Card) .WithMany(c => c.DeckCards) .HasForeignKey(gc => gc.CardId); builder.HasOne(gc => gc.Game) .WithMany(g => g.Deck) .HasForeignKey(gc => gc.GameId); }); // 配置第二组:桌面关联,映射到TableGameCards表 modelBuilder.Entity<GameCard>("TableGameCard", builder => { builder.ToTable("TableGameCards"); builder.HasKey(x => new {x.GameId, x.CardId}); builder.HasOne(gc => gc.Card) .WithMany(c => c.TableCards) .HasForeignKey(gc => gc.CardId); builder.HasOne(gc => gc.Game) .WithMany(g => g.OnTable) .HasForeignKey(gc => gc.GameId); }); }
配置完成后生成迁移,EF会自动创建两张结构完全独立的关联表,使用方式和你之前两套关联实体的用法完全一致。
内容的提问来源于stack exchange,提问作者Joris L
相关产品推荐
相关产品推荐

