如何使用 Fluent API 正确控制 EF Core 中的级联删除?
How to properly control cascading deletion in EF Core using Fluent API?
我有两个实体,Tag 和 Member。一个成员可以标记多个标签。一个标签可以用来标记多个成员。这是一个明显的多对多关系案例,因为我使用的是 EF Core,所以我必须声明一个显式连接器,我称之为 Tag_Member。我是这样配置的
private void OnModelCreating(EntityTypeBuilder<Tag_Member> entity)
{
entity.HasKey(e => new { e.TagId, e.MemberId });
entity.HasOne(e => e.Tag);
entity.HasOne(e => e.Member)
.WithMany(e => e.Tag_Member)
.HasForeignKey(e => e.MemberId);
}
删除时我希望强制执行的行为如下。
- 删除 Tag_Member 的实例时,没有任何变化。
- 删除 Tag 的实例时,Tag_Member 的任何连接实例都会被删除。
- 删除 Member 的实例时,Tag_Member 的任何连接实例都会被删除。
我对两点感到困惑。当我添加如下所示的删除条件时,我有很多选项可供选择,尽管阅读了 intellisense,但我不确定要使用哪个来强制执行上述行为。
entity.HasOne(e => e.Member)
.WithMany(e => e.Tag_Member)
.HasForeignKey(e => e.MemberId)
.OnDelete(DeleteBehavior.NoAction);
我应该使用 NoAction、ClientNoAction、Restrict 还是其他?我什至不清楚删除行为影响了哪些实体。是哪个?
第二个困惑点是我没有为标签配置显示 OnDelete()。我没有使用 WithMany() 因为该实体缺少对互连实体的引用。我仍然可以管理它的删除行为吗?我是否需要显式声明它才能实现请求的行为?
entity.HasOne(e => e.Tag)
.OnDelete(DeleteBehavior.NoAction);
类大致是这样的。
public class Tag { public Guid Id { get; set; } }
public class Member { public Guid Id { get; set; } }
public class Tag_Member
{
public Guid TagId { get; set; }
public Guid MemberId { get; set; }
public Tag Tag { get; set; }
public Member Member { get; set; }
}
编辑:根据回答中的建议,成员与标签关系的最终版本。
private static void OnModelCreating(EntityTypeBuilder<Member> entity)
{
entity.HasKey(e => e.Id); ...
}
private static void OnModelCreating(EntityTypeBuilder<Tag> entity)
{
entity.HasKey(e => e.Id); ...
}
private static void OnModelCreating(EntityTypeBuilder<Member_Tag> entity)
{
entity.HasKey(e => new { e.MemberId, e.TagId });
entity.HasOne(e => e.Member).WithMany().OnDelete(DeleteBehavior.NoAction);
entity.HasOne(e => e.Tag).WithMany().OnDelete(DeleteBehavior.NoAction);
}
I'm not even clear on which of hte entities that the deletetion behavior affects. Which is it?
这很简单。级联删除总是影响 dependent 实体(即包含 FK 的实体)。
I don't feel certain which to use to enforce the above behavior. Should I use NoAction
, ClientNoAction
, Restrict
or someting else?
您似乎在使用 EF Core 3.0 预览版,它添加了更多尚未记录的选项。但是在数据库级别实现的 classic 级联删除的选项一直是 Cascade
.
I haven't used WithMany()
because that entity lacks references back to the interlinking entity.
为了能够流畅地配置关系方面,您必须使用 Has
+ With
对来完全指定关系方。由于 导航属性 对于关系的任何一方都不是强制性的,因此您只需要它来将正确的参数传递给 Has
/ With
方法 - 如果您有导航 属性,传递名称或 lambda 表达式访问器,否则不传递任何内容(但仍包括调用)。例如
entity.HasOne(e => e.Tag)
.WithMany() // <--
.OnDelete(DeleteBehavior.Cascade); // now you can do this
但请注意,对于 必需的 关系,DeleteBehavior.Cascade
是 默认 (换句话说,当 FK 不可为空时类型),因此您通常不需要为此进行流畅的配置。如果 属性 名称遵循 EF Core 命名约定,则根本不需要流畅的配置。
简单例子可见here.
我有两个实体,Tag 和 Member。一个成员可以标记多个标签。一个标签可以用来标记多个成员。这是一个明显的多对多关系案例,因为我使用的是 EF Core,所以我必须声明一个显式连接器,我称之为 Tag_Member。我是这样配置的
private void OnModelCreating(EntityTypeBuilder<Tag_Member> entity)
{
entity.HasKey(e => new { e.TagId, e.MemberId });
entity.HasOne(e => e.Tag);
entity.HasOne(e => e.Member)
.WithMany(e => e.Tag_Member)
.HasForeignKey(e => e.MemberId);
}
删除时我希望强制执行的行为如下。
- 删除 Tag_Member 的实例时,没有任何变化。
- 删除 Tag 的实例时,Tag_Member 的任何连接实例都会被删除。
- 删除 Member 的实例时,Tag_Member 的任何连接实例都会被删除。
我对两点感到困惑。当我添加如下所示的删除条件时,我有很多选项可供选择,尽管阅读了 intellisense,但我不确定要使用哪个来强制执行上述行为。
entity.HasOne(e => e.Member)
.WithMany(e => e.Tag_Member)
.HasForeignKey(e => e.MemberId)
.OnDelete(DeleteBehavior.NoAction);
我应该使用 NoAction、ClientNoAction、Restrict 还是其他?我什至不清楚删除行为影响了哪些实体。是哪个?
第二个困惑点是我没有为标签配置显示 OnDelete()。我没有使用 WithMany() 因为该实体缺少对互连实体的引用。我仍然可以管理它的删除行为吗?我是否需要显式声明它才能实现请求的行为?
entity.HasOne(e => e.Tag)
.OnDelete(DeleteBehavior.NoAction);
类大致是这样的。
public class Tag { public Guid Id { get; set; } }
public class Member { public Guid Id { get; set; } }
public class Tag_Member
{
public Guid TagId { get; set; }
public Guid MemberId { get; set; }
public Tag Tag { get; set; }
public Member Member { get; set; }
}
编辑:根据回答中的建议,成员与标签关系的最终版本。
private static void OnModelCreating(EntityTypeBuilder<Member> entity)
{
entity.HasKey(e => e.Id); ...
}
private static void OnModelCreating(EntityTypeBuilder<Tag> entity)
{
entity.HasKey(e => e.Id); ...
}
private static void OnModelCreating(EntityTypeBuilder<Member_Tag> entity)
{
entity.HasKey(e => new { e.MemberId, e.TagId });
entity.HasOne(e => e.Member).WithMany().OnDelete(DeleteBehavior.NoAction);
entity.HasOne(e => e.Tag).WithMany().OnDelete(DeleteBehavior.NoAction);
}
I'm not even clear on which of hte entities that the deletetion behavior affects. Which is it?
这很简单。级联删除总是影响 dependent 实体(即包含 FK 的实体)。
I don't feel certain which to use to enforce the above behavior. Should I use
NoAction
,ClientNoAction
,Restrict
or someting else?
您似乎在使用 EF Core 3.0 预览版,它添加了更多尚未记录的选项。但是在数据库级别实现的 classic 级联删除的选项一直是 Cascade
.
I haven't used
WithMany()
because that entity lacks references back to the interlinking entity.
为了能够流畅地配置关系方面,您必须使用 Has
+ With
对来完全指定关系方。由于 导航属性 对于关系的任何一方都不是强制性的,因此您只需要它来将正确的参数传递给 Has
/ With
方法 - 如果您有导航 属性,传递名称或 lambda 表达式访问器,否则不传递任何内容(但仍包括调用)。例如
entity.HasOne(e => e.Tag)
.WithMany() // <--
.OnDelete(DeleteBehavior.Cascade); // now you can do this
但请注意,对于 必需的 关系,DeleteBehavior.Cascade
是 默认 (换句话说,当 FK 不可为空时类型),因此您通常不需要为此进行流畅的配置。如果 属性 名称遵循 EF Core 命名约定,则根本不需要流畅的配置。
简单例子可见here.