.net 实体框架试图创建不必要的列

0md85ypi  于 2023-04-08  发布在  .NET
关注(0)|答案(1)|浏览(96)

当我创建新的迁移时,EF试图创建不必要的列ProductDataId
我的模型看起来像这样:

public abstract class ObjectBaseData
{
    [Key]
    public int Id { get; set; }
    // ...
}

[Table("Products")]
public class ProductData : ObjectBaseData
{
     public List<CategoryProductData> CategoriesIds { get; set; } = new List<CategoryProductData>();
    // ...
}

[Table("Categories")]
public class CategoryData : ObjectBaseData
{
}

[Table("CategoryProduct")]
public class CategoryProductData
{
    [Key]
    public int Id { get; set; }

    [ForeignKey(nameof(CategoryData))]
    public int CategoryId { get; set; }

    [ForeignKey(nameof(ProductData))]
    public int ProductId { get; set; }
}

public class DataContext : DbContext
{
    public DbSet<ProductData> Products { get; set; }
    public DbSet<CategoryData> Categories { get; set; }

    public DataContext(DbContextOptions<DataContext> options) : base(options)
    {
    }
}

当我创建新的迁移时,我在迁移脚本中得到以下内容:

public partial class MyMigration : Migration
{
    /// <inheritdoc />
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.AddColumn<int>(
            name: "ProductDataId",
            table: "CategoryProduct",
            type: "int",
            nullable: true);

        migrationBuilder.CreateIndex(
            name: "IX_CategoryProduct_ProductDataId",
            table: "CategoryProduct",
            column: "ProductDataId");

        migrationBuilder.AddForeignKey(
            name: "FK_CategoryProduct_Products_ProductDataId",
            table: "CategoryProduct",
            column: "ProductDataId",
            principalTable: "Products",
            principalColumn: "Id");

        // ...
    }

    protected override void Down(MigrationBuilder migrationBuilder)
    {
        // ...
    }
}

这个荒谬的专栏是在我重命名一些类时开始创建的(没有改变,只是重命名了)。
我试图在ForeignKey属性中输入我在Table属性中定义的确切名称,但它没有帮助...

[Table("CategoryProduct")]
public class CategoryProductData
{
    [Key]
    public int Id { get; set; }

    [ForeignKey(nameof(CategoryData))]    ---> [ForeignKey("Categories")]
    public int CategoryId { get; set; }

    [ForeignKey(nameof(ProductData))]     ---> [ForeignKey("Products")]
    public int ProductId { get; set; }
}

为什么会发生这种情况?我该如何避免?

j2cgzkjk

j2cgzkjk1#

这个无意义的列是在我重命名一些类时开始创建的(没有什么变化,只是重命名了)
这足以打破EFC命名约定,对于外键属性,EFC命名约定是

  • <navigation property name><principal key property name>
  • <navigation property name>Id
  • <principal entity type name><principal key property name>
  • <principal entity type name>Id

请注意术语 propertyentity(类),因为它们与单独配置的列名和表名不同。
正如你所看到的,使用你的最新命名,ProductId不匹配上述任何模式。你没有导航属性,所以前两个不适用,最后两个解析为ProductDataId。因此,EF Core将你的ProductId属性视为常规属性/列,并使用shadow属性创建必要的FK属性/列ProductDataId
我试图在表属性中定义的ForeignKey属性中输入确切的名称,但没有帮助...
ForeignKey是一个令人困惑的属性,我建议避免,因为它根据应用的位置有不同的含义。例如,当应用于引用导航属性时,它指定FK property name。当应用于FK property 时,它指定引用导航 property name。当应用于集合导航属性时,它指定引用导航 property name。没有人知道它指定了什么。但在所有情况下,关键字都是 property name(而不是列、实体或表名)。
对我来说,唯一可靠的方法是流畅的API配置,在这里您使用C#编译时支持来配置关系的所有方面。

modelBuilder.Entity<ProductData>()
    .HasMany(e => e.CategoriesIds) // collection nav property
    .WithOne() // no reference nav property
    .HasForeignKey(e => e.ProductId);

顺便说一句,ProductData.CategoryId也有同样的问题,所以最好为它添加类似的配置(以及任何类似的配置)。如果它们符合EFC命名约定,这不会有什么坏处,但如果你以后像这样重命名类,这将有所帮助。

相关问题