【问题标题】:Why EF Core keeps adding shadow properties to migration files? Like AgencyId1, AgencyId2 etc为什么 EF Core 不断向迁移文件添加影子属性?像 AgencyId1、AgencyId2 等
【发布时间】:2021-08-02 13:09:35
【问题描述】:

当我尝试创建迁移时,EF 不断添加影子属性,例如 AgencyId、AgencyId1、AgencyId2。我认为问题出在我的配置中,但我尝试了几种方法,但都没有奏效

生成类似的东西:

  migrationBuilder.CreateTable(
            name: "Packages",
            columns: table => new
            {​
                AgencyId1 = table.Column<int>(type: "int", nullable: true),
                AgencyId = table.Column<int>(type: "int", nullable: false)
            }​,
            constraints: table =>
            {​
                table.PrimaryKey("PK_Packages", x => x.Id);
                table.ForeignKey(
                    name: "FK_Packages_Agencies_AgencyId",
                    column: x => x.AgencyId,
                    principalTable: "Agencies",
                    principalColumn: "Id",
                    onDelete: ReferentialAction.Cascade);
                table.ForeignKey(
                    name: "FK_Packages_Agencies_AgencyId1",
                    column: x => x.AgencyId1,
                    principalTable: "Agencies",
                    principalColumn: "Id",
                    onDelete: ReferentialAction.Restrict);
            }​);

包装:

  public class Package : PackageModel
{​
    public int AgencyId {​ get; set; }​
    public virtual Agency Agency {​ get; set; }​
    ...

(也试过不使用 virtual 关键字)

机构配置

  internal class AgencyConfiguration : IEntityTypeConfiguration<Agency>
{​
    public void Configure(EntityTypeBuilder<Agency> builder)
    {​
        builder.HasKey(x => x.Id);
        builder.Property(x => x.Id)
            .IsRequired()
            .ValueGeneratedOnAdd();
        builder.Property(x => x.Name)
            .IsRequired()
            .HasMaxLength(250);
        builder.HasMany(x => x.Packages)
            .WithOne()
            .HasForeignKey(x => x.AgencyId)
            .IsRequired()
            .OnDelete(DeleteBehavior.Cascade);
    }​
}​

包配置

  internal class PackageConfiguration : IEntityTypeConfiguration<Package>
{​
    public void Configure(EntityTypeBuilder<Package> builder)
    {​
        builder.HasKey(x => x.Id);
        builder.Property(x => x.Id)
            .IsRequired()
            .ValueGeneratedOnAdd();
        builder.HasOne(x => x.Agency)
            .WithMany()
            .HasForeignKey(x => x.AgencyId)
            .IsRequired()
            .OnDelete(DeleteBehavior.Cascade);
    }​
}​

(也尝试在 Package 端不重复配置,仅在代理端 - 效果不佳)

没有重复的同名列,没有重复的配置文件或类似的东西。

正在 CoreDbContext 中应用配置:

  protected override void OnModelCreating(ModelBuilder modelBuilder)
    {​
        modelBuilder.ApplyConfiguration(new AgencyConfiguration());
        modelBuilder.ApplyConfiguration(new PackageConfiguration());

有什么想法吗? 谢谢

【问题讨论】:

  • PackageModel 中是否有添加其他属性的内容?
  • @Neil 不,只有 Name 和 Description 属性
  • 是否有另一个表引用了这个表?

标签: c# .net entity-framework entity-framework-core


【解决方案1】:

为什么 EF Core 不断向迁移文件添加影子属性?比如 AgencyId1、AgencyId2 等。

原因几乎总是关系配置错误。在你的情况下,这里

// Agency
builder.HasMany(x => x.Packages)
    .WithOne() // <-- where is navigation property?
    .HasForeignKey(x => x.AgencyId)
    .IsRequired()
    .OnDelete(DeleteBehavior.Cascade);

// Package
builder.HasOne(x => x.Agency)
    .WithMany() // <-- where is navigation property?
    .HasForeignKey(x => x.AgencyId)
    .IsRequired()
    .OnDelete(DeleteBehavior.Cascade);

首先,这个想法是一种关系,所以应该配置在一个地方。这是单独的实体配置类概念不能很好发挥作用的地方,因为关系涉及两个实体,因此在逻辑上不属于它们中的任何一个。

所以,至少选择其中一个并在那里配置它,但永远不要在两个地方。为什么?因为我省略了导航属性,您实际上是在告诉 EF Core 创建 两个 关系(导航属性仅在一侧),因此需要额外的 FK。

例如任一

// Agency
builder.HasMany(x => x.Packages) // collection navigation
    .WithOne(x => a.Agency) // reference navigation
    .HasForeignKey(x => x.AgencyId) // FK property
    .IsRequired() // not really needed, default for non nullable FKs
    .OnDelete(DeleteBehavior.Cascade); // not really needed, default for required relationships

// Package
builder.HasOne(x => x.Agency)
    .WithMany(x => x.Packages)
    .HasForeignKey(x => x.AgencyId)
    .IsRequired()
    .OnDelete(DeleteBehavior.Cascade);

从不两者兼而有之。

甚至更好,因为这一切都是由 EF Core 约定的,所以删除整个关系配置。

【讨论】:

  • 非常感谢伊万的详细解释,它有帮助!但是,如果我完全删除该关系,它会告诉 Introducing FOREIGN KEY constraint 'FK_Users_Organizations_OrganizationId' on table 'Users' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTI ON or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints. 我的实体中的问题是自身结构吗?
  • 该消息引用了不同的实体/表,除了这些是真实的实体而不是来自样本。该示例应该在没有配置的情况下工作,因为配置正在设置DeleteBehavior.Cascade,这已经按照惯例设置了。你得到的错误是当你真的需要关闭级联删除 off 因为模型中有多个级联路径。因此,请检查实际情况,并记住 - 任何导航属性都会引入常规关系,因此请仔细配对它们,并记住不可为空的 FK 会引入级联删除。
猜你喜欢
  • 2022-01-15
  • 2018-08-09
  • 1970-01-01
  • 2017-05-30
  • 2017-11-05
  • 2021-05-07
  • 1970-01-01
  • 2017-11-30
  • 2018-11-30
相关资源
最近更新 更多