Obiekt „DF __ *” jest zależny od kolumny „*” - Zmiana int na double

168

Zasadniczo mam tabelę w mojej bazie danych EF z następującymi właściwościami:

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

Działa dobrze, jednak gdy zmieniam wartość int Rating na podwójną, podczas aktualizacji bazy danych pojawia się następujący błąd:

Obiekt „DF_ Movies _Rating__48CFD27E” zależy od kolumny „Rating”. ALTER TABLE ALTER COLUMN Ocena nie powiodła się, ponieważ co najmniej jeden obiekt uzyskuje dostęp do tej kolumny.

W czym problem?

Jordan Axe
źródło
1
Usuń ograniczenie DF_Movies_Rating__48CFD27E, a następnie zmień typ pola
Joe Taras
@JoeTaras Ale nigdy nie stworzyłem ograniczenia o takiej nazwie. Co to jest i gdzie to znajdę?
Jordan Axe,
2
Podczas tworzenia pola DBMS tworzy automatycznie ograniczenie. Jeśli rozszerzysz informacje o tabeli, w sekcji ograniczeń znajdziesz je. Powiedz mi, czy znajdziesz;)
Joe Taras

Odpowiedzi:

252

Spróbuj tego:

Usuń ograniczenie DF_Movies_Rating__48CFD27E przed zmianą typu pola.

Ograniczenie jest zwykle tworzone automatycznie przez DBMS (SQL Server).

Aby zobaczyć ograniczenie skojarzone z tabelą, rozwiń atrybuty tabeli w Eksploratorze obiektów , a następnie kategorię Ograniczenia, jak pokazano poniżej:

Drzewo Twojego stołu

Przed zmianą typu pola należy usunąć ograniczenie.

