Das Objekt 'DF __ *' ist abhängig von der Spalte '*' - Ändern von int in double

168

Grundsätzlich habe ich eine Tabelle in meiner EF-Datenbank mit den folgenden Eigenschaften:

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

Es funktioniert einwandfrei, aber wenn ich das int von Rating in ein Double ändere, wird beim Aktualisieren der Datenbank der folgende Fehler angezeigt:

Das Objekt 'DF_ Movies _Rating__48CFD27E' ist abhängig von der Spalte 'Rating'. ALTER TABLE ALTER COLUMN Die Bewertung ist fehlgeschlagen, da ein oder mehrere Objekte auf diese Spalte zugreifen.

Was ist das Problem?

Jordan Axe
quelle
1
Entfernen Sie die Einschränkung DF_Movies_Rating__48CFD27E und ändern Sie dann den Typ Ihres Feldes
Joe Taras
@ JoeTaras Aber ich habe noch nie eine Einschränkung namens so erstellt. Was ist das und wo finde ich es?
Jordan Axe
2
Wenn Sie ein Feld erstellen, erstellt DBMS automatisch eine Einschränkung. Wenn Sie Ihre Tabelleninformationen erweitern, finden Sie sie im Abschnitt "Einschränkungen". Sag mir, ob du finden wirst;)
Joe Taras

Antworten:

252

Versuche dies:

Entfernen Sie die Einschränkung DF_Movies_Rating__48CFD27E, bevor Sie Ihren Feldtyp ändern.

Die Einschränkung wird normalerweise automatisch vom DBMS (SQL Server) erstellt.

Um die mit der Tabelle verknüpfte Einschränkung anzuzeigen, erweitern Sie die Tabellenattribute im Objekt-Explorer , gefolgt von der Kategorie Einschränkungen, wie unten gezeigt:

Baum Ihres Tisches

Sie müssen die Einschränkung entfernen, bevor Sie den Feldtyp ändern.

Joe Taras
quelle
40
@ ManirajSS: ALTER TABLE yourtable DROP CONSTRAINT DF_Movies_Rating__48CFD27E
Joe Taras
18
Was hat die Erstellung der Einschränkung ausgelöst? Ich habe ein paar davon und ich will sie wirklich nicht!
Simon Parker
5
Hmm, und was tun, wenn ich dort DB-Migrationen meines Frameworks (Laravel) und dropColumn verwenden möchte? Ich habe keine Ahnung, wie ich die Einschränkung
löschen soll,
2
Ich bin mir sicher: Ich habe es gelöscht und der Ordner Constraints wird leer. Wenn ich die Anwendung ausführe oder update-databasesie erneut aufrufe, habe
mshwf
2
Warum zum Teufel lässt SQLServer das Contraint nicht implizit fallen? Es hat es doch implizit geschaffen!
youcantryreachingme
46

Das ist der tsqlWeg

 ALTER TABLE yourtable DROP CONSTRAINT constraint_name     -- DF_Movies_Rating__48CFD27E

Der Vollständigkeit halber zeigt dies nur den Kommentar von @Joe Taras als Antwort

Luis Siquot
quelle
46

Ich füge dies als Antwort hinzu, um zu erklären, woher die Einschränkung kommt. Ich habe versucht, es in den Kommentaren zu tun, aber es ist schwer, es dort gut zu bearbeiten: - /

Wenn Sie eine Tabelle mit einer Spalte mit Standardwerten erstellen (oder ändern), wird die Einschränkung für Sie erstellt.

In Ihrer Tabelle könnte es zum Beispiel sein:

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

Dadurch wird die Einschränkung für Standard 100 erstellt.

Wenn Sie es stattdessen so erstellen

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

Dann erhalten Sie eine gut benannte Einschränkung, auf die Sie beim Ändern dieser Tabelle leichter verweisen können.

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;

Sie können diese letzten beiden Anweisungen kombinieren, um die Spalte zu ändern und die Einschränkung in einer Zeile zu benennen (Sie müssen dies tun, wenn es sich sowieso um eine vorhandene Tabelle handelt).

