Objek 'DF __ *' tergantung pada kolom '*' - Mengubah int menjadi ganda

168

Pada dasarnya saya mendapat tabel di basis data EF saya dengan properti berikut:

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

Namun berfungsi dengan baik ketika saya mengubah int dari Rating menjadi dua kali lipat saya mendapatkan kesalahan berikut saat memperbarui database:

Objek 'DF_ Movies _Rating__48CFD27E' tergantung pada kolom 'Rating'. ALTER TABLE ALTER COLUMN Peringkat gagal karena satu atau lebih objek mengakses kolom ini.

apa masalahnya?

Jordan Axe
sumber
1
Hapus kendala DF_Movies_Rating__48CFD27E dan kemudian ubah jenis bidang Anda
Joe Taras
@ JoTaras Tapi saya belum pernah membuat batasan bernama itu. Apa itu dan di mana saya menemukannya?
Jordan Axe
2
Ketika Anda membuat bidang, DBMS secara otomatis membuat kendala. Jika Anda memperluas info tabel Anda, di bagian kendala Anda akan menemukannya. Katakan padaku jika Anda akan menemukan;)
Joe Taras

Jawaban:

252

Coba ini:

Hapus kendala DF_Movies_Rating__48CFD27E sebelum mengubah jenis bidang Anda.

Batasan biasanya dibuat secara otomatis oleh DBMS (SQL Server).

Untuk melihat kendala yang terkait dengan tabel, perluas atribut tabel di Object explorer , diikuti oleh kategori Kendala seperti yang ditunjukkan di bawah ini:

Pohon meja Anda

Anda harus menghapus kendala sebelum mengubah jenis bidang.

