Объект 'DF__*' зависит от столбца '*' - изменение int на double
В основном я получил таблицу в моей базе данных EF со следующими свойствами:
public int Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string Image { get; set; }
public string WatchUrl { get; set; }
public int Year { get; set; }
public string Source { get; set; }
public int Duration { get; set; }
public int Rating { get; set; }
public virtual ICollection<Category> Categories { get; set; }
Это работает нормально, однако, когда я изменяю int рейтинга на двойное, я получаю следующую ошибку при обновлении базы данных:
Объект "DF_ Movies _Rating__48CFD27E" зависит от столбца "Рейтинг". ALTER TABLE ALTER COLUMN Оценка не выполнена, так как один или несколько объектов имеют доступ к этому столбцу.
В чем проблема?
8 ответов
Попробуй это:
Удалите ограничение DF_Movies_Rating__48CFD27E перед изменением типа вашего поля.
Ограничение обычно создается автоматически СУБД (SQL Server).
Чтобы увидеть ограничение, связанное с таблицей, разверните атрибуты таблицы в обозревателе объектов, а затем категорию Ограничения, как показано ниже:
Вы должны удалить ограничение перед изменением типа поля.
Я добавляю это как ответ, чтобы объяснить, откуда исходит ограничение. Я пытался сделать это в комментариях, но там сложно отредактировать:-/
Если вы создаете (или изменяете) таблицу со столбцом, который имеет значения по умолчанию, это создаст для вас ограничение.
Например, в вашей таблице это может быть:
CREATE TABLE Movie (
...
rating INT NOT NULL default 100
)
Это создаст ограничение по умолчанию 100.
Если вы вместо этого создадите это так
CREATE TABLE Movie (
name VARCHAR(255) NOT NULL,
rating INT NOT NULL CONSTRAINT rating_default DEFAULT 100
);
Затем вы получите ограничение с хорошим именем, на которое легче ссылаться при изменении указанной таблицы.
ALTER TABLE Movie DROP CONSTRAINT rating_default;
ALTER TABLE Movie ALTER COLUMN rating DECIMAL(2) NOT NULL;
-- sets up a new default constraint with easy to remember name
ALTER TABLE Movie ADD CONSTRAINT rating_default DEFAULT ((1.0)) FOR rating;
Вы можете объединить эти последние 2 оператора, чтобы изменить столбец и назвать ограничение в одной строке (в любом случае, если это существующая таблица, это необходимо)
Это tsql
путь
ALTER TABLE yourtable DROP CONSTRAINT constraint_name -- DF_Movies_Rating__48CFD27E
Для полноты, это просто показывает комментарий @Joe Taras в качестве ответа
Поскольку ограничение имеет непредсказуемое имя, вы можете написать специальный скрипт (DropConstraint), чтобы удалить его, не зная его имени (было протестировано в EF 6.1.3):
public override void Up()
{
DropConstraint();
AlterColumn("dbo.MyTable", "Rating", c => c.Double(nullable: false));
}
private void DropConstraint()
{
Sql(@"DECLARE @var0 nvarchar(128)
SELECT @var0 = name
FROM sys.default_constraints
WHERE parent_object_id = object_id(N'dbo.MyTable')
AND col_name(parent_object_id, parent_column_id) = 'Rating';
IF @var0 IS NOT NULL
EXECUTE('ALTER TABLE [dbo].[MyTable] DROP CONSTRAINT [' + @var0 + ']')");
}
public override void Down()
{
AlterColumn("dbo.MyTable", "Rating", c => c.Int(nullable: false));
}
Когда мы пытаемся удалить столбец, от которого зависит, мы видим такую ошибку:
Объект 'DF__*' зависит от столбца ''.
удалить ограничение, которое зависит от этого столбца с помощью:
ALTER TABLE TableName DROP CONSTRAINT dependent_constraint;
Пример:
Сообщение 5074, Уровень 16, Состояние 1, Строка 1
Объект 'DF__Employees__Colf__1273C1CD' зависит от столбца 'Colf'.
Сообщение 4922, уровень 16, состояние 9, строка 1
ALTER TABLE DROP COLUMN Colf не удалось, поскольку один или несколько объектов имеют доступ к этому столбцу.
Отбросить ограничение (DF__Employees__Colf__1273C1CD):
ALTER TABLE Employees DROP CONSTRAINT DF__Employees__Colf__1273C1CD;
Тогда вы можете удалить столбец:
Alter Table TableName Drop column ColumnName
MS SQL Studio заботится о том, когда вы удаляете столбец, но если вам нужно удалить ограничение программно, здесь есть простое решение
Вот фрагмент кода, который удалит столбец с ограничением по умолчанию:
DECLARE @ConstraintName nvarchar(200)
SELECT @ConstraintName = Name FROM SYS.DEFAULT_CONSTRAINTS WHERE PARENT_OBJECT_ID = OBJECT_ID('__TableName__') AND PARENT_COLUMN_ID = (SELECT column_id FROM sys.columns WHERE NAME = N'__ColumnName__' AND object_id = OBJECT_ID(N'__TableName__'))
IF @ConstraintName IS NOT NULL
EXEC('ALTER TABLE __TableName__ DROP CONSTRAINT ' + @ConstraintName)
IF EXISTS (SELECT * FROM syscolumns WHERE id=object_id('__TableName__') AND name='__ColumnName__')
EXEC('ALTER TABLE __TableName__ DROP COLUMN __ColumnName__')
Просто замените TableName и ColumnName на соответствующие значения. Вы можете безопасно запустить это, даже если столбец уже удален.
Бонус: вот код для удаления внешних ключей и других типов ограничений.
IF EXISTS(SELECT 1 FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE where TABLE_NAME = '__TableName__' AND COLUMN_NAME = '__ColumnName__')
BEGIN
SELECT @ConstraintName = CONSTRAINT_NAME FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE where TABLE_NAME = '__TableName__' AND COLUMN_NAME = '__ColumnName__'
EXEC('ALTER TABLE __TableName__ DROP CONSTRAINT ' + @ConstraintName)
END
При удалении столбцов из нескольких таблиц я столкнулся со следующей ошибкой ограничений по умолчанию. Аналогичная проблема возникает, если вам нужно изменить тип данных столбца.
Объект "DF_TableName_ColumnName" зависит от столбца "ColumnName".
Чтобы решить эту проблему, я должен сначала отказаться от всех этих ограничений, используя следующий запрос
DECLARE @sql NVARCHAR(max)=''
SELECT @SQL += 'Alter table ' + Quotename(tbl.name) + ' DROP constraint ' + Quotename(cons.name) + ';'
FROM SYS.DEFAULT_CONSTRAINTS cons
JOIN SYS.COLUMNS col ON col.default_object_id = cons.object_id
JOIN SYS.TABLES tbl ON tbl.object_id = col.object_id
WHERE col.[name] IN ('Column1','Column2')
--PRINT @sql
EXEC Sp_executesql @sql
После этого я отбросил все эти столбцы (мое требование, не упомянутое в этом вопросе)
DECLARE @sql NVARCHAR(max)=''
SELECT @SQL += 'Alter table ' + Quotename(table_catalog)+ '.' + Quotename(table_schema) + '.'+ Quotename(TABLE_NAME)
+ ' DROP column ' + Quotename(column_name) + ';'
FROM information_schema.columns where COLUMN_NAME IN ('Column1','Column2')
--PRINT @sql
EXEC Sp_executesql @sql
Я разместил здесь, если кто-то обнаружит ту же проблему.
Удачного кодирования!
У меня была эта ошибка при попытке запустить миграцию, чтобы обойти ее, я переименовал столбец и заново сгенерировал миграцию, используя
add-migration migrationname -force
в консоли диспетчера пакетов. Я тогда смог бежать
update-database
успешно.