EF Core - DbUpdateException
你是否曾在 SaveChanges() 時迎來晴天霹靂,一行紅字 DbUpdateException 打斷了你的程式?這就像在大海航行時,突然撞上一座看不見的暗礁──平時無聲無息,一出事卻攪得你天翻地覆。
這篇文章,我們就來一起潛入這片資料海域,探查六種常見導致 DbUpdateException 的暗礁地形。每一種都有它的風險與成因,但只要理解清楚,就能順利避開,繼續駛向資料的彼岸。
💥 1. 主鍵(Primary Key)衝突,一碼歸一人
主鍵(Primary Key)是資料的身份證號。若你試圖插入一筆資料,但主鍵與資料庫中已存在的資料相同,那就如同系統收到兩張一模一樣的身分證,無法分辨誰是誰,只能報錯。
1 | context.Users.Add(new User { Id = 1 }); // Id = 1 已存在 |
常見原因
- 手動指定主鍵值,未使用自動遞增。
- 測試資料未清空。
💥 2. 外鍵(Foreign Key)違反,找不到對應人
外鍵(Foreign Key)是資料之間的橋樑。若你新增一筆訂單,卻引用了一位不存在的客戶,那就像寄信到一個虛構地址──沒有收件人,自然寄不出去。
1 | context.Orders.Add(new Order { CustomerId = 999 }); // Customers 表沒有 Id=999 |
💥 3. 必填欄位(NOT NULL)為 null : 不該留白的愛
有些欄位規定不可為 null,就像是報名表不能漏填姓名。若你在儲存時忘記提供資料庫期待的欄位值,它會用最嚴厲的方式提醒你:「打妹!」
1 | context.Products.Add(new Product { Name = null }); // Name 是 NOT NULL 欄位 |
💥 4. 欄位長度限制超過(MaxLength/Size) : 你話太多了
若欄位被設定為 nvarchar(50),但你給了超過 50 字元的字串,那就像在行李箱塞入一整隻鯨魚──太長,裝不下,自然塞不進去。
1 | product.Description = new string('A', 1000); // 限制為 255 字,實際給了 1000 |
作法
- 使用 MaxLength 屬性限制輸入。
- 在 UI 端或伺服端做前置驗證。
💥 5. 資料類型不相符 : 能飛不代表能跑
資料庫欄位有明確型別,你給的值若型別錯誤,轉換失敗就會直接炸開。例如欄位預期是數字,你卻給了一串無法解析的字串。
1 | order.TotalAmount = Convert.ToDecimal("abc"); // 無法轉換為 decimal |
作法
- 加強轉型檢查。
- 使用 TryParse 等方式進行防禦型處理。
💥 6. 違反唯一約束(Unique Constraint) : 這世界只容一個你
唯一約束(Unique Constraint)就像是資料世界的排他戀愛:Email 是唯一的,不能同時給兩個人。若你試圖插入一筆已存在的 Email,資料庫會毫不猶豫地拒絕這段三角戀。
1 | context.Users.Add(new User { Email = "existing@email.com" }); // 已存在 |
- 儲存前先查詢是否存在相同值。
- 或於資料庫層加上 Try-Catch 處理違反例外。
🌊 結語:掌握海圖,才能穿越暗礁
DbUpdateException 並不可怕,可怕的是對其一無所知。這六大類錯誤,猶如暗藏在資料海域下的礁岩,初學者難免觸礁,但熟練者懂得避開,甚至利用這些限制來保障資料正確性。
All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
Comment