Представление ограничения FOREIGN KEY может вызвать циклы или несколько каскадных путей – почему?

Я боролся с этим некоторое время и не могу понять, что происходит. У меня есть объект карты, который содержит стороны (обычно 2), и обе карты и стороны имеют этап. Я использую EF Codefirst миграции, и миграции не работают с этой ошибкой:

Представление ограничения FOREIGN KEY «FK_dbo.Sides_dbo.Cards_CardId» в таблице «Стороны» может вызывать циклы или несколько каскадных путей. Укажите ON DELETE NO ACTION или ON UPDATE NO ACTION или измените другие ограничения FOREIGN KEY.

Вот мой объект карты :

public class Card { public Card() { Sides = new Collection(); Stage = Stage.ONE; } [Key] [Required] public virtual int CardId { get; set; } [Required] public virtual Stage Stage { get; set; } [Required] [ForeignKey("CardId")] public virtual ICollection Sides { get; set; } } 

Вот моя сторона :

 public class Side { public Side() { Stage = Stage.ONE; } [Key] [Required] public virtual int SideId { get; set; } [Required] public virtual Stage Stage { get; set; } [Required] public int CardId { get; set; } [ForeignKey("CardId")] public virtual Card Card { get; set; } } 

И вот мой объект Stage :

 public class Stage { // Zero public static readonly Stage ONE = new Stage(new TimeSpan(0, 0, 0), "ONE"); // Ten seconds public static readonly Stage TWO = new Stage(new TimeSpan(0, 0, 10), "TWO"); public static IEnumerable Values { get { yield return ONE; yield return TWO; } } public int StageId { get; set; } private readonly TimeSpan span; public string Title { get; set; } Stage(TimeSpan span, string title) { this.span = span; this.Title = title; } public TimeSpan Span { get { return span; } } } 

Что странно, что если я добавлю следующее в мой class Stage:

  public int? SideId { get; set; } [ForeignKey("SideId")] public virtual Side Side { get; set; } 

Миграция выполняется успешно. Если я открою SSMS и посмотрю на таблицы, я вижу, что Stage_StageId добавлен в Cards (как ожидалось / желателен), однако Sides содержит ссылки на Stage (не ожидается).

Если я затем добавлю

  [Required] [ForeignKey("StageId")] public virtual Stage Stage { get; set; } public int StageId { get; set; } 

Для моего classа Side я вижу столбец StageId добавленный в мою таблицу Side .

Это работает, но теперь во всем моем приложении любая ссылка на Stage содержит SideId , которая в некоторых случаях совершенно неактуальна. Я хотел бы просто присвоить своим объектам Card и Side свойство Stage основанное на вышеуказанном classе Stage, без загрязнения среды с эталонными свойствами, если это возможно … что я делаю неправильно?

Поскольку требуется Stage , все отношения «один ко многим», в которых задействована Stage будут иметь каскадное удаление по умолчанию. Это означает, что если вы удалите объект Stage

  • удаление будет каскадом непосредственно в Side
  • удаление будет каскадом непосредственно на Card и потому что Card и Side имеют обязательные отношения «один ко многим» с каскадным удалением, включенным по умолчанию, снова будут каскадом от Card к Side

Таким образом, у вас есть два каскадных пути удаления из Stage в Side – что вызывает исключение.

Вы должны либо сделать Stage необязательным, по крайней мере, в одном из объектов (т. Е. Удалить атрибут [Required] из свойств Stage ) или отключить каскадное удаление с помощью Fluent API (невозможно с аннотациями данных):

 modelBuilder.Entity() .HasRequired(c => c.Stage) .WithMany() .WillCascadeOnDelete(false); modelBuilder.Entity() .HasRequired(s => s.Stage) .WithMany() .WillCascadeOnDelete(false); 

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

 [ForeignKey("StageId")] public virtual Stage Stage { get; set; } public int? StageId { get; set; } 

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

 builder.Conventions.Remove(); builder.Conventions.Remove(); 

Кто-нибудь задается вопросом, как это сделать в ядре EF:

  protected override void OnModelCreating(ModelBuilder modelBuilder) { foreach (var relationship in modelBuilder.Model.GetEntityTypes().SelectMany(e => e.GetForeignKeys())) { relationship.DeleteBehavior = DeleteBehavior.Restrict; } ..... rest of the code..... 

Вы можете установить cascadeDelete в false или true (в методе миграции Up ()). Зависит от вашего требования.

 AddForeignKey("dbo.Stories", "StatusId", "dbo.Status", "StatusID", cascadeDelete: false); 

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

В моем случае я не хотел удалять зависимую запись при удалении ключа. Если это имеет место в вашей ситуации, просто просто измените значение Boolean при переходе на false:

 AddForeignKey("dbo.Stories", "StatusId", "dbo.Status", "StatusID", cascadeDelete: false); 

Скорее всего, если вы создаете отношения, которые генерируют эту ошибку компилятора, но DO хотят сохранить каскадное удаление; у вас есть проблема с вашими отношениями.

Это звучит странно, и я не знаю почему, но в моем случае это происходило, потому что мой ConnectionString использовал «.». в атрибуте «источник данных». Как только я изменил его на «localhost», он работал как шарм. Никаких других изменений не требовалось.

В .NET Core я изменил параметр onDelete на ReferencialAction.NoAction

  constraints: table => { table.PrimaryKey("PK_Schedule", x => x.Id); table.ForeignKey( name: "FK_Schedule_Teams_HomeId", column: x => x.HomeId, principalTable: "Teams", principalColumn: "Id", onDelete: ReferentialAction.NoAction); table.ForeignKey( name: "FK_Schedule_Teams_VisitorId", column: x => x.VisitorId, principalTable: "Teams", principalColumn: "Id", onDelete: ReferentialAction.NoAction); }); 

Существующие ответы велики, я просто хотел добавить, что я столкнулся с этой ошибкой по другой причине. Я хотел создать начальную миграцию EF в существующей БД, но я не использовал флаг -IgnoreChanges и применил команду Update-Database в пустой базе данных (также при существующих сбоях).

Вместо этого мне пришлось запустить эту команду, когда текущая структура db является текущей:

 Add-Migration Initial -IgnoreChanges 

Вероятно, в структуре db существует реальная проблема, но сохранить мир за один шаг за раз …

Я исправил это. Когда вы добавляете миграцию, в методе Up () будет строка вроде этого:

.ForeignKey (“dbo.Members”, t => t.MemberId, cascadeDelete: True)

Если вы просто удалите cascadeDelete с конца, он будет работать.

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

Добавьте этот метод в class базы данных контекста:

 protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Conventions.Remove(); } 

