[英]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.Release
或Release.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.