O objeto 'DF __ *' depende da coluna '*' - Alterando int para dobrar

168

Basicamente, recebi uma tabela no meu banco de dados EF com as seguintes propriedades:

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; }

Funciona bem, no entanto, quando altero o int de Rating para um dobro, recebo o seguinte erro ao atualizar o banco de dados:

O objeto 'DF_ Movies _Rating__48CFD27E' depende da coluna 'Rating'. ALTER TABLE ALTER COLUMN A classificação falhou porque um ou mais objetos acessam esta coluna.

Qual é o problema?

Jordan Axe
fonte
1
Remova a restrição DF_Movies_Rating__48CFD27E e altere o tipo do seu campo
Joe Taras
@ JoeTaras Mas eu nunca criei uma restrição chamada isso. O que é e onde o encontro?
perfil completo de Jordan Axe
2
Quando você cria um campo, o DBMS cria automaticamente uma restrição. Se você expandir as informações da tabela, na seção de restrições, você as encontrará. Diga-me se você encontrará;)
Joe Taras

Respostas:

252

Tente o seguinte:

Remova a restrição DF_Movies_Rating__48CFD27E antes de alterar seu tipo de campo.

A restrição geralmente é criada automaticamente pelo DBMS (SQL Server).

Para ver a restrição associada à tabela, expanda os atributos da tabela no Pesquisador de objetos , seguidos pela categoria Restrições, como mostrado abaixo:

Árvore da sua mesa

Você deve remover a restrição antes de alterar o tipo de campo.

Joe Taras
fonte
40
@ManirajSS: ALTER TABLE sua tabela DROP CONSTRAINT DF_Movies_Rating__48CFD27E
Joe Taras
18
O que desencadeou a criação da restrição? Eu tenho um monte deles e realmente não os quero!
Simon Parker
5
Hmm, e o que fazer se eu quiser usar migrações de banco de dados do meu framework (Laravel) e dropColumn lá? Eu não tenho idéia de como eliminar a restrição que tem nome misterioso,
gerada
2
Eu tenho certeza: eu o soltei e a pasta Restrições fica vazia e, quando executo o aplicativo ou chamo-o de update-databasenovo, publiquei este problema: stackoverflow.com/questions/40267769/…
mshwf
2
Por que diabos o SQLServer não descarta o contraint implicitamente? Afinal, ele o criou implicitamente!
youcantryreachingme
46

Este é o tsqlcaminho

 ALTER TABLE yourtable DROP CONSTRAINT constraint_name     -- DF_Movies_Rating__48CFD27E

Para ser completo, isso apenas mostra o comentário de @Joe Taras como resposta

Luis Siquot
fonte
46

Estou adicionando isso como uma resposta para explicar de onde vem a restrição. Tentei fazê-lo nos comentários, mas é difícil editar bem lá: - /

Se você criar (ou alterar) uma tabela com uma coluna com valores padrão, ela criará a restrição para você.

Na sua tabela, por exemplo, pode ser:

CREATE TABLE Movie (
    ...
    rating INT NOT NULL default 100
)

Isso criará a restrição para o padrão 100.

Se você criá-lo assim

CREATE TABLE Movie (
  name VARCHAR(255) NOT NULL,
  rating INT NOT NULL CONSTRAINT rating_default DEFAULT 100
);

Então você obtém uma restrição bem nomeada que é mais fácil de referenciar quando você está alterando a tabela.

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;

Você pode combinar essas duas últimas instruções para alterar a coluna e nomear a restrição em uma linha (você precisa, se for uma tabela existente)

h3adache
fonte
Obrigado por adicionar informações sobre como evitar o problema, nomeando todas as restrições em primeiro lugar. (Ou seja, evitar o problema de deixar cair restrições nomeados aleatoriamente)
youcantryreachingme
22

Como a restrição tem nome imprevisível, você pode escrever um script especial ( DropConstraint ) para removê-lo sem saber o nome (foi testado no 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));    
}
Slava Utesinov
fonte
Essa resposta funciona muito bem em um ambiente baseado em migração, no qual você não pode dar ao luxo de codificar o nome da restrição.
Menion Leah 4/11
Se você criar uma função wrapper / extensão / sobrecarregada para AlterColumn - como o AlterColumnX - poderá incluir a lógica DropConstraint lá - e poderá passar o nome da tabela e o nome da coluna para não precisar escrevê-los novamente.
N19k #
10

O MS SQL Studio cuida de quando você exclui a coluna, mas se você precisar Excluir Restrições Programaticamente, aqui está uma solução simples

Aqui está um trecho de código que solta uma coluna com uma restrição padrão:

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__')

Apenas substitua TableName e ColumnName pelos valores apropriados. Você pode executar isso com segurança, mesmo que a coluna já tenha sido descartada.

Bônus : Aqui está o código para descartar chaves estrangeiras e outros tipos de restrições.

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

Blog

AZ_
fonte
1
salvei minha vida duas vezes agora. Ambos, tendo que excluir restrições de verificação. Primeiro de tudo eu tenho que usar a primeira consulta. Segundo, preciso usar a segunda consulta porque a restrição de verificação não foi encontrada na tabela SYS.DEFAULT_CONSTRAINTS. Muito obrigado!
domingo
8

Quando tentamos soltar uma coluna da qual dependemos, vemos esse tipo de erro:

O objeto 'DF __ *' depende da coluna ''.

descarte a restrição que depende dessa coluna com:

ALTER TABLE TableName DROP CONSTRAINT dependent_constraint;

Exemplo:

Msg 5074, Nível 16, Estado 1, Linha 1

O objeto ' DF__Employees__Colf__1273C1CD' depende da coluna 'Colf'.

Msg 4922, nível 16, estado 9, linha 1

ALTER TABLE DROP COLUMN Colf falhou porque um ou mais objetos acessam esta coluna.

Restrição de descarte (DF__Employees__Colf__1273C1CD):

ALTER TABLE Employees DROP CONSTRAINT DF__Employees__Colf__1273C1CD;

Então você pode soltar a coluna:

Alter Table TableName Drop column ColumnName
Jinna Balu
fonte
1

Solução:

abra a tabela do banco de dados -> expanda a tabela -> expanda as restrições e veja isso

captura de tela

Arup Mahapatra
fonte
Embora esse código possa responder à pergunta, fornecer um contexto adicional a respeito de por que e / ou como esse código responde à pergunta melhora seu valor a longo prazo.
Donald Duck
-1

Ocorreu um erro ao tentar executar uma migração para contorná-la. Renomeei a coluna e gere novamente a migração usando

add-migration migrationname -force

no console do gerenciador de pacotes. Eu era capaz de correr

update-database

com sucesso.

Kirsten Greed
fonte
2
Tenha cuidado, isso não renomeia uma coluna - ele solta a coluna e adiciona uma nova coluna. Você perderá todos os dados que existiam na coluna, a menos que adicione código personalizado na migração.
caesay