В .NET Core я играл со всеми верхними ответами, но без каких-либо успехов. Я много изменил структуру БД и каждый раз добавлял новую миграцию, пытающуюся update-database , но получал ту же ошибку.

Затем я начал remove-migration один за другим, пока консоль диспетчера пакетов не исключила меня:

Миграция ‘20170827183131 _ ***’ уже применяется к базе данных

После этого я успешно добавил новую миграцию ( add-migration ) и update-database

Поэтому мое предложение было бы: очистить все ваши временные миграции до вашего текущего состояния БД.

Ни один из вышеупомянутых решений не работал для меня. То, что мне нужно было сделать, это использовать nullable int (int?) Для внешнего ключа, который не был необходим (или не был ключ нулевого столбца), а затем удалить некоторые из моих миграций.

Начните с удаления миграций, затем попробуйте ввести значение null.

Проблема заключалась как в модификации, так и в моделировании. Изменение кода не требовалось.

  • Entity Framework создает множественное имя таблицы, но представление ожидает уникальное имя таблицы?
  • Как установить значение по умолчанию для POCO в EF CF?
  • Тайм-ауты структуры организации
  • Результат запроса нельзя перечислить более одного раза
  • Не удалось выполнить проверку для одного или нескольких объектов. Дополнительную информацию см. В разделе «Свойство EntityValidationErrors».
  • Как отключить сущность из контекста в Entity Framework?
  • Entity Framework 4 Single () vs First () vs FirstOrDefault ()
  • Entity Framework 4 - AddObject vs Attach
  • Объект нельзя удалить, поскольку он не найден в ObjectStateManager
  • Entity Framework Code Только ошибка: модель, поддерживающая контекст, изменилась с момента создания базы данных
  • Что такое независимые ассоциации и ассоциации с иностранными ключами?
  • Давайте будем гением компьютера.