Как использовать CASCADE DELETE для удаления всех данных клиента - PullRequest
0 голосов
/ 14 июля 2020

Я хочу удалить все объекты, связанные с арендатором, из многопользовательской базы данных при удалении одного арендатора. Я работаю с EF Core и Microsoft SQL Server, хотя я предполагаю, что этот topi c не ограничивается этими технологиями.

В этом ответе сказано, что:

это классический случай использования FOREIGN KEYS с опцией ON CASCADE

Однако мне не удалось заставить его работать. Кажется, что, поскольку объекты арендованные также связаны между собой, будут созданы циклы. Я создал простое приложение, чтобы протестировать это изолированно, вы можете найти его здесь . При попытке обновить базу данных в соответствии с миграцией я получаю следующую ошибку:

Необработанное исключение. Microsoft.Data.SqlClient.SqlException (0x80131904): введение ограничения FOREIGN KEY «FK_Posts_Tenants_TenantId» в таблице «Сообщения» может вызвать циклы или несколько каскадных путей. Укажите ON DELETE NO ACTION или ON UPDATE NO ACTION или измените другие ограничения FOREIGN KEY.

My 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; }
}

Итак, мой вопрос: is это возможно? и если это так, что мне следует изменить в моей конфигурации? Я прочитал , что создание FK между сущностями обнуляемыми может решить проблему, но я не хочу вносить это изменение только для заставить эту работу. Я также видел этот ответ для замены CASCADE DELETE триггером, но мне этот вариант не нравится.

1 Ответ

1 голос
/ 14 июля 2020

У вас есть «несколько каскадных путей» для Post:

Tenant => Blog => Post
Tenant => Post

Post.TenantId избыточно, поскольку сообщение содержится в c Blog, определяемом клиентом.

Существуют различные возможности:

  • удалить Post.TenantId
  • удалить ссылку между Tenant и Post (заменить на Blog и Post)
  • добавить правильный OnDelete() поведение ( документы MS )
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...