通常我們使用微軟建立好的資料表不會注意他有做那些關聯,功能方便,在使用的時候也需要注意一些事情,這邊特別記錄資料表關聯調整,設定上程式碼需要調整什麼。
Entity Framework Core 關聯刪除
Entity Framework Core 关联删除 - Sweet-Tang - 博客园
SQL 4種行為
在SQL Server中支持如下四種行為:
ON DELETE NO ACTION
默認行為,刪除主表數據行時,依賴表中的數據不會執行任何操作,此時會產生錯誤,並回滾DELETE語句。例如會產生下面的錯誤:
DELETE 語句與 REFERENCE 約束"FK_Order Details_Orders_OrderID"衝突。該衝突發生於數據庫"Northwind_Test",表"dbo.Order Details", column 'OrderID'。
語句已終止。
ON DELETE CASCADE
刪除主表數據行時,依賴表的中數據行也會同步刪除。
ON DELETE SET NULL
刪除主表數據行時,將依賴表中數據行的外鍵更新為NULL。為了滿足此約束,目標表的外鍵列必須可為空值。
ON DELETE SET DEFAULT
刪除主表數據行時,將依賴表的中數據行的外鍵更新為默認值。為了滿足此約束,目標表的所有外鍵列必須具有默認值定義;如果外鍵可為空值,並且未顯式設置默認值,則將使用NULL作為該列的隱式默認值。
簡單介紹了數據庫中行為後,我們來著重介紹 EF Core 中的關聯實體的行為。
預設 Identity 資料表動作(級聯刪除 CasCade)
Identity 資料表動作預設為級聯刪除(CasCade) ,這邊要注意 SQL Server 預設為 NoAction,Identity 資料表預設不知道為什麼做級聯刪除 (CasCade)。但我們可以手動改掉他。
下圖是看資料表建立的Schema,可以看外鍵設定。
這邊可以直接測試看看
GIT: 刪除使用者 · malagege/NetCoreAuthSample@01b8e0a
防止連同刪除方法
GIT: 角色防止連動刪除用戶關連資料 · malagege/NetCoreAuthSample@0a6a78f
全部外鍵設定 Restrict
AppContextDb.cs
1
2
3
4
5
6
|
// base.OnModelCreating(modelBuilder);
var foreignKeys = modelBuilder.Model.GetEntityTypes().SelectMany(e => e.GetForeignKeys());
foreach (var foreignKey in foreignKeys)
{
foreignKey.DeleteBehavior = DeleteBehavior.Restrict;
}
|
powershell
1
|
Add-Migration DeleteBehaviorRestrict
|
不知道是不是新版關係,我們這邊會出錯
1
|
The entity type 'IdentityUserLogin<string>' requires a primary key to be defined. If you intended to use a keyless entity type, call 'HasNoKey' in 'OnModelCreating'. For more information on keyless entity types, see https://go.microsoft.com/fwlink/?linkid=2141943.
|
後來發現少了一句base.OnModelCreating(modelBuilder);,參考c# - The entity type ‘IdentityUserLogin<string>’ requires a primary key to be defined - Stack Overflow
AppContextDb.cs
1
2
3
4
5
6
|
base.OnModelCreating(modelBuilder);
var foreignKeys = modelBuilder.Model.GetEntityTypes().SelectMany(e => e.GetForeignKeys());
foreach (var foreignKey in foreignKeys)
{
foreignKey.DeleteBehavior = DeleteBehavior.Restrict;
}
|
Powershell 以下指令就會成功了
1
|
Add-Migration DeleteBehaviorRestrict
|
其他相關IdentityASP.NET Core 中的模型自訂 | Microsoft Docs
刪除含有帳號的角色會看到Exception。
指定 Identity Table 外來鍵設定
上面寫法我覺得程式很少,不能做到特定篩選,我怕日後這些程式碼會不會影響我建立關聯的Entity,所以我找相關可以取代指定 Entity方法。後來拼拼湊湊組成下面這個。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
var foreignKeys = modelBuilder.Entity<IdentityUserRole<string>>().Metadata.GetForeignKeys();
foreach (var foreignKey in foreignKeys)
{
foreignKey.DeleteBehavior = DeleteBehavior.Restrict;
}
foreignKeys = modelBuilder.Entity<IdentityUserToken<string>>().Metadata.GetForeignKeys();
foreach (var foreignKey in foreignKeys)
{
foreignKey.DeleteBehavior = DeleteBehavior.Restrict;
}
foreignKeys = modelBuilder.Entity<IdentityUserClaim<string>>().Metadata.GetForeignKeys();
foreach (var foreignKey in foreignKeys)
{
foreignKey.DeleteBehavior = DeleteBehavior.Restrict;
}
foreignKeys = modelBuilder.Entity<IdentityUserLogin<string>>().Metadata.GetForeignKeys();
foreach (var foreignKey in foreignKeys)
{
foreignKey.DeleteBehavior = DeleteBehavior.Restrict;
}
foreignKeys = modelBuilder.Entity<IdentityRoleClaim<string>>().Metadata.GetForeignKeys();
foreach (var foreignKey in foreignKeys)
{
foreignKey.DeleteBehavior = DeleteBehavior.Restrict;
}
|
我還是不建議用上面方法,反思為什麼不用程式去查詢判斷 IdentityUserRole 相關資料表有沒有料?透過程式去阻擋?這都是可以解決的。
參考來源