Joe Taras
źródło
40
@ManirajSS: ALTER TABLE yourtable DROP CONSTRAINT DF_Movies_Rating__48CFD27E
Joe Taras
18
Co spowodowało powstanie ograniczenia? Mam ich sporo i naprawdę ich nie chcę!
Simon Parker
5
Hmm, a co zrobić, jeśli chcę użyć migracji DB mojego frameworka (Laravel) i tam dropColumn? Nie mam pojęcia, jak usunąć ograniczenie, które ma tajemniczą nazwę, generowane automatycznie przez serwer SQL :(
JustAMartin
2
Jestem pewien: upuściłem go i folder Constraints staje się pusty, a kiedy uruchomię aplikację lub update-database
wywołam
2
Dlaczego, u licha, SQLServer nie porzuca ograniczenia niejawnie? W końcu stworzył go pośrednio!
youcantryreachingme
46

To jest tsqldroga

 ALTER TABLE yourtable DROP CONSTRAINT constraint_name     -- DF_Movies_Rating__48CFD27E

Aby uzyskać kompletność, jako odpowiedź pokazuje tylko komentarz @Joe Taras

Luis Siquot
źródło
46

Dodam to jako odpowiedź, aby wyjaśnić, skąd pochodzi ograniczenie. Próbowałem to zrobić w komentarzach, ale tam ciężko jest ładnie edytować: - /

Jeśli utworzysz (lub zmienisz) tabelę z kolumną, która ma wartości domyślne, utworzy ograniczenie za Ciebie.

Na przykład w Twojej tabeli może to być:

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

Utworzy ograniczenie dla domyślnych 100.

Jeśli zamiast tego utworzysz go w ten sposób

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

Następnie otrzymujesz ładnie nazwane ograniczenie, które jest łatwiejsze do odniesienia, gdy zmieniasz wspomnianą tabelę.

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;

Możesz połączyć te ostatnie 2 instrukcje, aby zmienić kolumnę i nazwać ograniczenie w jednej linii (musisz to zrobić, jeśli i tak jest to istniejąca tabela)

h3adache
źródło
Dziękujemy za dodanie informacji o tym, jak uniknąć problemu, nadając nazwy wszystkim ograniczeniom. (To znaczy unikaj problemu zrzucania losowo nazwanych ograniczeń)
youcantryreachingme
22

Ponieważ ograniczenie ma nieprzewidywalną nazwę, możesz napisać specjalny skrypt ( DropConstraint ), aby go usunąć bez znajomości jego nazwy (zostało przetestowane w 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
źródło
Ta odpowiedź działa świetnie w środowisku opartym na migracji, w którym nie możesz sobie pozwolić na sztywne kodowanie nazwy ograniczenia.
Menion Leah
Jeśli utworzysz funkcję opakowującą / rozszerzającą / przeciążoną dla AlterColumn - taką jak AlterColumnX - możesz dołączyć tam logikę DropConstraint - i możesz przekazać nazwę tabeli i nazwę kolumny, aby nie trzeba było ich ponownie pisać.
N73k
10

MS SQL Studio zajmie się usunięciem kolumny, ale jeśli chcesz programowo usunąć ograniczenie, tutaj jest proste rozwiązanie

Oto fragment kodu, który usunie kolumnę z domyślnym ograniczeniem:

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

Wystarczy zastąpić TableName i NazwaKolumny z odpowiednimi wartościami. Możesz to bezpiecznie uruchomić, nawet jeśli kolumna została już upuszczona.

Bonus : Oto kod do usuwania kluczy obcych i innych typów ograniczeń.

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_
źródło
1
dwukrotnie uratował mi życie. Obie z nich, muszą usunąć ograniczenia sprawdzające. Przede wszystkim muszę użyć pierwszego zapytania. Po drugie, muszę użyć drugiego zapytania, ponieważ ograniczenie sprawdzające nie zostało znalezione w tabeli SYS.DEFAULT_CONSTRAINTS. Wielkie dzięki!
niedziela
8

Kiedy próbujemy usunąć kolumnę, od której zależy, widzimy taki błąd:

Obiekt „DF __ *” jest zależny od kolumny „”.

usuń ograniczenie, które jest zależne od tej kolumny:

ALTER TABLE TableName DROP CONSTRAINT dependent_constraint;

Przykład:

Msg 5074, poziom 16, stan 1, wiersz 1

Obiekt „ DF__Employees__Colf__1273C1CD” jest zależny od kolumny „Colf”.

Msg 4922, poziom 16, stan 9, wiersz 1

ALTER TABLE DROP COLUMN Colf nie powiódł się, ponieważ co najmniej jeden obiekt uzyskuje dostęp do tej kolumny.

Porzuć ograniczenie (DF__Employees__Colf__1273C1CD):

ALTER TABLE Employees DROP CONSTRAINT DF__Employees__Colf__1273C1CD;

Następnie możesz upuścić kolumnę:

Alter Table TableName Drop column ColumnName
Jinna Balu
źródło
1

Rozwiązanie :

otwórz tabelę bazy danych -> rozwiń tabelę -> rozwiń ograniczenia i zobacz to

zrzut ekranu

Arup Mahapatra
źródło
Chociaż ten kod może odpowiedzieć na pytanie, zapewnia dodatkowy kontekst dotyczący tego, dlaczego i / lub jak ten kod odpowiada, poprawia jego długoterminową wartość.
Kaczor Donald
-1

Wystąpił ten błąd podczas próby uruchomienia migracji w celu obejścia tego problemu. Zmieniłem nazwę kolumny i ponownie wygenerowałem migrację przy użyciu

add-migration migrationname -force

w konsoli menedżera pakietów. Wtedy mogłem biegać

update-database

z powodzeniem.

Kirsten Greed
źródło
2
Uważaj, to nie zmienia nazwy kolumny - usuwa kolumnę i dodaje nową. Utracisz wszystkie dane, które istniały w kolumnie, chyba że dodasz niestandardowy kod podczas migracji.
caesay