文章目錄
如何避免多個 Entity Framework 6 instance 造成資料覆蓋問題 (DB First - SQL Server)
前後台分離且共同存取 table 或是同時有多台機器甚至是修改資料不經由 Entity Framework 都是平常開發上很常見的情境,但這些操作卻可能因為 Entity Framework 的 cache 機制而出現資料不一致的現象,最近同事疑似遇到類似問題,雖然立馬就想到解決方式,但已經好一陣子沒用,為避免說錯就自己先測試一下並紀錄紀錄囉
要確保資料的完整及一致性,做法有好幾個包括 DB First、Code First、DB table setting 首先就從最簡單的做法:DB First + table setting + SQL Server 看起
重現問題
- user A 開啟特定一筆資料 (name 為 Yowko) 想要修改內容
- user B 也想修改同一筆資料 (name 為 Yowko)
修改情境 (同時開啟資料,僅存檔順序不同)
user B 將 salary 改為
100
並存檔,user A 則改為110
並存檔user A 將 salary 改為
110
並存檔,user B 則改為100
並存檔user B 將 salary 改為
100
並存檔,user A 則修改 name 為Yowko Tsai
並存檔user A 將 name 為
Yowko Tsai
並存檔,user B 則修改 salary 為100
並存檔
結果為何?
user B 將 salary 改為 100 並存檔,user A 則改為 110 並存檔
user A 將 salary 改為 110 並存檔,user B 則改為 100 並存檔
user B 將 salary 改為 100 並存檔,user A 則修改 name 為 Yowko Tsai 並存檔
user A 將 name 為 Yowko Tsai 並存檔,user B 則修改 salary 為 100 並存檔
看完上面幾種情境真實操作的結果,我想應該沒有人可以接受,所以接著就來看看該如何設定
設定步驟
DB Table 設定 >加入
rowversion
欄位EntityFramework 設定
更新 edmx
將
rowversion
欄位 Concurrency Model 屬性改為Fixed
調整 View > 讓
rowversion
成為隱藏欄位@Html.HiddenFor(model=>model.rowversion)
針對資料過時錯誤做特別處理
try { await db.SaveChangesAsync(); } catch (DbUpdateConcurrencyException ex) { return Content($"<script>alert('資料已被他人修改,請重新編輯');document.location = '{Url.Action("Edit",user.Id)}'</script>"); }
實際效果
心得
一開始在 SQL Server 上想加入 rowversion
一直找不到相關設定,查文件又說從 SQL Server 2008 開始就支援,讓我一度懷疑起是不是應該額外安裝什麼套件之類的,後來才發現原來與 timestamp
是同義詞,甚至還建議應該以 rowversion
為主,timestamp
會逐漸淘汰,但就連同屬自家工具的 SSMS (SQL Server Management Studio) 與 Visual Studio 都出現不同的呈現方式,就比較容易讓人混淆了
參考資訊
文章作者 Yowko Tsai
上次更新 2021-11-03
授權合約
本部落格 (Yowko's Notes) 所有的文章內容(包含圖片),任何轉載行為,必須通知並獲本部落格作者 (Yowko Tsai) 的同意始得轉載,且轉載皆須註明出處與作者。
Yowko's Notes 由 Yowko Tsai 製作,以創用CC 姓名標示-非商業性-相同方式分享 3.0 台灣 授權條款 釋出。