Проект базы данных Visual Studio - изменение таблицы перед развертыванием не работает
Мне нужно изменить составной первичный ключ для таблицы из проекта базы данных в Visual Studio 2017, а именно изменить его на 2 столбца вместо 4 после удаления всех дубликатов. Я поместил скрипт, который удаляет дубликаты, перед развертыванием, и он выглядит так:
CREATE TABLE tmp_table
(
<same columns as old_table>,
CONSTRAINT [PK_NewPK]
PRIMARY KEY CLUSTERED ([Column1], [Column2] ASC)
) ON [PRIMARY]
INSERT INTO tmp_table
(SELECT <unique data from old_table>)
TRUNCATE old_table
DROP old_table
EXEC sp_rename 'tmp_table', 'old_table'
Он работает как charm, но новый old_table после развертывания все еще имеет старый первичный ключ из 4 столбцов, что неудивительно, поскольку код для old_table не был изменен. Проблема в том, что когда я пытаюсь отредактировать old_table, чтобы иметь PK с двумя столбцами, развертывание завершается неудачно с
SQL72014: поставщик данных.Net SqlClient:
Сообщение 3728, уровень 16, состояние 1, строка 1
'DF__old_table__' не является ограничением.
Я предположил, что изменения кода в таблицах применяются после сценариев перед развертыванием, но что-то выглядит ужасно неправильно с порядком событий здесь, и я не вижу, как это исправить.
1 ответ
Хорошо, перечитав этот пост несколько раз, я понял, что не так с порядком событий здесь (да, проблема этапа перед развертыванием) - то есть код развертывания генерируется из результатов сравнения моделей, и сравнение моделей выполняется ДО выполнения кода перед развертыванием. Итак, это выглядит так:
- Модели исходной и целевой баз данных сравниваются, отмечается изменение первичного ключа для old_table, и сценарий развертывания изменяется, чтобы отразить это, включая удаление ограничения по умолчанию;
- Код перед развертыванием выполняется, и он немного изменяет old_table, но сценарий развертывания не знает об этом;
- Код развертывания выполняется и сразу падает при попытке удалить это ограничение по умолчанию, потому что его больше нет (но он был там, когда мы проверяли, только его нет и даже не будет... тьфу);
- Прибыль (не совсем).
И да, это то, как это должно работать, и я действительно упустил что-то очевидное. Теперь я знаю.
Решение для меня заключалось в том, чтобы создать это ограничение DF__old_table__ в конце сценария перед развертыванием, поэтому оно все еще существует в измененной old_table, когда код развертывания ищет его, но затем оно исчезнет, потому что код развертывания для old_table не будет имеют какие-либо значения по умолчанию, и даже если это так, ограничение будет иметь другое имя (потому что безымянные ограничения являются злом).
Кстати, это решение не является надежным на 100%, потому что безымянное ограничение не может иметь одинаковые случайно сгенерированные имена на вашем компьютере разработчика и на рабочем сервере. И это безрассудно. Но это работает для нашей установки, и любые альтернативы, которые я мог придумать, были еще более хакерскими.