Проект базы данных 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%, потому что безымянное ограничение не может иметь одинаковые случайно сгенерированные имена на вашем компьютере разработчика и на рабочем сервере. И это безрассудно. Но это работает для нашей установки, и любые альтернативы, которые я мог придумать, были еще более хакерскими.

Другие вопросы по тегам