EF Core HasOptional WithOptionalDependent

EF Core HasOptional WithOptionalDependent

我的数据库中有以下 table:

Product                                 ResourceAssociation
-------                                 ------------------
Name                          /-------> Id
ResourceAssociation_Id ------/         SomeProperty

因此 Product 有一个 ResourceAssociation_Id,它是 ResourceAssociation table 的 FK。

这是一个遗留应用程序,其 Entity Framework 6 地图包含这段代码:

HasOptional(t => t.ResourceAssociation).WithOptionalDependent().WillCascadeOnDelete(true);

我希望将其移植到 EF Core。 EF Core 似乎不再具有 HasOptional。我试过这个:

builder.HasOne(t => t.ResourceAssociation)
    .WithOne().HasForeignKey("ResourceAssociation_Id")
    .IsRequired(false)
    .OnDelete(DeleteBehavior.Cascade);

我也试过用 WithMany 替换 WithOne。但是没用。

当我尝试创建没有 ResourceAssociation 的新产品(因为它不是必需的)时,EF Core 仍然告诉我我的 ModelState 无效,因为 ResourceAssociation 为空。

我无法在 WithOne 中指定 属性(例如 WithOne(x => x.Product)),因为 ResourceAssociation 是一个 table,它也将用于其他 table(例如示例 Brand 也有一个 ResourceAssociation_Id 列指向 table).

这种设置甚至可以在 EF Core 中使用吗?或者我是否必须将不同的导航属性添加到我的 ResourceAssociation class(即产品、品牌...)?

在 EF Core 中,HasOne / WithOne(即使具有导航属性)不足以确定 one-to-one 关系中哪个是主要实体,哪个是依赖实体(对于 one-to-many,一个总是主要的,许多是依赖的,对于 many-to-many,没有 principal/dependent)。

因此,HasForeignKey / HasPrincipalKey 的泛型类型参数 需要 来确定分别是依赖/主要实体。这实际上在 Other Relationship Patterns - One-to-one EF Core 文档主题中进行了解释:

When configuring the relationship with the Fluent API, you use the HasOne and WithOne methods.

When configuring the foreign key you need to specify the dependent entity type - notice the generic parameter provided to HasForeignKey in the listing below. In a one-to-many relationship it is clear that the entity with the reference navigation is the dependent and the one with the collection is the principal. But this is not so in a one-to-one relationship - hence the need to explicitly define it.

所以你需要在这里指定 Product 作为关系的依赖,以及 FK 属性 / 列名:

builder.HasOne(t => t.ResourceAssociation)
    .WithOne() // ok, no navigation
    .HasForeignKey<Product>("ResourceAssociation_Id") // FK name in the dependent
    //               ^^^ the dependent entity of the relationship
    .IsRequired(false)
    .OnDelete(DeleteBehavior.Cascade);