如何使用 CASCADE DELETE 删除所有租户数据

How to use CASCADE DELETE for removing all tenant data

我想在删除一个租户时从多租户数据库中删除与该租户相关的所有实体。我正在使用 EF Core 和 Microsoft SQL 服务器,但我想这个主题不限于这些技术。

this answer中表示:

this is the classical case for use of FOREIGN KEYS with ON CASCADE option

但是,我没能成功。似乎由于 tenantized 实体也在它们之间链接,因此将创建循环。我创建了一个简单的应用程序来单独测试它,你可以找到它 here。尝试根据迁移更新数据库时,出现以下错误:

Unhandled exception. Microsoft.Data.SqlClient.SqlException (0x80131904): Introducing FOREIGN KEY constraint 'FK_Posts_Tenants_TenantId' on table 'Posts' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.

我的 DbContext 和实体:

public class BloggingContext : DbContext
{
    public DbSet<Tenant> Tenants { get; set; }
    public DbSet<Blog> Blogs { get; set; }
    public DbSet<Post> Posts { get; set; }
    protected override void OnConfiguring(DbContextOptionsBuilder options) => options.UseSqlServer("Server=.;Database=TestCascadeDelete;Trusted_Connection=True");
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Blog>(b => b.HasOne<Tenant>().WithMany().HasForeignKey(e => e.TenantId));
        modelBuilder.Entity<Post>(b => b.HasOne<Tenant>().WithMany().HasForeignKey(e => e.TenantId));
    }
}
public class Tenant
{
    public int TenantId { get; set; }
}
public class Blog
{
    public int TenantId { get; set; }
    public int BlogId { get; set; }
    public List<Post> Posts { get; } = new List<Post>();
}
public class Post
{
    public int TenantId { get; set; }
    public int PostId { get; set; }
    public int BlogId { get; set; }
    public Blog Blog { get; set; }
}

所以我的问题是:这可能吗?如果是,我应该在我的配置中更改什么?我已经read that making the FK’s between entities nullable could solve the problem, but I don’t want to make that change just to make this work. I've also seen this answer用触发器替换 CASCADE DELETE,但我不喜欢这个选项。

您有 Post 的“多个级联路径”:

Tenant => Blog => Post
Tenant => Post

Post.TenantId 是多余的,因为 Post 包含在特定于租户的 Blog.

有多种可能性:

  • 移除Post.TenantId
  • 删除 Tenant 和 Post 之间的引用(替换为 Blog 和 Post)
  • 添加正确的 OnDelete() 行为 (MS docs)