当我创建新的迁移时,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; }
}
为什么会发生这种情况?我该如何避免?
1条答案
按热度按时间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
请注意术语 property 和 entity(类),因为它们与单独配置的列名和表名不同。
正如你所看到的,使用你的最新命名,
ProductId
不匹配上述任何模式。你没有导航属性,所以前两个不适用,最后两个解析为ProductDataId
。因此,EF Core将你的ProductId
属性视为常规属性/列,并使用shadow属性创建必要的FK属性/列ProductDataId
。我试图在表属性中定义的ForeignKey属性中输入确切的名称,但没有帮助...
ForeignKey
是一个令人困惑的属性,我建议避免,因为它根据应用的位置有不同的含义。例如,当应用于引用导航属性时,它指定FK property name。当应用于FK property 时,它指定引用导航 property name。当应用于集合导航属性时,它指定引用导航 property name。没有人知道它指定了什么。但在所有情况下,关键字都是 property name(而不是列、实体或表名)。对我来说,唯一可靠的方法是流畅的API配置,在这里您使用C#编译时支持来配置关系的所有方面。
顺便说一句,
ProductData.CategoryId
也有同样的问题,所以最好为它添加类似的配置(以及任何类似的配置)。如果它们符合EFC命名约定,这不会有什么坏处,但如果你以后像这样重命名类,这将有所帮助。