Как настроить каскадное удаление, где есть циклы и несколько каскадных путей - PullRequest
0 голосов
/ 12 июля 2019

У меня возникли некоторые проблемы с тем, как разобраться в этих отношениях и как, возможно, установить для них настройки каскадного удаления.

  • Существует таблица сотрудников, где у каждого сотрудника есть любое количество ручек, вложений и заданий
  • Существует таблица ручек, где каждая ручка принадлежит сотруднику и может использоваться в инструменте
  • Существует таблица вложений, где каждое вложение принадлежит сотруднику и может использоваться в инструменте
  • Существует таблица инструментов, где каждый инструмент состоит из одного вложения, одной ручки и используется для любого количества заданий
  • Существует таблица рабочих мест, где каждая работа принадлежит работнику, и может иметь или не иметь инструмент, используемый на нем

Примечание: ручки и вложения могут существовать без использования инструмента

Короче говоря: сотрудник может смешивать и сочетать ручки и вложения для создания инструментов, а затем использовать инструмент в назначенном ему задании.

На этой диаграмме показано, как база данных соединена вместе (, не стесняйтесь, предложите лучший дизайн )

Диаграмма БД

Так настроены модели. Модель задания имеет нулевую ссылку на инструменты FK (ToolId), поэтому задание может существовать без инструмента.

public class Employee
{
    public int EmployeeId { get; set; }
    public string Name { get; set; }

    public List<Handle> Handles { get; set; }
    public List<Attachment> Attachments { get; set; }
    public List<Job> Jobs { get; set; }
}
public class Handle
{
    public int HandleId { get; set; }
    public string Material { get; set; }
    public double ExpectedLife { get; set; }
    public double LifetimeMaintenance { get; set; }

    public int EmployeeId { get; set; }
    public Employee Employee { get; set; }
    public List<Tool> Tools { get; set; }
}
public class Attachment
{
    public int AttachmentId { get; set; }
    public string Material { get; set; }
    public string Type { get; set; }
    public double ExpectedLife { get; set; }
    public double LifetimeMaintenance { get; set; }

    public int EmployeeId { get; set; }
    public Employee Employee { get; set; }
    public List<Tool> Tools { get; set; }
}
public class Tool
{
    public int ToolId { get; set; }
    public string OperationSpeed { get; set; }


    public int HandleId { get; set; }
    public Handle Handle { get; set; }

    public int AttachmentId { get; set; }
    public Attachment Attachment { get; set; }

    public List<Job> Jobs { get; set; }
}
public class Job
{
    public int JobId { get; set; }
    public string Name { get; set; }
    public double EffortRequired { get; set; }

    public int EmployeeID { get; set; }
    public Employee Employee { get; set; }
    public int? ToolId { get; set; }
    public Tool Tool { get; set; }
}

Вот как был создан контекст БД. Существует параметр каскадного удаления, позволяющий установить для инструмента FK в Jobs (ToolId) значение NULL при удалении инструмента (поэтому задание не будет удалено при удалении его инструмента).

public class ToolsDbContext : DbContext
{
    public ToolsDbContext(DbContextOptions<ToolsDbContext> options) : base(options)
    {

    }

    public DbSet<Employee> employees { get; set; }
    public DbSet<Handle> handles { get; set; }
    public DbSet<Attachment> attachments { get; set; }
    public DbSet<Tool> tools { get; set; }
    public DbSet<Job> jobs { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Tool>()
            .HasMany(j => j.Jobs)
            .WithOne(t => t.Tool)
            .OnDelete(DeleteBehavior.SetNull);
    }
}

Создание миграции работает, но затем обновление базы данных завершается неудачно со следующей ошибкой:

Introducing FOREIGN KEY constraint 'FK_tools_handles_HandleId' on table 'tools' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
Could not create constraint or index. See previous errors.

Я не совсем уверен, как понять эту ошибку.

Обдумав это:

  • Если дескриптор удален, он удалит все инструменты, в которых он используется, что, в свою очередь, установит для ToolId в связанных заданиях значение null
  • Если вложение будет удалено, оно удалит все инструменты, в которых оно используется, что, в свою очередь, установит для ToolId в связанных заданиях значение null
  • Если инструмент удален, он установит ToolId в связанных заданиях на null
  • Если задание удалено, каскадный эффект не будет

Поэтому я думаю, что проблема должна быть в удалении сотрудника, но я не понимаю, почему (пока?) ...

  • Если сотрудник удален, все должно быть удалено; он должен удалить все связанные задания, дескрипторы и вложения. Затем эти удаленные дескрипторы или вложения должны, в свою очередь, удалить связанные с ними инструменты (не важно, что было первым).

Так что есть каскадные пути удаления сотрудника, но я ожидаю, что все это будет работать на основе настройки модели как есть ... Так что мне нужно настроить больше требований каскадного удаления в dbcontext? Если так, я не уверен, как это должно быть настроено ...

Примечание: без модели сотрудников в базе данных все вроде бы работает

Ответы [ 2 ]

1 голос
/ 12 июля 2019

SQL-сервер не позволяет иметь несколько каскадных путей к одной и той же таблице в базе данных.В вашем случае есть два из них для инструментов:

  • Сотрудник -> Ручка -> Инструмент
  • Сотрудник -> Вложение -> Инструмент

Всеспособы решения этой проблемы заключаются в установке DeleteBehavior.Restrict для одного или другого отношения, например:

  • Установка DeleteBehavior.Restrict для Entity -> Обработка отношения и обработка этого каскадного пути с помощью триггера (в противном случае«restrict» не позволит удалить запись, имеющую ссылки на нее)
  • Установка DeleteBehavior.Restrict для Entity -> Обработка отношений и обработка этого каскадного пути в коде приложения (перед удалением явно / обновите / удалите все связанные объекты)основной)
  • Установка «ограничить» поведение для обоих отношений сущностей

и т.д ...

0 голосов
/ 12 июля 2019

Вы сказали:

Существует таблица сотрудников, где у каждого сотрудника есть любое количество ручек, вложений и заданий

Новаша диаграмма устанавливает прямую связь между работником и дескриптором, у одного дескриптора много сотрудников, а у сотрудника есть только один дескриптор

Ваше утверждение противоречит вашей диаграмме

Я думаю, что это моделирование неверно с точки зрения базы данных.Я думаю, что работа должна иметь сотрудника.(Если в задании несколько сотрудников, вам понадобится еще одна таблица jobemployees, которая сопоставляет один идентификатор задания нескольким сотрудникам.) В задании есть инструмент, у инструмента есть дескриптор и вложение.Я не понимаю, почему удаление сотрудника должно удалить его работу (если я уволил кого-то, дом, который он построил, работая на меня, все еще существует), но вы можете очистить это без использования каскадных ограничений

В конечном итоге вы можете увидеть вНарисуйте цикл, который вы создали.Если удаление чего-либо с 1-го конца удаляет все с *-конца, то удаление чего-либо на диаграмме запускает цепочку, которая принимает разделенный путь, который возвращается вместе.Удаление сущности сотрудника действительно разрушает это

В конечном счете, у сотрудника не должно быть непосредственно работы, ручки или приложения

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...