EntityFramework - 每个类型的表 (TPT) 继承和映射关系与 CodeFirst

本文关键字:继承 映射 关系 CodeFirst TPT 类型 EntityFramework | 更新日期: 2023-09-27 18:31:15

我有以下实体,我正在使用EntityFramework CodeFirst来保持这些实体:

public class User {
     RedGroup RedGroup { get; protected set; }
     virtual ICollection<GreenGroup> GreenGroups { get;  }
     int Id { get; protected set; }
     int? RedGroupId { get; protected set; }
}
public abstract class Group { 
     int Id { get; protected set; }
     virtual ICollection<User> Users { get; protected set; }
}
public class RedGroup : Group {
    // Other properties
}
public class GreenGroup : Group {
    // Other properties
}

本质上,用户可以属于零个或一个红色组,以及多个绿色组。 每个组都有一个属于它的用户集合。

我正在尝试使用 TPT 的代码优先设置 EF,但在对映射进行排序时遇到问题。 目前,我有以下OnModelCreating

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
     modelBuilder.Configurations.Add(new RedGroupMap());
     modelBuilder.Configurations.Add(new GreenGroupMap());
     modelBuilder.Configurations.Add(new UserMap());
}

这些是映射类:

 public abstract class GroupMap<T> : EntityTypeConfiguration<T>
     where T : Group {
    public GroupMap() {
        this.ToTable("Groups");
        this.HasKey(t => t.Id);
        this.Property(t => t.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity).HasColumnName("Id");
        // Also has other  non-relationship mappings
    }
 }
 public class RedGroupMap() : GroupMap<RedGroup> {
    public RedGroupMap() {
        this.ToTable("RedGroups");
        // Also has other  non-relationship mappings
    }
 }
 public class GreenGroupMap() : GroupMap<GreenGroup> {
    public GreenGroupMap() {
        this.ToTable("GreenGroups");
        this.HasMany(c => c.Users)
            .WithMany(p => p.GreenGroups)
            .Map(m =>
            {
                m.MapLeftKey("GreenGroupId");
                m.MapRightKey("UserId");
                m.ToTable("Users_GreenGroups");
            });
       // Also has other non-relationship mappings
    }
}
public class UserMap() : EntityTypeConfiguration<User> {
  this.ToTable("Users");
  this.HasKey(t => t.Id);
  this.Property(t => t.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity).HasColumnName("Id");
  this.HasOptional(t => t.RedGroup)
            .WithMany(t => t.Users)
            .Map(x => x.MapKey("RedGroupId"))
            .WillCascadeOnDelete(false);
}

我收到以下运行时错误:

Users: FromRole: NavigationProperty 'Users' is not valid. Type 'RedGroup' of FromRole 'User_RedGroup_Target' in AssociationType 'User_RedGroup' must exactly match with the type 'GreenGroup' on which this NavigationProperty is declared on.

恐怕我对如何设置这个感到困惑。

如何设置实体框架映射以允许每个类型的表层次结构?

EntityFramework - 每个类型的表 (TPT) 继承和映射关系与 CodeFirst

我创建了一个没有您的映射的上下文,但配置要简单得多,一切似乎都正常:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);
    modelBuilder.Entity<Group>().ToTable("Groups");
    modelBuilder.Entity<RedGroup>().ToTable("RedGroups");
    modelBuilder.Entity<GreenGroup>().ToTable("GreenGroups");
}

我注意到您已经定义了 [User] .HasOptional(t => t.RedGroup),但用户上的 RedGroupId 字段被定义为int而不是int? - 也许这是相关的?

public class User {
     int? RedGroupId { get; protected set; }    // int -> int?
     RedGroup RedGroup { get; protected set; }  // virtual missing, but shouldn't matter
     // Other properties
}

如果需要 RedGroup,请尝试改用.HasRequired