L'oggetto 'DF __ *' dipende dalla colonna '*' - Modifica int in double


168

Fondamentalmente ho ottenuto una tabella nel mio database EF con le seguenti proprietà:

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

Funziona bene tuttavia quando cambio int di Rating per raddoppiare ottengo il seguente errore durante l'aggiornamento del database:

L'oggetto "DF_ Movies _Rating__48CFD27E" dipende dalla colonna "Classificazione". ALTER TABLE ALTER COLUMN La valutazione non è riuscita perché uno o più oggetti accedono a questa colonna.

Qual è il problema?


1
Rimuovi il vincolo DF_Movies_Rating__48CFD27E e quindi modifica il tipo di campo
Joe Taras,

@JoeTaras Ma non ho mai creato un vincolo chiamato così. Che cos'è e dove lo trovo?
Jordan Ax

2
Quando si crea un campo, DBMS crea automaticamente un vincolo. Se espandi le informazioni sulla tabella, nella sezione dei vincoli le troverai. Dimmi se lo troverai;)
Joe Taras,

Risposte:


252

Prova questo:

Rimuovere il vincolo DF_Movies_Rating__48CFD27E prima di modificare il tipo di campo.

Il vincolo viene in genere creato automaticamente dal DBMS (SQL Server).

Per visualizzare il vincolo associato alla tabella, espandere gli attributi della tabella in Esplora oggetti , seguito dalla categoria Vincoli come mostrato di seguito:

Albero della tua tavola

È necessario rimuovere il vincolo prima di modificare il tipo di campo.


40
@ManirajSS: ALTER TABLE yourtable DROP CONSTRAINT DF_Movies_Rating__48CFD27E
Joe Taras,

18
Cosa ha innescato la creazione del vincolo? Ne ho un sacco e davvero non li voglio!
Simon Parker,

5
Hmm, e cosa fare se voglio usare le migrazioni di DB del mio framework (Laravel) e dropColumn lì? Non ho idea di come eliminare il vincolo che ha un nome misterioso, generato automaticamente da SQL Server :(
JustAMartin

2
Sono sicura: ho Droped esso ed i vincoli di cartella si svuota, e quando faccio funzionare l'applicazione o chiamo la update-databasesi ricrearsi di nuovo ho postato questo problema: stackoverflow.com/questions/40267769/...
mshwf

2
Perché diamine SQLServer non rilascia il implicito in modo implicito? Dopo tutto, l'ha creato implicitamente!
youcantryreachingme,

46

Questo è il tsqlmodo

 ALTER TABLE yourtable DROP CONSTRAINT constraint_name     -- DF_Movies_Rating__48CFD27E

Per completezza, questo mostra semplicemente il commento di @Joe Taras come risposta


46

Sto aggiungendo questo come risposta per spiegare da dove viene il vincolo. Ho provato a farlo nei commenti ma è difficile modificarlo bene lì: - /

Se si crea (o si modifica) una tabella con una colonna con valori predefiniti, verrà creato il vincolo per l'utente.

Nella tua tabella ad esempio potrebbe essere:

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

Creerà il vincolo per il valore predefinito 100.

Se invece lo crei così

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

Quindi si ottiene un vincolo ben definito che è più facile fare riferimento quando si modifica detta tabella.

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;

Puoi combinare queste ultime 2 istruzioni in modo da modificare la colonna e nominare il vincolo in una riga (devi comunque se è una tabella esistente)


Grazie per aver aggiunto informazioni su come evitare il problema nominando innanzitutto tutti i vincoli. (Cioè, evita il problema di eliminare i vincoli con
nomi

22

Poiché il vincolo ha un nome imprevedibile, è possibile scrivere uno script speciale ( DropConstraint ) per rimuoverlo senza conoscerne il nome (è stato testato in 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));    
}

Questa risposta funziona benissimo in un ambiente basato sulla migrazione in cui non è possibile permettersi il nome del vincolo hardcode.
Menion Leah,

Se crei una funzione wrapper / extension / overload per AlterColumn - come AlterColumnX - puoi includere la logica DropConstraint in essa - e puoi passare il nome della tabella e il nome della colonna in modo da non doverli riscrivere.
N73k,

10

MS SQL Studio si occupa di eliminare la colonna, ma se è necessario eliminare il vincolo a livello di programmazione, ecco una soluzione semplice

Ecco uno snippet di codice che eliminerà una colonna con un vincolo predefinito:

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

Sostituisci semplicemente TableName e ColumnName con i valori appropriati. Puoi eseguirlo in sicurezza anche se la colonna è già stata eliminata.

Bonus : ecco il codice per eliminare le chiavi esterne e altri tipi di vincoli.

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


1
mi ha salvato la vita due volte ora. Entrambi, eliminando i vincoli di controllo. Prima di tutto devo usare la prima query. In secondo luogo, devo usare la seconda query perché il vincolo del controllo non è stato trovato nella tabella SYS.DEFAULT_CONSTRAINTS. Molte grazie!
domenica

8

Quando proviamo a eliminare una colonna da cui dipende, vediamo questo tipo di errore:

L'oggetto 'DF __ *' dipende dalla colonna ''.

rilasciare il vincolo che dipende da quella colonna con:

ALTER TABLE TableName DROP CONSTRAINT dependent_constraint;

Esempio:

Messaggio 5074, livello 16, stato 1, riga 1

L'oggetto ' DF__Employees__Colf__1273C1CD' dipende dalla colonna 'Colf'.

Messaggio 4922, livello 16, stato 9, riga 1

ALTER TABLE DROP COLUMN Colf non riuscito perché uno o più oggetti accedono a questa colonna.

Vincolo di rilascio (DF__Employees__Colf__1273C1CD):

ALTER TABLE Employees DROP CONSTRAINT DF__Employees__Colf__1273C1CD;

Quindi puoi rilasciare la colonna:

Alter Table TableName Drop column ColumnName

1

Soluzione:

apri tabella database -> espandi tabella -> espandi vincoli e vedi questo

immagine dello schermo


Mentre questo codice può rispondere alla domanda, fornendo un contesto aggiuntivo riguardo al perché e / o al modo in cui questo codice risponde alla domanda migliora il suo valore a lungo termine.
Donald Duck,

-1

Ho riscontrato questo errore nel tentativo di eseguire una migrazione per aggirare il problema. Ho rinominato la colonna e ricreato la migrazione utilizzando

add-migration migrationname -force

nella console di gestione dei pacchetti. Sono stato quindi in grado di correre

update-database

con successo.


2
Fai attenzione, questo non rinomina una colonna: rilascia la colonna e aggiunge una nuova colonna. Perderai tutti i dati che esistevano nella colonna a meno che non aggiungessi codice personalizzato nella migrazione.
martedì
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.