L'objet 'DF __ *' dépend de la colonne '*' - Modification de int en double

168

Fondamentalement, j'ai une table dans ma base de données EF avec les propriétés suivantes:

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

Cela fonctionne bien, mais lorsque je change l'int de Rating pour être un double, j'obtiens l'erreur suivante lors de la mise à jour de la base de données:

L'objet 'DF_ Movies _Rating__48CFD27E' dépend de la colonne 'Rating'. ALTER TABLE ALTER COLUMN L'évaluation a échoué car un ou plusieurs objets accèdent à cette colonne.

Quel est le problème?

Jordan Axe
la source
1
Supprimez la contrainte DF_Movies_Rating__48CFD27E puis changez le type de votre champ
Joe Taras
@JoeTaras Mais je n'ai jamais créé de contrainte nommée ça. Qu'est-ce que c'est et où puis-je le trouver?
Jordan Axe
2
Lorsque vous créez un champ, le SGBD crée automatiquement une contrainte. Si vous développez les informations de votre table, dans la section contrainte, vous la trouverez. Dites-moi si vous trouverez;)
Joe Taras

Réponses:

252

Essaye ça:

Supprimez la contrainte DF_Movies_Rating__48CFD27E avant de modifier votre type de champ.

La contrainte est généralement créée automatiquement par le SGBD (SQL Server).

Pour voir la contrainte associée à la table, développez les attributs de table dans l' Explorateur d'objets , puis la catégorie Contraintes comme indiqué ci-dessous:

Arbre de votre table

Vous devez supprimer la contrainte avant de modifier le type de champ.

Joe Taras
la source
40
@ManirajSS: ALTER TABLE yourtable DROP CONSTRAINT DF_Movies_Rating__48CFD27E
Joe Taras
18
Qu'est-ce qui a déclenché la création de la contrainte? J'en ai un tas et je n'en veux vraiment pas!
Simon Parker
5
Hmm, et que faire si je veux utiliser les migrations DB de mon framework (Laravel) et dropColumn là-bas? Je ne sais pas comment supprimer la contrainte qui a un nom mystérieux, générée automatiquement par le serveur SQL :(
JustAMartin
2
Je suis sûr: je l'ai laissé tomber et le dossier Contraintes devient vide, et quand je lance l'application ou que je l'appelle, update-databaseil se recrée à nouveau, j'ai posté ce problème: stackoverflow.com/questions/40267769/…
mshwf
2
Pourquoi diable SQLServer ne supprime-t-il pas la contraint implicitement? Après tout, il l'a créé implicitement!
youcantryreachingme
46

C'est le tsqlchemin

 ALTER TABLE yourtable DROP CONSTRAINT constraint_name     -- DF_Movies_Rating__48CFD27E

Par souci d'exhaustivité, cela montre simplement le commentaire de @Joe Taras comme réponse

Luis Siquot
la source
46

J'ajoute ceci comme réponse pour expliquer d'où vient la contrainte. J'ai essayé de le faire dans les commentaires mais c'est difficile de bien éditer là-bas: - /

Si vous créez (ou modifiez) une table avec une colonne qui a des valeurs par défaut, cela créera la contrainte pour vous.

Dans votre tableau par exemple, cela pourrait être:

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

Cela créera la contrainte par défaut 100.

Si vous le créez plutôt comme ça

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

Ensuite, vous obtenez une contrainte bien nommée qui est plus facile à référencer lorsque vous modifiez ladite table.

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;

Vous pouvez combiner ces 2 dernières instructions afin de modifier la colonne et de nommer la contrainte sur une ligne (vous devez quand même le faire s'il s'agit d'une table existante)

h3adache
la source
Merci d'avoir ajouté des informations sur la façon d'éviter le problème en nommant toutes les contraintes en premier lieu. (Autrement dit, évitez le problème de la suppression des contraintes nommées au hasard)
youcantryreachingme
22

Comme la contrainte a un nom imprévisible, vous pouvez écrire un script spécial ( DropConstraint ) pour le supprimer sans connaître son nom (a été testé à 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
la source
Cette réponse fonctionne très bien dans un environnement basé sur la migration où vous ne pouvez pas vous permettre de coder en dur le nom de la contrainte.
Menion Leah
Si vous créez une fonction wrapper / extension / surchargée pour AlterColumn - comme AlterColumnX - vous pouvez y inclure cette logique DropConstraint - et vous pouvez passer le nom de la table et le nom de la colonne afin de ne pas avoir à les écrire à nouveau.
N73k
10

MS SQL Studio prend soin de supprimer la colonne mais si vous devez supprimer la contrainte par programme voici une solution simple

Voici un extrait de code qui supprimera une colonne avec une contrainte par défaut:

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

Remplacez simplement TableName et ColumnName par les valeurs appropriées. Vous pouvez l'exécuter en toute sécurité même si la colonne a déjà été supprimée.

Bonus : voici le code pour supprimer les clés étrangères et d'autres types de contraintes.

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_
la source
1
m'a sauvé la vie deux fois maintenant. Les deux, devant supprimer les contraintes de contrôle. Tout d'abord, je dois utiliser la première requête. Deuxièmement, je dois utiliser la deuxième requête car la contrainte de vérification n'a pas été trouvée dans la table SYS.DEFAULT_CONSTRAINTS. Merci beaucoup!
dimanche
8

Lorsque nous essayons de supprimer une colonne dont dépend, nous voyons ce type d'erreur:

L'objet 'DF __ *' dépend de la colonne ''.

supprimez la contrainte qui dépend de cette colonne avec:

ALTER TABLE TableName DROP CONSTRAINT dependent_constraint;

Exemple:

Msg 5074, niveau 16, état 1, ligne 1

L'objet ' DF__Employees__Colf__1273C1CD' dépend de la colonne 'Colf'.

Msg 4922, niveau 16, état 9, ligne 1

ALTER TABLE DROP COLUMN Colf a échoué car un ou plusieurs objets accèdent à cette colonne.

Contrainte de suppression (DF__Employees__Colf__1273C1CD):

ALTER TABLE Employees DROP CONSTRAINT DF__Employees__Colf__1273C1CD;

Ensuite, vous pouvez supprimer la colonne:

Alter Table TableName Drop column ColumnName
Jinna Balu
la source
1

Solution :

ouvrir la table de base de données -> développer la table -> développer les contraintes et voir ceci

capture d'écran

Arup Mahapatra
la source
Bien que ce code puisse répondre à la question, fournir un contexte supplémentaire concernant la raison et / ou la manière dont ce code répond à la question améliore sa valeur à long terme.
Donald Duck
-1

J'ai eu cette erreur en essayant d'exécuter une migration pour la contourner J'ai renommé la colonne et re-généré la migration en utilisant

add-migration migrationname -force

dans la console du gestionnaire de packages. J'ai pu alors courir

update-database

avec succès.

Kirsten Greed
la source
2
Attention, cela ne renomme pas une colonne - cela supprime la colonne et ajoute une nouvelle colonne. Vous perdrez toutes les données qui existaient auparavant dans la colonne, sauf si vous ajoutez du code personnalisé dans la migration.
caesay