h3adache
quelle
Vielen Dank, dass Sie Informationen hinzugefügt haben, wie Sie das Problem vermeiden können, indem Sie zunächst alle Einschränkungen benennen. (Das heißt, vermeiden Sie das Problem, zufällig benannte Einschränkungen zu
löschen
22

Da die Einschränkung einen unvorhersehbaren Namen hat, können Sie ein spezielles Skript ( DropConstraint ) schreiben , um sie zu entfernen, ohne den Namen zu kennen (wurde in EF 6.1.3 getestet):

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
quelle
Diese Antwort funktioniert hervorragend in einer migrationsbasierten Umgebung, in der Sie es sich nicht leisten können, den Namen einer Einschränkung fest zu codieren.
Menion Leah
Wenn Sie eine Wrapper- / Erweiterungs- / Überlastungsfunktion für AlterColumn erstellen - wie AlterColumnX -, können Sie diese DropConstraint-Logik dort einfügen - und Sie können den Tabellennamen und den Spaltennamen übergeben, damit Sie sie nicht erneut schreiben müssen.
N73k
10

MS SQL Studio kümmert sich darum, wann Sie die Spalte löschen. Wenn Sie jedoch die Einschränkung programmgesteuert löschen müssen, finden Sie hier eine einfache Lösung

Hier ist ein Code-Snippet, mit dem eine Spalte mit einer Standardeinschränkung gelöscht wird:

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

Ersetzen Sie einfach TableName und ColumnName durch die entsprechenden Werte. Sie können dies sicher ausführen, auch wenn die Spalte bereits gelöscht wurde.

Bonus : Hier ist der Code zum Löschen von Fremdschlüsseln und anderen Arten von Einschränkungen.

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_
quelle
1
hat mir jetzt zweimal das Leben gerettet. Beide müssen Prüfbeschränkungen löschen. Zuerst muss ich die erste Abfrage verwenden. Zweitens muss ich die zweite Abfrage verwenden, da die Prüfbedingung nicht in der Tabelle SYS.DEFAULT_CONSTRAINTS gefunden wurde. Vielen Dank!
Sonntag,
8

Wenn wir versuchen, eine Spalte zu löschen, von der abhängig ist, sehen wir diese Art von Fehler:

Das Objekt 'DF __ *' ist abhängig von der Spalte ''.

Löschen Sie die von dieser Spalte abhängige Einschränkung mit:

ALTER TABLE TableName DROP CONSTRAINT dependent_constraint;

Beispiel:

Nachricht 5074, Ebene 16, Status 1, Zeile 1

Das Objekt ' DF__Employees__Colf__1273C1CD' ist abhängig von der Spalte 'Colf'.

Nachricht 4922, Ebene 16, Status 9, Zeile 1

ALTER TABLE DROP COLUMN Colf ist fehlgeschlagen, weil ein oder mehrere Objekte auf diese Spalte zugreifen.

Drop Constraint (DF__Employees__Colf__1273C1CD):

ALTER TABLE Employees DROP CONSTRAINT DF__Employees__Colf__1273C1CD;

Dann können Sie die Spalte löschen:

Alter Table TableName Drop column ColumnName
Jinna Balu
quelle
1

Lösung:

Öffnen Sie die Datenbanktabelle -> erweitern Sie die Tabelle -> erweitern Sie die Einschränkungen und sehen Sie dies

Bildschirmfoto

Arup Mahapatra
quelle
Während dieser Code die Frage möglicherweise beantwortet, verbessert die Bereitstellung eines zusätzlichen Kontexts darüber, warum und / oder wie dieser Code die Frage beantwortet, ihren langfristigen Wert.
Donald Duck
-1

Ich hatte diesen Fehler beim Versuch, eine Migration auszuführen, um sie zu umgehen. Ich habe die Spalte umbenannt und die Migration mit neu generiert

add-migration migrationname -force

in der Paketmanager-Konsole. Ich konnte dann rennen

update-database

erfolgreich.

Kirsten Gier
quelle
2
Seien Sie vorsichtig, dies benennt keine Spalte um - es löscht die Spalte und fügt eine neue Spalte hinzu. Sie verlieren alle Daten, die früher in der Spalte vorhanden waren, es sei denn, Sie fügen der Migration benutzerdefinierten Code hinzu.
Caesay