Подтвердить что ты не робот

Entity Framework Code First: ограничение FOREIGN KEY может вызвать циклы или несколько каскадных путей

Entity Framework Code Сначала можно создать БД для следующих POCO.

public class Item {
    public int Id { get; set; }
    public string Name { get; set; }
}

public class ItemPair {
    public int Id { get; set; }

    public virtual Item FirstItem { get; set; }
    public virtual Item SecondItem { get; set; }
}

Я хотел бы установить связь с первым и вторым элементами через поля ИД, а не весь класс "Предмет". Итак:

public class ItemPair {
    public int Id { get; set; }

    public virtual Item FirstItem { get; set; }
    public int FirstItem_Id { get; set; }

    public virtual Item SecondItem { get; set; }
    public int SecondItem_Id { get; set; }
}

также работает. Изменить. На самом деле это не работает. Просто генерирует дополнительные столбцы FirstItem_Id1 и SecontItem_Id2.

Но просто изменив свойства внешнего ключа на FirstItemId, SecondItemId (без подчеркивания):

public class ItemPair {
    public int Id { get; set; }

    public virtual Item FirstItem { get; set; }
    public int FirstItemId { get; set; }

    public virtual Item SecondItem { get; set; }
    public int SecondItemId { get; set; }
}

приводит к следующему исключению.

{"Introducing FOREIGN KEY constraint 'ItemPair_SecondItem' on table 'ItemPair' may cause
cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION,
or modify other FOREIGN KEY constraints.\r\nCould not create constraint. 
See previous errors."}

Почему? И что я могу сделать, чтобы избежать этого исключения.

4b9b3361

Ответ 1

Я ожидаю, что в первом случае ваши свойства Id не будут использоваться в базе данных, так как FKs и EF создадут еще два столбца (вы можете проверить это, заставив спаривание свойства навигации с помощью свойства FK с помощью ForeignKeyAttribute). Во втором случае EF будет правильно распознавать ваши свойства, но также будет использовать соглашение об исключении каскада, которое вызовет ошибку на SQL-сервере. У вас есть два свойства из таблицы, указывающие на одного и того же родителя. Фактически в базе данных вы можете создать ItemPair из того же Item (оба FK установлены на один и тот же идентификатор). Если оба отношения имеют включенное каскадное удаление, это приведет к нескольким каскадным путям = > не разрешено на SQL-сервере.

Решение здесь - это плавное отображение, чтобы вручную определить, как отношения сопоставляются. Здесь приведен пример.

Ответ 2

Я решил просто удалить соглашение об исключении каскада.

 protected override void OnModelCreating(DbModelBuilder modelBuilder) {
        base.OnModelCreating(modelBuilder);

        modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
        modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();

    }

Причины:

  • Я предпочитаю отмечать удаленные или деактивированные записи для целей аудита.
  • В большинстве случаев я удаляю только таблицы соединения/отображения.
  • С ORM. В редком случае, в котором я нуждаюсь, достаточно тривиально перебирать и удалять дочерние записи.

Спасибо, Ладислав Мрнка, указывая мне в правильном направлении.