Объект 'DF __ *' зависит от столбца '*' - изменение int на double

168

В основном я получил таблицу в моей базе данных 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 Оценка не выполнена, поскольку один или несколько объектов имеют доступ к этому столбцу.

В чем проблема?

Джордан Топор
источник
1
Снимите ограничение DF_Movies_Rating__48CFD27E, а затем измените тип поля
Джо Тарас,
@JoeTaras Но я никогда не создавал ограничения с таким названием. Что это и где я могу найти это?
Джордан Топор
2
При создании поля СУБД создайте автоматически ограничение. Если вы развернете информацию таблицы, в разделе ограничений вы найдете ее. Скажи мне, если найдешь;)
Джо Тарас

Ответы:

252

Попробуй это:

Удалите ограничение DF_Movies_Rating__48CFD27E перед изменением типа вашего поля.

Ограничение обычно создается автоматически СУБД (SQL Server).

Чтобы увидеть ограничение, связанное с таблицей, разверните атрибуты таблицы в обозревателе объектов , а затем категорию Ограничения, как показано ниже:

Дерево твоего стола

Вы должны удалить ограничение перед изменением типа поля.

Джо Тарас
источник
40
@ManirajSS: ALTER TABLE yourtable DROP CONSTRAINT DF_Movies_Rating__48CFD27E
Джо Тарас
18
Что спровоцировало создание ограничения? У меня их много, и я действительно не хочу их!
Саймон Паркер
5
Хм, а что делать, если я хочу использовать миграцию БД моего фреймворка (Laravel) и dropColumn там? Я понятия не имею, как удалить ограничение с загадочным именем,
автоматически сгенерированное
2
Я уверен: я это и падаю на порядок ограничения папки становятся пустыми, и когда я запустить приложение или вызвать update-databaseего воссоздать себя снова я отправил этот вопрос: stackoverflow.com/questions/40267769/...
mshwf
2
Почему, черт возьми, SQLServer не отбрасывает неявное ограничение? Это, в конце концов, создало это неявно!
youcantryreachingme
46

Это tsqlпуть

 ALTER TABLE yourtable DROP CONSTRAINT constraint_name     -- DF_Movies_Rating__48CFD27E

Для полноты, это просто показывает комментарий @Joe Taras в качестве ответа

Луис Сиквот
источник
46

Я добавляю это как ответ, чтобы объяснить, откуда исходит ограничение. Я пытался сделать это в комментариях, но там сложно отредактировать: - /

Если вы создаете (или изменяете) таблицу со столбцом, который имеет значения по умолчанию, это создаст для вас ограничение.

Например, в вашей таблице это может быть:

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 оператора, чтобы изменить столбец и назвать ограничение в одной строке (в любом случае, если это уже существующая таблица)

h3adache
источник
Спасибо за добавление информации о том, как избежать этой проблемы, указав в первую очередь все ограничения. (То есть, избегайте проблемы
удаления
22

Поскольку ограничение имеет непредсказуемое имя, вы можете написать специальный скрипт ( 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));    
}
Слава Утесинов
источник
Этот ответ отлично работает в среде на основе миграции, где вы не можете позволить себе жестко задавать имя ограничения.
Menion Leah
Если вы делаете функцию-обертку / расширение / перегруженную функцию для AlterColumn - например, AlterColumnX - вы можете включить в нее эту логику DropConstraint - и вы можете передать имя таблицы и имя столбца, чтобы вам не приходилось писать их снова.
N73k
10

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

Блог

AZ_
источник
1
спасла мою жизнь дважды сейчас Им обоим приходится удалять проверочные ограничения. Прежде всего я должен использовать первый запрос. Во-вторых, мне нужно использовать второй запрос, потому что в таблице SYS.DEFAULT_CONSTRAINTS не найдено проверочное ограничение. Большое спасибо!
воскресенье
8

Когда мы пытаемся удалить столбец, от которого зависит, мы видим такую ​​ошибку:

Объект '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
Джинна Балу
источник
1

Решение :

открыть таблицу базы данных -> развернуть таблицу -> развернуть ограничения и увидеть это

Скриншот

Аруп Махапатра
источник
Хотя этот код может ответить на вопрос, предоставление дополнительного контекста относительно того, почему и / или как этот код отвечает на вопрос, повышает его долгосрочную ценность.
Дональд Дак
-1

У меня была эта ошибка при попытке запустить миграцию, чтобы обойти ее, я переименовал столбец и заново сгенерировал миграцию, используя

add-migration migrationname -force

в консоли диспетчера пакетов. Я тогда смог бежать

update-database

успешно.

Кирстен Жадность
источник
2
Будьте осторожны, это не переименовывает столбец - он удаляет столбец и добавляет новый столбец. Вы потеряете все данные, которые раньше существовали в столбце, если не добавите пользовательский код в миграцию.
caesay