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?


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.


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


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)


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

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


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

1

Rozwiązanie :

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

zrzut ekranu


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.


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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.