Как обрабатывать каскадное удаление в отношениях «многие ко многим» в Entity Framework - PullRequest
0 голосов
/ 28 ноября 2018

У меня есть три объекта: Boss, Employee и Instruction.У боссов есть набор инструкций, которые они могут выдавать (отношения один-ко-многим), а у боссов есть набор сотрудников (отношения один-ко-многим), которым они могут давать эти инструкции.Инструкция может быть дана более чем одному Сотруднику, поэтому между Сотрудниками и Инструкцией существует отношение многие ко многим.Итак, вот мои сущности:

public class Boss
{
    public int ID { get; set; }
    public string Name { get; set; }
    public ICollection<Instruction> Instructions { get; set; }
    public ICollection<Employee> Employees { get; set; }
}
public class Employee
{
    public int ID { get; set; }
    public int BossID { get; set; }
    public string Name { get; set; }
    public DateTime WorkTime { get; set; }
    public ICollection<Instruction> Instructions { get; set; }
}
public class Instruction
{
    public int ID { get; set; }
    public string Name { get; set; }
    public int BossID { get; set;}
    public ICollection<Employee> Employees { get; set; }
}

Цель состоит в том, чтобы написать запросы для получения списков сотрудников босса, а также посмотреть, какие сотрудники назначены для каждой инструкции.Дополнительная причина для его моделирования таким образом заключается в том, что мы можем применять ограничения уникальности, чтобы, например, у нас не было одного и того же сотрудника, введенного несколько раз, и, возможно, мы не хотим, чтобы босс планировал работать с несколькими сотрудниками.в то же время.Итак, вот DbContext с этими отношениями, отображаемыми с помощью Fluent API:

public class Model1 : DbContext
{
    public Model1() : base("name=Model1") { }
    public virtual DbSet<Boss> Bosses { get; set; }
    public virtual DbSet<Instruction> Instructions { get; set; }
    public virtual DbSet<Employee> Employees { get; set; }
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();
        modelBuilder.Entity<Employee>().HasMany<Instruction>(x => x.Instructions).WithMany(x => x.Employees);
        modelBuilder.Entity<Boss>().HasMany<Instruction>(x => x.Instructions);
        modelBuilder.Entity<Boss>().HasMany<Employee>(x =>x.Employees);

        modelBuilder.Entity<Employee>().Property(x => x.BossID)
            .HasColumnAnnotation(IndexAnnotation.AnnotationName,
            new IndexAnnotation(new IndexAttribute("OneEmployeeAtATime", 0) { IsUnique = true }));

        modelBuilder.Entity<Employee>().Property(x => x.WorkTime)
            .HasColumnAnnotation(IndexAnnotation.AnnotationName,
            new IndexAnnotation(new IndexAttribute("OneEmployeeAtATime", 1) { IsUnique = true }));

        base.OnModelCreating(modelBuilder);
    }
}

Строка modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>(); находится там, потому что в противном случае я получаю ошибку «несколько каскадных путей».Я хочу, чтобы при удалении Boss он также удалял его Employees и Instructions, но если я удаляю либо Instruction, либо Employee, он не должен каскадироваться.Но когда я запускаю свой тест:

using (Model1 db = new Model1())
{
    Boss boss = db.Bosses.First();
    db.Bosses.Remove(boss);
    db.SaveChanges();
}

, я получаю это сообщение об ошибке:

System.Data.Entity.Infrastructure.DbUpdateException: при обновлении записей произошла ошибка.Смотрите внутреннее исключение для деталей.---> System.Data.Entity.Core.UpdateException: при обновлении записей произошла ошибка.Смотрите внутреннее исключение для деталей.---> System.Data.SqlClient.SqlException: инструкция DELETE вступила в конфликт с ограничением REFERENCE "FK_dbo.EmployeeInstructions_dbo.Employees_Employee_ID".Конфликт произошел в базе данных «Model1», таблице «dbo.EmployeeInstructions», столбце «Employee_ID».Утверждение было прекращено.

Я что-то упустил в Fluent API?

...