Joe Taras
sumber
40
@ManirajSS: ALTER TABLE yourtable DROP CONSTRAINT DF_Movies_Rating__48CFD27E
Joe Taras
18
Apa yang memicu terciptanya kendala? Saya memiliki banyak dari mereka, dan saya benar-benar tidak menginginkannya!
Simon Parker
5
Hmm, dan apa yang harus saya lakukan jika saya ingin menggunakan migrasi DB dari framework saya (Laravel) dan dropColumn di sana? Saya tidak tahu bagaimana cara menghilangkan kendala yang memiliki nama misterius, di-autogenerasi oleh SQL server :(
JustAMartin
2
Saya yakin: Saya menjatuhkannya dan folder Kendala menjadi kosong, dan ketika saya menjalankan aplikasi atau memanggilnya membuat update-databaseulang lagi saya memposting masalah ini: stackoverflow.com/questions/40267769/…
mshwf
2
Kenapa sih SQLServer tidak menjatuhkan contraint secara implisit? Lagi pula, itu membuatnya secara implisit!
youcantryreachingme
46

Inilah tsqlcaranya

 ALTER TABLE yourtable DROP CONSTRAINT constraint_name     -- DF_Movies_Rating__48CFD27E

Untuk kelengkapan, ini hanya menunjukkan komentar @ Jo Taras sebagai jawaban

Luis Siquot
sumber
46

Saya menambahkan ini sebagai jawaban untuk menjelaskan dari mana kendala berasal. Saya mencoba melakukannya di komentar tetapi sulit untuk mengedit dengan baik di sana: - /

Jika Anda membuat (atau mengubah) tabel dengan kolom yang memiliki nilai default, itu akan membuat kendala untuk Anda.

Di meja Anda, misalnya, mungkin:

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

Ini akan membuat batasan untuk default 100.

Jika Anda malah membuatnya seperti itu

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

Kemudian Anda mendapatkan batasan nama yang bagus yang lebih mudah untuk referensi ketika Anda mengubah tabel tersebut.

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;

Anda dapat menggabungkan 2 pernyataan terakhir itu sehingga Anda mengubah kolom dan memberi nama kendala dalam satu baris (Anda harus melakukannya jika itu adalah tabel yang sudah ada)

h3adache
sumber
Terima kasih telah menambahkan info tentang cara menghindari masalah dengan menyebutkan semua kendala di tempat pertama. (Yaitu, hindari masalah menjatuhkan batasan yang disebutkan secara acak)
youcantryreachingme
22

Karena constraint memiliki nama yang tidak dapat diprediksi, Anda dapat menulis skrip khusus ( DropConstraint ) untuk menghapusnya tanpa mengetahui namanya (diuji di 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
sumber
Jawaban ini berfungsi baik di lingkungan berbasis migrasi di mana Anda tidak mampu membayar nama kendala hardcode.
Menion Leah
Jika Anda membuat fungsi pembungkus / ekstensi / kelebihan beban untuk AlterColumn - seperti AlterColumnX - Anda dapat menyertakan logika DropConstraint di sana - dan Anda bisa memasukkan nama tabel & nama kolom sehingga Anda tidak perlu menulisnya lagi.
N73k
10

MS SQL Studio berhati-hati ketika Anda menghapus kolom tetapi jika Anda perlu Hapus Batasan Secara program di sini adalah solusi sederhana

Berikut cuplikan kode yang akan menjatuhkan kolom dengan batasan default:

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

Cukup ganti TableName dan ColumnName dengan nilai yang sesuai. Anda dapat menjalankan ini dengan aman bahkan jika kolom sudah dijatuhkan.

Bonus : Inilah kode untuk menjatuhkan kunci asing dan jenis kendala lainnya.

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_
sumber
1
menyelamatkan hidup saya dua kali sekarang. Keduanya, harus menghapus batasan pemeriksaan. Pertama-tama saya harus menggunakan permintaan pertama. Kedua, saya harus menggunakan kueri kedua karena kendala pemeriksaan tidak ditemukan di tabel SYS.DEFAULT_CONSTRAINTS. Terima kasih banyak!
Minggu
8

Ketika kami mencoba untuk menjatuhkan kolom yang diandalkan maka kita melihat kesalahan semacam ini:

Objek 'DF __ *' tergantung pada kolom ''.

jatuhkan batasan yang bergantung pada kolom itu dengan:

ALTER TABLE TableName DROP CONSTRAINT dependent_constraint;

Contoh:

Msg 5074, Level 16, Negara Bagian 1, Baris 1

Objek ' DF__Employees__Colf__1273C1CD' tergantung pada kolom 'Colf'.

Msg 4922, Level 16, Negara 9, Baris 1

ALTER TABLE DROP COLUMN Colf gagal karena satu atau lebih objek mengakses kolom ini.

Jatuhkan Kendala (DF__Employees__Colf__1273C1CD):

ALTER TABLE Employees DROP CONSTRAINT DF__Employees__Colf__1273C1CD;

Maka Anda dapat Drop Kolom:

Alter Table TableName Drop column ColumnName
Jinna Balu
sumber
1

Solusi:

buka tabel database -> rentangkan tabel -> rentangkan kendala dan lihat ini

tangkapan layar

Arup Mahapatra
sumber
Sementara kode ini dapat menjawab pertanyaan, memberikan konteks tambahan tentang mengapa dan / atau bagaimana kode ini menjawab pertanyaan meningkatkan nilai jangka panjangnya.
Donald Duck
-1

Saya mengalami kesalahan ini ketika mencoba menjalankan migrasi untuk mengatasinya. Saya mengganti nama kolom dan membuat ulang migrasi menggunakan

add-migration migrationname -force

di konsol manajer paket. Saya kemudian bisa berlari

update-database

berhasil.

Kirsten Greed
sumber
2
Hati-hati, ini tidak mengganti nama kolom - itu menjatuhkan kolom dan menambahkan kolom baru. Anda akan kehilangan data apa pun yang dulu ada di kolom kecuali jika Anda menambahkan kode khusus dalam migrasi.
caesay