У меня проблема, когда я пытаюсь добавить ограничения в свои таблицы. Я получаю ошибку:
Введение ограничения FOREIGN KEY «FK74988DB24B3C886» в таблицу «Сотрудник» может привести к возникновению циклов или нескольких каскадных путей. Укажите ON DELETE NO ACTION или ON UPDATE NO ACTION или измените другие ограничения FOREIGN KEY.
Мое ограничение между Code
таблицей и employee
таблицей. Code
Таблица содержит Id
, Name
, FriendlyName
, Type
и Value
. employee
Имеет ряд полей, ссылочные коды, так что может быть ссылка для каждого типа кода.
Мне нужно, чтобы поля были установлены в нуль, если код, на который ссылается, удален.
Есть идеи, как я могу это сделать?
sql
sql-server
constraints
Рикардо Альтамирано
источник
источник
Ответы:
SQL Server выполняет простой подсчет каскадных путей и вместо того, чтобы пытаться определить, существуют ли какие-либо циклы на самом деле, он предполагает наихудшее и отказывается создавать ссылочные действия (CASCADE): вы можете и должны создавать ограничения без ссылочных действий. Если вы не можете изменить свой дизайн (или это может скомпрометировать вещи), вам следует рассмотреть возможность использования триггеров в качестве крайней меры.
FWIW разрешение каскадных путей - сложная проблема. Другие продукты SQL просто проигнорируют проблему и позволят вам создавать циклы, и в этом случае будет гонка, чтобы увидеть, кто перезапишет значение последним, вероятно, по незнанию дизайнера (например, ACE / Jet делает это). Я понимаю, что некоторые продукты SQL будут пытаться разрешить простые случаи. Факт остается фактом, SQL Server даже не пытается, он играет очень безопасно, запретив более одного пути и, по крайней мере, говорит вам об этом.
Сами Microsoft советует использовать триггеры вместо ограничений FK.
источник
Типичная ситуация с несколькими каскадными путями будет такой: мастер-таблица с двумя деталями, скажем, «Master» и «Detail1» и «Detail2». Обе детали каскадного удаления. Пока проблем нет. Но что, если обе детали имеют отношение «один ко многим» с какой-то другой таблицей (скажем, «SomeOtherTable»). SomeOtherTable имеет столбец Detail1ID И столбец Detail2ID.
Другими словами: некоторые записи в SomeOtherTable связаны с записями Detail1, а некоторые записи в SomeOtherTable связаны с записями Detail2. Даже если гарантируется, что SomeOtherTable-записи никогда не принадлежат обеим деталям, теперь невозможно сделать каскадное удаление записей SomeOhterTable для обеих деталей, потому что существует несколько каскадных путей от Master к SomeOtherTable (один через Detail1 и один через Detail2). Теперь вы, возможно, уже поняли это. Вот возможное решение:
Все поля идентификатора являются ключевыми и имеют автоинкремент. Суть лежит в полях DetailMainId таблиц деталей. Эти поля являются ключевыми и ссылочными противоречиями. Теперь можно каскадно удалять все, удаляя только основные записи. Недостатком является то, что для каждой записи detail1 И для каждой записи detail2 также должна существовать запись DetailMain (которая фактически создается первой, чтобы получить правильный и уникальный идентификатор).
источник
Я хотел бы отметить, что (функционально) существует большая разница между циклами и / или несколькими путями в SCHEMA и DATA. Хотя циклы и, возможно, многолучевое распространение в DATA могут, безусловно, усложнять обработку и вызывать проблемы с производительностью (стоимость «правильной» обработки), стоимость этих характеристик в схеме должна быть близка к нулю.
Поскольку наиболее очевидные циклы в RDB происходят в иерархических структурах (оргструктура, деталь, подраздел и т. Д.), К сожалению, SQL Server предполагает худшее; т.е. цикл схемы == цикл данных. На самом деле, если вы используете ограничения RI, вы не можете построить цикл в данных!
Я подозреваю, что проблема многолучевого распространения аналогична; то есть множественные пути в схеме не обязательно подразумевают множественные пути в данных, но у меня меньше опыта с проблемой многолучевого распространения.
Конечно , если SQL Server был разрешить циклы он все еще подвергаться на глубину 32, но это, вероятно , достаточно для большинства случаев. (Жаль, что это не настройка базы данных!)
Триггеры «вместо удаления» тоже не работают. При втором посещении таблицы триггер игнорируется. Итак, если вы действительно хотите смоделировать каскад, вам придется использовать хранимые процедуры при наличии циклов. Вместо этого триггер вместо удаления будет работать для случаев многолучевого распространения.
Celko предлагает «лучший» способ представления иерархий, в котором нет циклов, но есть компромиссы.
источник
Доступна статья, в которой объясняется, как выполнить несколько путей удаления с помощью триггеров. Может быть, это полезно для сложных сценариев.
http://www.mssqltips.com/sqlservertip/2733/solving-the-sql-server-multiple-cascade-path-issue-with-a-trigger/
источник
Судя по всему, у вас есть действие OnDelete / OnUpdate для одного из ваших существующих внешних ключей, которое изменит вашу таблицу кодов.
Таким образом, создав этот внешний ключ, вы будете создавать циклическую проблему,
Например, при обновлении сотрудников происходит изменение кодов с помощью действия при обновлении, при изменении действия сотрудников с помощью действия при обновлении ... и т. Д ...
Если вы опубликуете свои определения таблиц для обеих таблиц, а также определения внешнего ключа / ограничения, мы сможем сообщить вам, в чем проблема ...
источник
Это связано с тем, что у Emplyee может быть Коллекция другой сущности, например, у Квалификаций и Квалификаций могут быть другие Университеты коллекции, например
}
}
}
На DataContext это может быть как ниже
}
в этом случае существует цепочка от сотрудника к квалификации и от квалификации к университетам. Так что это было то же исключение для меня.
Это сработало для меня, когда я изменился
к
источник
Триггер является решением этой проблемы:
источник
Это ошибка типа триггера политик базы данных. Триггер - это код, который может добавить некоторую интеллектуальность или условия к каскадному отношению, например, каскадное удаление. Вам может понадобиться специализировать параметры связанных таблиц, например, « Отключение CascadeOnDelete» :
Или полностью отключите эту функцию:
источник
Мое решение этой проблемы, возникшее при использовании ASP.NET Core 2.0 и EF Core 2.0, заключалось в следующем:
Запустите
update-database
команду в консоли управления пакетами (PMC) для создания базы данных (это приводит к ошибке «Введение ограничения FOREIGN KEY ... может привести к циклам или нескольким каскадным путям.»Запустите
script-migration -Idempotent
команду в PMC, чтобы создать скрипт, который можно запускать независимо от существующих таблиц / ограничений.Возьми полученный скрипт и найди
ON DELETE CASCADE
и замени наON DELETE NO ACTION
Выполнить модифицированный SQL для базы данных
Теперь ваши миграции должны быть современными, и каскадное удаление не должно происходить.
Жаль, что я не смог найти какой-либо способ сделать это в Entity Framework Core 2.0.
Удачи!
источник