Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Entity Framework Core (EF Core) mewakili hubungan menggunakan kunci asing. Entitas dengan kunci asing adalah entitas anak atau dependen dalam hubungan. Nilai kunci asing entitas ini harus cocok dengan nilai kunci utama (atau nilai kunci alternatif) dari entitas utama/induk terkait.
Jika entitas utama/induk dihapus, nilai kunci asing dari entitas bergantung/anak tidak akan lagi sesuai dengan kunci utama atau kunci alternatif dari entitas utama/induk mana pun. Ini adalah status yang tidak valid, dan akan menyebabkan pelanggaran batasan referensial di sebagian besar database.
Ada dua opsi untuk menghindari pelanggaran batasan referensial ini:
- Atur nilai FK ke null
- Hapus juga entitas dependen/anak
Opsi pertama hanya valid untuk hubungan opsional di mana properti kunci asing (dan kolom basis data yang dipetakan) harus dapat bernilai null.
Opsi kedua dapat diterapkan pada semua jenis hubungan dan dikenal sebagai "penghapusan kaskade".
Petunjuk / Saran
Dokumen ini menjelaskan penghapusan bertingkat (dan menghapus yatim piatu) dari perspektif pembaruan database. Ini memanfaatkan secara berat konsep yang diperkenalkan dalam Pelacakan Perubahan dalam EF Core dan Perubahan Kunci Asing dan Navigasi. Pastikan untuk sepenuhnya memahami konsep-konsep ini sebelum menangani materi di sini.
Petunjuk / Saran
Anda dapat menjalankan dan men-debug ke semua kode dalam dokumen ini dengan mengunduh kode sampel dari GitHub.
Saat perilaku berantai terjadi
Penghapusan berjenjang diperlukan ketika entitas dependen atau anak tidak dapat lagi dikaitkan dengan entitas utama atau induknya saat ini. Ini dapat terjadi karena prinsipal/induk dihapus, atau dapat terjadi ketika prinsipal/induk masih ada tetapi dependen/anak tidak lagi terkait dengannya.
Menghapus prinsipal atau induk
Pertimbangkan model sederhana ini di mana Blog
adalah prinsipal/induk dalam hubungan dengan Post
, yang merupakan dependen/anak.
Post.BlogId
adalah properti kunci asing, nilai yang harus cocok dengan Blog.Id
kunci utama blog tempat posting berada.
public class Blog
{
public int Id { get; set; }
public string Name { get; set; }
public IList<Post> Posts { get; } = new List<Post>();
}
public class Post
{
public int Id { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public int BlogId { get; set; }
public Blog Blog { get; set; }
}
Menurut konvensi, hubungan ini dikonfigurasi sebagai diperlukan, karena Post.BlogId
properti kunci asing tidak dapat diubah ke null. Hubungan yang diperlukan dikonfigurasi untuk menggunakan penghapusan kaskade secara default. Lihat Hubungan untuk informasi selengkapnya tentang hubungan pemodelan.
Saat menghapus blog, semua postingan dihapus secara bertingkat. Contohnya:
using var context = new BlogsContext();
var blog = await context.Blogs.OrderBy(e => e.Name).Include(e => e.Posts).FirstAsync();
context.Remove(blog);
await context.SaveChangesAsync();
SaveChanges menghasilkan SQL berikut, menggunakan SQL Server sebagai contoh:
-- Executed DbCommand (1ms) [Parameters=[@p0='1'], CommandType='Text', CommandTimeout='30']
SET NOCOUNT ON;
DELETE FROM [Posts]
WHERE [Id] = @p0;
SELECT @@ROWCOUNT;
-- Executed DbCommand (0ms) [Parameters=[@p0='2'], CommandType='Text', CommandTimeout='30']
SET NOCOUNT ON;
DELETE FROM [Posts]
WHERE [Id] = @p0;
SELECT @@ROWCOUNT;
-- Executed DbCommand (2ms) [Parameters=[@p1='1'], CommandType='Text', CommandTimeout='30']
SET NOCOUNT ON;
DELETE FROM [Blogs]
WHERE [Id] = @p1;
SELECT @@ROWCOUNT;
Memisahkan hubungan
Daripada menghapus blog, kita justru dapat mengalihkan hubungan antara setiap posting dan blognya. Ini dapat dilakukan dengan mengatur navigasi Post.Blog
referensi ke null untuk setiap posting:
using var context = new BlogsContext();
var blog = await context.Blogs.OrderBy(e => e.Name).Include(e => e.Posts).FirstAsync();
foreach (var post in blog.Posts)
{
post.Blog = null;
}
await context.SaveChangesAsync();
Hubungan juga dapat diputus dengan menghapus setiap postingan dari Blog.Posts
navigasi koleksi:
using var context = new BlogsContext();
var blog = await context.Blogs.OrderBy(e => e.Name).Include(e => e.Posts).FirstAsync();
blog.Posts.Clear();
await context.SaveChangesAsync();
Dalam kedua kasus, hasilnya sama: blog tidak dihapus, tetapi posting yang tidak lagi terkait dengan blog apa pun dihapus:
-- Executed DbCommand (1ms) [Parameters=[@p0='1'], CommandType='Text', CommandTimeout='30']
SET NOCOUNT ON;
DELETE FROM [Posts]
WHERE [Id] = @p0;
SELECT @@ROWCOUNT;
-- Executed DbCommand (0ms) [Parameters=[@p0='2'], CommandType='Text', CommandTimeout='30']
SET NOCOUNT ON;
DELETE FROM [Posts]
WHERE [Id] = @p0;
SELECT @@ROWCOUNT;
Menghapus elemen yang tidak lagi terhubung dengan elemen utama atau pendukung dikenal sebagai "menghapus elemen yatim piatu".
Petunjuk / Saran
Penghapusan kaskade dan penghapusan yatim piatu terkait erat. Keduanya mengakibatkan penghapusan entitas turunan atau anak ketika hubungan dengan entitas utama atau induk yang dibutuhkan terputus. Untuk penghapusan berjenjang, pemisahan ini terjadi karena pengelola/induk itu sendiri dihapus. Untuk yatim piatu, entitas utama/induk masih ada, tetapi tidak lagi terkait dengan entitas dependen/anak.
Di mana perilaku berantai terjadi
Perilaku bertingkat dapat diterapkan ke:
- Entitas yang saat ini dilacak oleh DbContext
- Entitas dalam database yang belum dimuat ke dalam konteks
Penghapusan berurutan entitas yang dilacak
EF Core selalu menerapkan perilaku bertingkat yang dikonfigurasi ke entitas yang dilacak. Ini berarti bahwa jika aplikasi memuat semua entitas dependen/anak yang relevan ke dalam DbContext, seperti yang ditunjukkan pada contoh di atas, maka perilaku berjenjang akan diterapkan dengan benar terlepas dari bagaimana database dikonfigurasi.
Petunjuk / Saran
Waktu yang tepat ketika perilaku bertingkat terjadi pada entitas yang dilacak dapat dikontrol menggunakan ChangeTracker.CascadeDeleteTiming dan ChangeTracker.DeleteOrphansTiming. Lihat Mengubah Kunci Asing dan Navigasi untuk informasi selengkapnya.
Penghapusan beruntun dalam database
Banyak sistem database juga menawarkan perilaku berskala yang dipicu ketika entitas dihapus dalam database. EF Core mengonfigurasi perilaku ini berdasarkan perilaku penghapusan kaskade dalam model EF Core saat database dibuat menggunakan EnsureCreated atau migrasi EF Core. Misalnya, menggunakan model di atas, tabel berikut dibuat untuk postingan saat menggunakan SQL Server:
CREATE TABLE [Posts] (
[Id] int NOT NULL IDENTITY,
[Title] nvarchar(max) NULL,
[Content] nvarchar(max) NULL,
[BlogId] int NOT NULL,
CONSTRAINT [PK_Posts] PRIMARY KEY ([Id]),
CONSTRAINT [FK_Posts_Blogs_BlogId] FOREIGN KEY ([BlogId]) REFERENCES [Blogs] ([Id]) ON DELETE CASCADE
);
Perhatikan bahwa batasan kunci asing yang menentukan hubungan antara blog dan posting dikonfigurasi dengan ON DELETE CASCADE
.
Jika kita tahu bahwa database dikonfigurasi seperti ini, maka kita dapat menghapus blog tanpa terlebih dahulu memuat posting dan database akan mengurus penghapusan semua posting yang terkait dengan blog tersebut. Contohnya:
using var context = new BlogsContext();
var blog = await context.Blogs.OrderBy(e => e.Name).FirstAsync();
context.Remove(blog);
await context.SaveChangesAsync();
Perhatikan bahwa Include
tidak ada untuk posting, dan karena itu, posting tidak dimuat. SaveChanges dalam hal ini hanya akan menghapus blog, karena itulah satu-satunya entitas yang dilacak:
-- Executed DbCommand (6ms) [Parameters=[@p0='1'], CommandType='Text', CommandTimeout='30']
SET NOCOUNT ON;
DELETE FROM [Blogs]
WHERE [Id] = @p0;
SELECT @@ROWCOUNT;
Ini akan mengakibatkan pengecualian jika batasan kunci asing dalam database tidak dikonfigurasi untuk penghapusan kaskade. Namun, dalam hal ini posting dihapus oleh database karena telah dikonfigurasi dengan ON DELETE CASCADE
saat dibuat.
Nota
Database biasanya tidak memiliki cara untuk menghapus yatim piatu secara otomatis. Ini karena sementara EF Core mewakili hubungan menggunakan navigasi serta kunci asing, database hanya memiliki kunci asing dan tidak ada navigasi. Ini berarti bahwa biasanya tidak mungkin untuk memutuskan hubungan tanpa memuat kedua sisi ke dalam DbContext.
Nota
Database in-memory EF Core saat ini tidak mendukung penghapusan kaskade di dalam basis data.
Peringatan
Jangan mengonfigurasi penghapusan berantai di dalam database saat menghapus entitas secara lembut. Ini dapat menyebabkan entitas secara tidak sengaja dihapus permanen alih-alih dihapus lembut.
Batasan database cascade
Beberapa database, terutama SQL Server, memiliki batasan pada perilaku bertingkat yang membentuk siklus. Misalnya, pertimbangkan model berikut:
public class Blog
{
public int Id { get; set; }
public string Name { get; set; }
public IList<Post> Posts { get; } = new List<Post>();
public int OwnerId { get; set; }
public Person Owner { get; set; }
}
public class Post
{
public int Id { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public int BlogId { get; set; }
public Blog Blog { get; set; }
public int AuthorId { get; set; }
public Person Author { get; set; }
}
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public IList<Post> Posts { get; } = new List<Post>();
public Blog OwnedBlog { get; set; }
}
Model ini memiliki tiga hubungan, semuanya diperlukan dan oleh karena itu dikonfigurasi untuk menghapus bertahap menurut konvensi:
- Menghapus blog akan menghapus semua posting terkait
- Menghapus penulis postingan akan menyebabkan postingan yang ditulis dihapus secara bertingkat
- Menghapus pemilik blog akan menyebabkan blog dihapus secara kaskade
Semua ini masuk akal (meskipun kebijakan manajemen blog cukup ketat!) tetapi ketika mencoba untuk membuat database SQL Server dengan kaskade yang dikonfigurasi ini, akan menghasilkan pengecualian berikut:
Microsoft.Data.SqlClient.SqlException (0x80131904): Memperkenalkan batasan KUNCI ASING 'FK_Posts_Person_AuthorId' pada tabel 'Posts' dapat menyebabkan siklus atau beberapa jalur kaskade. Tentukan ON DELETE NO ACTION atau ON UPDATE NO ACTION, atau ubah batasan KUNCI ASING lainnya.
Ada dua cara untuk menangani situasi ini:
- Ubah satu atau beberapa hubungan agar tidak melakukan penghapusan berurutan.
- Konfigurasikan database tanpa satu atau beberapa penghapusan bertingkat ini, lalu pastikan semua entitas dependen dimuat sehingga EF Core dapat melakukan perilaku bertingkat.
Menggunakan pendekatan pertama dengan contoh kami, kita dapat menjadikan hubungan pasca-blog bersifat opsional dengan memberinya properti kunci asing yang dapat bernilai null.
public int? BlogId { get; set; }
Hubungan opsional memungkinkan postingan ada tanpa blog, yang berarti penghapusan bertingkat tidak akan lagi dikonfigurasi secara default. Ini berarti tidak ada lagi siklus dalam tindakan berkala, dan database dapat dibuat tanpa kesalahan di SQL Server.
Dengan mengambil pendekatan kedua, kita dapat menjaga hubungan pemilik blog yang diperlukan dan dikonfigurasi untuk penghapusan bertingkat, tetapi membuat konfigurasi ini hanya berlaku untuk entitas yang dilacak, bukan database:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder
.Entity<Blog>()
.HasOne(e => e.Owner)
.WithOne(e => e.OwnedBlog)
.OnDelete(DeleteBehavior.ClientCascade);
}
Sekarang apa yang terjadi jika kita memuat seseorang dan blog yang mereka miliki, lalu menghapus orang tersebut?
using var context = new BlogsContext();
var owner = await context.People.SingleAsync(e => e.Name == "ajcvickers");
var blog = await context.Blogs.SingleAsync(e => e.Owner == owner);
context.Remove(owner);
await context.SaveChangesAsync();
EF Core akan menghapus secara berjenjang pada pemilik sehingga blog juga dihapus.
-- Executed DbCommand (8ms) [Parameters=[@p0='1'], CommandType='Text', CommandTimeout='30']
SET NOCOUNT ON;
DELETE FROM [Blogs]
WHERE [Id] = @p0;
SELECT @@ROWCOUNT;
-- Executed DbCommand (2ms) [Parameters=[@p1='1'], CommandType='Text', CommandTimeout='30']
SET NOCOUNT ON;
DELETE FROM [People]
WHERE [Id] = @p1;
SELECT @@ROWCOUNT;
Namun, jika blog tidak dimuat ketika pemilik dihapus:
using var context = new BlogsContext();
var owner = await context.People.SingleAsync(e => e.Name == "ajcvickers");
context.Remove(owner);
await context.SaveChangesAsync();
Kemudian pengecualian akan dilemparkan karena pelanggaran batasan kunci asing dalam database:
Microsoft.Data.SqlClient.SqlException: Pernyataan DELETE bertentangan dengan batasan REFERENSI "FK_Blogs_People_OwnerId". Konflik terjadi dalam database "Scratch", tabel "dbo. Blogs", kolom 'OwnerId'. Pernyataan ini telah dihapus.
Nilai null berurutan
Hubungan opsional memiliki properti kunci asing null yang dipetakan ke kolom database nullable. Ini berarti bahwa nilai kunci asing dapat diatur ke null ketika entitas utama/induk saat ini dihapus atau hubungan dengan dependen/anak diputus.
Mari kita lihat lagi contoh dari Ketika perilaku berjenjang terjadi, tetapi kali ini dengan hubungan opsional yang diwakili oleh properti kunci asing yang bersifat null:
public int? BlogId { get; set; }
Properti kunci asing ini akan diatur ke null untuk setiap postingan ketika blog terkait dihapus. Misalnya, kode ini, yang sama seperti sebelumnya:
using var context = new BlogsContext();
var blog = await context.Blogs.OrderBy(e => e.Name).Include(e => e.Posts).FirstAsync();
context.Remove(blog);
await context.SaveChangesAsync();
Sekarang akan menghasilkan pembaruan database berikut ketika SaveChanges dipanggil:
-- Executed DbCommand (2ms) [Parameters=[@p1='1', @p0=NULL (DbType = Int32)], CommandType='Text', CommandTimeout='30']
SET NOCOUNT ON;
UPDATE [Posts] SET [BlogId] = @p0
WHERE [Id] = @p1;
SELECT @@ROWCOUNT;
-- Executed DbCommand (0ms) [Parameters=[@p1='2', @p0=NULL (DbType = Int32)], CommandType='Text', CommandTimeout='30']
SET NOCOUNT ON;
UPDATE [Posts] SET [BlogId] = @p0
WHERE [Id] = @p1;
SELECT @@ROWCOUNT;
-- Executed DbCommand (1ms) [Parameters=[@p2='1'], CommandType='Text', CommandTimeout='30']
SET NOCOUNT ON;
DELETE FROM [Blogs]
WHERE [Id] = @p2;
SELECT @@ROWCOUNT;
Demikian juga, jika hubungan terputus menggunakan salah satu contoh dari atas:
using var context = new BlogsContext();
var blog = await context.Blogs.OrderBy(e => e.Name).Include(e => e.Posts).FirstAsync();
foreach (var post in blog.Posts)
{
post.Blog = null;
}
await context.SaveChangesAsync();
Atau:
using var context = new BlogsContext();
var blog = await context.Blogs.OrderBy(e => e.Name).Include(e => e.Posts).FirstAsync();
blog.Posts.Clear();
await context.SaveChangesAsync();
Kemudian postingan diperbarui dengan nilai kunci asing null saat SaveChanges dipanggil:
-- Executed DbCommand (2ms) [Parameters=[@p1='1', @p0=NULL (DbType = Int32)], CommandType='Text', CommandTimeout='30']
SET NOCOUNT ON;
UPDATE [Posts] SET [BlogId] = @p0
WHERE [Id] = @p1;
SELECT @@ROWCOUNT;
-- Executed DbCommand (0ms) [Parameters=[@p1='2', @p0=NULL (DbType = Int32)], CommandType='Text', CommandTimeout='30']
SET NOCOUNT ON;
UPDATE [Posts] SET [BlogId] = @p0
WHERE [Id] = @p1;
SELECT @@ROWCOUNT;
Lihat Mengubah Kunci Asing dan Navigasi untuk informasi selengkapnya tentang cara EF Core mengelola kunci asing dan navigasi saat nilainya diubah.
Nota
Perbaikan hubungan seperti ini telah menjadi perilaku default Kerangka Kerja Entitas sejak versi pertama pada 2008. Sebelum EF Core tidak memiliki nama dan tidak mungkin diubah. Sekarang dikenal sebagai ClientSetNull
seperti dijelaskan di bagian berikutnya.
Basis data juga dapat dikonfigurasi untuk menghapus nilai null seperti ini ketika prinsipal/induk dalam hubungan opsional dihapus. Namun, ini jauh kurang umum daripada menggunakan penghapusan berskala dalam database. Menggunakan penghapusan berjenjang dan null berjenjang dalam database secara bersamaan hampir selalu mengakibatkan siklus relasi saat menggunakan SQL Server. Lihat bagian berikutnya untuk informasi selengkapnya tentang mengonfigurasi null bertingkat.
Mengonfigurasi perilaku bertingkat
Petunjuk / Saran
Pastikan untuk membaca bagian di atas sebelum datang ke sini. Opsi konfigurasi kemungkinan tidak akan masuk akal jika materi sebelumnya tidak dipahami.
Perilaku kaskade dikonfigurasi per hubungan menggunakan metode OnDelete di OnModelCreating. Contohnya:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder
.Entity<Blog>()
.HasOne(e => e.Owner)
.WithOne(e => e.OwnedBlog)
.OnDelete(DeleteBehavior.ClientCascade);
}
Lihat Hubungan untuk informasi selengkapnya tentang mengonfigurasi hubungan antar jenis entitas.
OnDelete
menerima nilai dari enum DeleteBehavior yang diakui membingungkan. Enum ini mendefinisikan perilaku EF Core pada entitas yang dilacak, dan konfigurasi penghapusan bertingkat dalam database ketika EF digunakan untuk membuat skema.
Dampak pada skema database
Tabel berikut menunjukkan hasil dari setiap nilai OnDelete
pada batasan kunci asing yang dibuat oleh migrasi EF Core atau EnsureCreated.
DeleteBehavior | Dampak pada skema database |
---|---|
Air terjun | ON DELETE CASCADE (Hapus dengan Caleburan) |
Membatasi | PADA HAPUS BATASAN |
TidakAdaTindakan | default database |
SetNull | Saat Dihapus Tetapkan ke NULL |
ClientSetNull | default database |
ClientCascade | default database |
ClientNoAction | default database |
Perilaku ON DELETE NO ACTION
(default database) dan ON DELETE RESTRICT
dalam database relasional biasanya identik atau sangat mirip. Terlepas dari apa yang NO ACTION
mungkin menyiratkan, kedua opsi ini menyebabkan kendala referensial diberlakukan. Perbedaannya, ketika ada, adalah ketika database memeriksa batasan. Periksa dokumentasi database Anda untuk mengetahui perbedaan spesifik antara ON DELETE NO ACTION
dan ON DELETE RESTRICT
pada sistem database Anda.
SQL Server tidak mendukung ON DELETE RESTRICT
, jadi ON DELETE NO ACTION
digunakan sebagai gantinya.
Satu-satunya nilai yang akan menyebabkan perilaku berskala pada database adalah Cascade
dan SetNull
. Semua nilai lain akan mengonfigurasi database untuk tidak meneruskan perubahan apa pun.
Dampak pada perilaku SaveChanges
Tabel di bagian berikut mencakup apa yang terjadi pada entitas dependen/anak ketika prinsipal/induk dihapus, atau hubungannya dengan entitas dependen/anak terputus. Setiap tabel mencakup salah satu dari:
- Hubungan opsional (FK dapat bernilai null) dan wajib (FK tidak dapat bernilai null)
- Ketika anggota keluarga yang menjadi tanggungan/anak-anak diinisialisasi dan dipantau oleh DbContext dan ketika mereka hanya ada di database
Hubungan yang diperlukan dengan dependen/anak dimuat
DeleteBehavior | Saat menghapus entitas utama/induk | Saat memisahkan dari induk/prinsipal |
---|---|---|
Air terjun | Ketergantungan yang dihapus oleh EF Core | Ketergantungan yang dihapus oleh EF Core |
Membatasi | InvalidOperationException |
InvalidOperationException |
TidakAdaTindakan | InvalidOperationException |
InvalidOperationException |
SetNull |
SqlException dalam pembuatan database |
SqlException dalam pembuatan database |
ClientSetNull | InvalidOperationException |
InvalidOperationException |
ClientCascade | Ketergantungan yang dihapus oleh EF Core | Ketergantungan yang dihapus oleh EF Core |
ClientNoAction | DbUpdateException |
InvalidOperationException |
Catatan:
- Pengaturan baku untuk hubungan yang diperlukan seperti ini adalah
Cascade
. - Menggunakan apa pun selain penghapusan kaskade untuk hubungan yang diperlukan akan menghasilkan pengecualian saat SaveChanges dipanggil.
- Biasanya, ini adalah
InvalidOperationException
dari EF Core karena status tidak valid terdeteksi dalam anak-anak/dependen yang dimuat. -
ClientNoAction
memaksa EF Core untuk tidak memeriksa dependen perbaikan sebelum mengirimkannya ke database, jadi dalam hal ini database melemparkan pengecualian, yang kemudian dibungkus dalamDbUpdateException
oleh SaveChanges. -
SetNull
ditolak saat membuat database karena kolom kunci asing tidak dapat diubah ke null.
- Biasanya, ini adalah
- Karena dependent/anak telah dimuat, dependent/anak selalu dihapus oleh EF Core, dan tidak pernah dibiarkan untuk dihapus oleh database.
Hubungan yang diperlukan dengan tanggungan/anak tidak dimuat
DeleteBehavior | Saat menghapus entitas utama/induk | Saat memisahkan dari induk/prinsipal |
---|---|---|
Air terjun | Entri yang bergantung dihapus oleh basis data | Tidak tersedia |
Membatasi | DbUpdateException |
Tidak tersedia |
TidakAdaTindakan | DbUpdateException |
Tidak tersedia |
SetNull |
SqlException dalam pembuatan database |
Tidak tersedia |
ClientSetNull | DbUpdateException |
Tidak tersedia |
ClientCascade | DbUpdateException |
Tidak tersedia |
ClientNoAction | DbUpdateException |
Tidak tersedia |
Catatan:
- Memutuskan hubungan tidak berlaku di sini karena tanggungan/anak tidak dimuat.
- Pengaturan baku untuk hubungan yang diperlukan seperti ini adalah
Cascade
. - Menggunakan apa pun selain penghapusan kaskade untuk hubungan yang diperlukan akan menghasilkan pengecualian saat SaveChanges dipanggil.
- Biasanya, ini karena
DbUpdateException
dependen/anak tidak dimuat, dan karenanya status tidak valid hanya dapat dideteksi oleh database. SaveChanges kemudian membungkus pengecualian database dalamDbUpdateException
. -
SetNull
ditolak saat membuat database karena kolom kunci asing tidak dapat diubah ke null.
- Biasanya, ini karena
Hubungan opsional dengan dependen/anak dimuat
PerilakuHapus | Saat menghapus entitas utama/induk | Saat memisahkan dari induk/prinsipal |
---|---|---|
Air terjun | Ketergantungan yang dihapus oleh EF Core | Ketergantungan yang dihapus oleh EF Core |
Membatasi | FK Dependen diatur ke null oleh EF Core | FK Dependen diatur ke null oleh EF Core |
TidakAdaTindakan | FK Dependen diatur ke null oleh EF Core | FK Dependen diatur ke null oleh EF Core |
SetNull | FK Dependen diatur ke null oleh EF Core | FK Dependen diatur ke null oleh EF Core |
ClientSetNull | FK Dependen diatur ke null oleh EF Core | FK Dependen diatur ke null oleh EF Core |
ClientCascade | Ketergantungan yang dihapus oleh EF Core | Ketergantungan yang dihapus oleh EF Core |
ClientNoAction | DbUpdateException |
FK Dependen diatur ke null oleh EF Core |
Catatan:
- Default untuk hubungan opsional seperti ini adalah
ClientSetNull
. - Dependen/anak tidak pernah dihapus kecuali
Cascade
atauClientCascade
dikonfigurasi. - Semua nilai lainnya menyebabkan FK dependen diatur ke null (tidak ada nilai) oleh EF Core...
- ... kecuali
ClientNoAction
yang memberi tahu EF Core untuk tidak menyentuh kunci asing dependen/anak ketika prinsipal/induk dihapus. Oleh karena itu, database menghasilkan pengecualian, yang dibungkus sebagaiDbUpdateException
oleh SaveChanges.
- ... kecuali
Hubungan opsional dengan tanggungan/anak tidak terisi
DeleteBehavior | Saat menghapus entitas utama/induk | Saat memisahkan dari induk/prinsipal |
---|---|---|
Air terjun | Entri yang bergantung dihapus oleh basis data | Tidak tersedia |
Membatasi | DbUpdateException |
Tidak tersedia |
TidakAdaTindakan | DbUpdateException |
Tidak tersedia |
SetNull | FK Dependen diatur ke null menurut database | Tidak tersedia |
ClientSetNull | DbUpdateException |
Tidak tersedia |
ClientCascade | DbUpdateException |
Tidak tersedia |
ClientNoAction | DbUpdateException |
Tidak tersedia |
Catatan:
- Memutuskan hubungan tidak berlaku di sini karena tanggungan/anak tidak dimuat.
- Default untuk hubungan opsional seperti ini adalah
ClientSetNull
. - Tanggungan/anak perlu dimuat untuk menghindari pengecualian database, kecuali jika database telah dikonfigurasi untuk menerapkan penghapusan atau menjadikan nol.