Entity Framework - 父子关系 table

Entity Framework - Parent Child relational table

我有一个组织实体 table

public class Organization
{
    public int OrganizationId { get; set; } 
    public string Name { get; set; }        
    public int OrganizationTypeId { get; set; } 
    public OrganizationType OrganizationType { get; set; }
    public ICollection<OrganizationRelation> OrganizationRelations { get; set; }        
}

然后我有我的关系 table 和一个自引用父列

public class OrganizationRelation
{
    public int OrganizationRelationId { get; set; }
    public int OrganizationId { get; set; }        
    public int? ParentOrganizationId { get; set; }
    public Organization Organization { get; set; }
    public Organization ParentOrganization { get; set; }
}

public class OrganizationRelationModelConfiguration : IEntityTypeConfiguration<OrganizationRelation>
{
    public void Configure(EntityTypeBuilder<OrganizationRelation> builder)
    {
        builder.HasKey(c => c.OrganizationRelationId);
        builder.Property(c => c.OrganizationRelationId).ValueGeneratedOnAdd();
        builder.Property(c => c.OrganizationId).IsRequired();
        builder.Property(c => c.ParentOrganizationId);            
        builder.HasOne(r => r.Organization).WithMany().HasForeignKey(fk => fk.OrganizationId);
        builder.HasOne(r => r.ParentOrganization).WithMany().HasForeignKey(fk => fk.ParentOrganizationId);
        builder.ToTable("OrganizationRelation", "dbo");
    }
}

当我使用迁移部署我的数据库时,我看到 table 创建了:

CREATE TABLE [mdo].[OrganizationRelation](
[OrganizationRelationId] [int] IDENTITY(1,1) NOT NULL,
[OrganizationId] [int] NOT NULL,
[ParentOrganizationId] [int] NULL,
[OrganizationId1] [int] NULL,
 CONSTRAINT [PK_OrganizationRelation] PRIMARY KEY CLUSTERED
(
[OrganizationRelationId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

我正在使用 EF 5.0 我不明白为什么要创建列 OrganizationId1

您没有将 OrganizationRelation.ParentOrganization 映射到 Organization.OrganizationRelations,因此 EF 正在为第二个导航 属性 添加一个额外的 FK 到 OrganizationRelation

但该模型似乎过于复杂。为什么不

public class Organization
{
    public int OrganizationId { get; set; }
    public string Name { get; set; }
    public int OrganizationTypeId { get; set; }
    public int? ParentOrganizationId { get; set; }
    public Organization ParentOrganization { get; set; }
    public ICollection<Organization> ChildOrganizations{ get; } = new HashSet<Organization>();
}

这创造了

  CREATE TABLE [Organization] (
      [OrganizationId] int NOT NULL IDENTITY,
      [Name] nvarchar(max) NULL,
      [OrganizationTypeId] int NOT NULL,
      [ParentOrganizationId] int NULL,
      CONSTRAINT [PK_Organization] PRIMARY KEY ([OrganizationId]),
      CONSTRAINT [FK_Organization_Organization_ParentOrganizationId] FOREIGN KEY ([ParentOrganizationId]) REFERENCES [Organization] ([OrganizationId]) ON DELETE NO ACTION
  );

  CREATE INDEX [IX_Organization_ParentOrganizationId] ON [Organization] ([ParentOrganizationId]);

?

要将外键分解为单独的 table,您只需引入 1-1 依赖项 table,其中依赖项 table 的 FK 和 PK 相同作为主要table的PK。

所以用一个单独的实体做同样的事情看起来像这样:

public class Organization
{
    public int OrganizationId { get; set; }
    public string Name { get; set; }
    public int OrganizationTypeId { get; set; }
    public OrganizationRelation OrganizationRelation { get; set; }
    public ICollection<OrganizationRelation> ChildOrganizations { get; } = new HashSet<OrganizationRelation>();
}
public class OrganizationRelation
{
    public int OrganizationId { get; set; }
    public int ParentOrganizationId { get; set; }
    public Organization Organization { get; set; }
    public Organization ParentOrganization { get; set; }
}

protected override void OnModelCreating(ModelBuilder builder)
{
    base.OnModelCreating(builder);

    builder.Entity<OrganizationRelation>().HasKey(c => c.OrganizationId);

    builder.Entity<OrganizationRelation>()
           .HasOne(r => r.Organization)
           .WithOne(o => o.OrganizationRelation)
           .HasForeignKey(nameof(OrganizationRelation), nameof(OrganizationRelation.OrganizationId));

    builder.Entity<OrganizationRelation>()
           .HasOne(r => r.ParentOrganization)
           .WithMany(o => o.ChildOrganizations)
           .HasForeignKey(r => r.ParentOrganizationId)
           .OnDelete(DeleteBehavior.Restrict);

    builder.Entity<OrganizationRelation>().ToTable("OrganizationRelation", "dbo");


    base.OnModelCreating(builder);

}