Только что построив приложение на c # для запуска сценариев SQL, я столкнулся с несколькими проблемами при обработке ошибок.
У нас есть хранимая процедура в нашей базе данных, которая изменяет ограничение по умолчанию для таблиц (удаляя любую существующую и затем создавая новую), и она работает нормально, когда мы вызываем ее из SSMS. Однако когда мы вызываем ту же хранимую процедуру из .Net SqlClient, она выдает ошибку. Я получаю сообщение об ошибке SqlException
:
System.Data.SqlClient.SqlException: Column already has a DEFAULT bound to it.
Could not create constraint. See previous errors.
Этого не должно быть, поскольку мы никогда не увидим сообщение в SSMS, если сначала не выполним оператор drop. Если оператор Drop Constraint
закомментирован, мы видим то же сообщение.
Почему ограничение не сбрасывается при вызове хранимой процедуры из .Net?
Для справки, соответствующий код внутри хранимой процедуры:
SELECT @strSQL = 'ALTER TABLE [' + @strTableName + '] DROP CONSTRAINT [' + @strConstraintName + ']'
EXEC sp_executesql @strSQL
SELECT @strSQL = 'ALTER TABLE [' + @strTableName + '] ADD CONSTRAINT DF_' + @strTableName + '_' + @strColumnName + ' DEFAULT (' + @strDefaultValue + ') FOR ' + @strColumnName
EXEC sp_executesql @strSQL
РЕДАКТИРОВАТЬ: я рассмотрел перехват ошибок и игнорировал нефатальные ошибки, такие как эта. Однако, к сожалению, эта конкретная ошибка является ошибкой уровня 16, а такие ошибки, как обновление несуществующей таблицы, относятся только к уровню 15. Поэтому я не могу допустить, чтобы эта ошибка прошла путем фильтрации по классу ошибок исключения.
РЕДАКТИРОВАТЬ 2: Следует отметить, что @strConstraintName
определяется автоматически на основе имени таблицы и имени столбца:
SELECT
@strConstraintName = vdc.CONSTRAINT_NAME
FROM
dbo.vw_DEFAULT_CONSTRAINT vdc
WHERE
vdc.TABLE_NAME = @strTableName
AND vdc.COLUMN_NAME = @strColumnName
Разрешение
Итак, получается, что vw_DEFAULT_CONSTRAINT, который определял имя ограничения по умолчанию, был написан плохо.
По какой-то причине это была фильтрация на основе значения USER_ID () (представление было написано до того, как я начал), в котором не было необходимости. Удаление этого ограничения из представления вернуло правильное имя ограничения.
@ Ответ ErikE обеспечил хороший толчок в правильном направлении. Сохранение значений переменных во временную таблицу позволило мне увидеть, что 2 метода на самом деле не работали одинаково, что побудило меня продолжить изучение представления. Слава @ErikE за это, поэтому я выбрал его в качестве правильного ответа.
Мне кажется странным, что значение USER_ID () не было одинаковым, поскольку соединения были идентичными.