简体   繁体   English

EF Core 与级联删除的一对一可选关系 - 主体实体上的 FK

[英]EF Core One-to-One Optional Relation with Cascade Delete - FK on Principal Entity

I have two Entities and want to configure a 1:1 optional relationship that supports cascade one delete.我有两个实体,想配置一个支持级联一删除的 1:1 可选关系。 One Episode can have one optional Release , but a Release can never exist without an Episode .一个Episode可以有一个可选的Release ,但是没有一个Episode就不能存在一个Release So Episode should be the principal entity and Release the dependant entity, also whenever an Episode is deleted, the possible Release should also be deleted.因此, Episode应该是主要实体, Release应该是依赖实体,同样,每当删除一个Episode时,也应该删除可能的Release

But since i have a lot of business logic that depends on whether the Episode has a Release and what the possible details are, i need the FK to be on Episode rather than on Release an do a lot of checks like someEpisode.ReleaseId.HasValue .但是由于我有很多业务逻辑取决于Episode是否有Release以及可能的细节是什么,所以我需要 FK 位于Episode而不是Release上,并进行大量检查,例如someEpisode.ReleaseId.HasValue

public class Episode
{
    public Guid Id { get; set; }
    // a lot of episode infos...

    public Release? Release { get; set; }
    public Guid? ReleaseId { get; set; }
}
public class Release
{
    public Guid Id { get; set; }
    // a lot of release infos
}

But using this entity definitions, i could not find a way to configure EF Core to meet my expectations stated above.但是使用这个实体定义,我找不到配置 EF Core 以满足我上述期望的方法。 Episode is always considered als dependant entity. Episode总是被认为是依赖实体。 As a workaround i currently delete the Release manually whenever an Episode has to be deleted.作为一种解决方法,我目前在必须删除Episode时手动删除Release

Is it maybe impossible to place an FK on a principal entity, regardless of EF Core?无论EF Core如何,都可能无法在主体实体上放置FK吗?

Thanks!谢谢!

In 1:n associations it seems more intuitive to us that the independent entity, the parent, doesn't have a foreign key to its children.在 1:n 关联中,对我们来说似乎更直观的是,独立实体,即父级,对其子级没有外键。 We immediately sense that one foreign key for many children can't be right.我们立即感觉到许多孩子的一个外键不可能是正确的。 The children have a foreign key to the parent, obviously.显然,孩子们对父母有一个外键。

In 1:1 associations we somehow get lured into an object-oriented mindset more easily.在 1:1 的关联中,我们不知何故更容易被引诱到面向对象的思维模式中。 It seems natural that if an independent (principal) entity owns a dependent entity, the former should "own" the foreign key.如果一个独立(主)实体拥有一个从属实体,那么前者应该“拥有”外键似乎很自然。 However, just as in 1:n, the dependent entity is the child and, hence, has a foreign key (see object–relational impedance mismatch ).然而,就像在 1:n 中一样,依赖实体是子实体,因此有一个外键(参见对象-关系阻抗不匹配)。

With this in mind, it's clear how the model and the mappings should be coded.考虑到这一点,应该如何对模型和映射进行编码就很清楚了。 For example (because there are options):例如(因为有选项):

class Episode
{
    public Guid Id { get; set; }
    public Release? Release { get; set; }
}

class Release
{
    public Guid Id { get; set; }
    public Episode Episode { get; set; }
}

And the mapping:和映射:

modelBuilder.Entity<Release>()
    .HasOne(r => r.Episode)
    .WithOne(e => e.Release)
    .HasForeignKey<Release>();

The line HasForeignKey<Release>() turns Release into the dependent entity. HasForeignKey<Release>() Release转换为依赖实体。 By default, EF creates a shared primary key association in which Release 's primary key is also the foreign key:默认情况下,EF 创建一个共享主键关联,其中Release的主键也是外键:

CONSTRAINT [FK_Release_Episode_Id] FOREIGN KEY ([Id]) REFERENCES [Episode] 
    ([Id]) ON DELETE CASCADE

You can also have a separate foreign key:您还可以有一个单独的外键:

modelBuilder.Entity<Release>()
    .HasOne(r => r.Episode)
    .WithOne(e => e.Release)
    .HasForeignKey<Release>("EpisodeID");

...which creates a Release.EpisodeID foreign key field in the database and a shadow property in the class model. ...在数据库中创建一个Release.EpisodeID外键字段并在类模型中创建一个影子属性

Another option is to create a foreign key relationship (reference and foreign key property in the class model):另一种选择是创建外键关系(类模型中的引用和外键属性):

class Release
{
    public Guid Id { get; set; }
    public Guid EpisodeId { get; set; }
    public Episode Episode { get; set; }
}

...which EF understands by convention, ie without explicit mapping, but could be mapped explicitly as: ... EF 按惯例理解,即没有显式映射,但可以显式映射为:

modelBuilder.Entity<Release>()
    .HasOne(r => r.Episode)
    .WithOne(e => e.Release)
    .HasForeignKey<Release>(r => r.EpisodeId);

Finally, it's not necessary to have both reference properties in both classes.最后,没有必要在两个类中都有两个引用属性。 Either Episode.Release or Release.Episode can be omitted. Episode.ReleaseRelease.Episode都可以省略。 In the latter case, mappings should have modelBuilder.Entity<Release>() as starting point.在后一种情况下,映射应该以modelBuilder.Entity<Release>()作为起点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM