第四节:EF Core的并发处理
1.說明
和EF版本的并發(fā)處理方案一致,需要知道樂觀并發(fā)和悲觀并發(fā)的區(qū)別,EF Core只支持樂觀并發(fā);監(jiān)控并發(fā)的兩種方案:監(jiān)測單個字段和監(jiān)測整條數(shù)據(jù),DataAnnotations 和 FluentApi的兩種配置方式。
?(PS:EF Core中的并發(fā)處理模式和EF中的基本類似,其他相關(guān)概念參考:第二十節(jié): 深入理解并發(fā)機(jī)制以及解決方案(鎖機(jī)制、EF自有機(jī)制、隊列模式等):)
?2. 兩個概念
(1).悲觀并發(fā):比如有兩個用戶A,B,同時登錄系統(tǒng)修改一個文檔,如果A先進(jìn)入修改,則系統(tǒng)會把該文檔鎖住,B就沒辦法打開了,?只有等A修改完,完全退出的時候B才能進(jìn)入修改。
(2).樂觀并發(fā):A,B兩個用戶同時登錄,如果A先進(jìn)入修改緊跟著B也進(jìn)入了。A修改文檔的同時B也在修改,如果在A保存之后/ B再保存他的修改,此時系統(tǒng)檢測到數(shù)據(jù)庫中文檔記錄與B剛進(jìn)入時不一致,B保存時會拋出異常,修改失敗。
3. 監(jiān)測單個字段
用到的表結(jié)構(gòu):
(1). 監(jiān)測那個字段就配置哪個字段,有兩種配置方式,如下:
A. DataAnnotations配置:在對應(yīng)字段上加特性 [ConcurrencyCheck]
B. FluentApi配置: entity.Property(p => p.age).IsConcurrencyToken();
提交數(shù)據(jù)庫的時候,發(fā)現(xiàn)該字段中的值已經(jīng)被篡改了,就會進(jìn)入DbUpdateConcurrencyException并發(fā)異常中,這里面可以獲取三個值:數(shù)據(jù)庫原始值、?數(shù)據(jù)庫現(xiàn)在值、內(nèi)存中當(dāng)前值。
通常的處理方式:
①. Reload一下,放棄當(dāng)前內(nèi)存中的實體,重新到數(shù)據(jù)庫中加載當(dāng)前實體,然后用當(dāng)前數(shù)據(jù)庫中的值進(jìn)行相應(yīng)的業(yè)務(wù)處理。
②. 直接提示用戶,信息被修改,請重新操作一遍(可以更友好的提示一下)
(2).案例:
保證T_Concurrency01有一條id=01的記錄(age=10),分別用上面的兩種方式進(jìn)行配置,測試的結(jié)果最終age=4,執(zhí)行正確。
1 { 2 //保證T_Concurrency01有一條id=01的記錄(age=10) 3 ypfContext db1 = new ypfContext(); 4 ypfContext db2 = new ypfContext(); 5 6 try 7 { 8 var data1 = db1.T_Concurrency01.Where(u => u.id == "01").FirstOrDefault(); 9 var data2 = db2.T_Concurrency01.Where(u => u.id == "01").FirstOrDefault(); 10 11 data1.age = data1.age - 2; 12 int result1 = db1.SaveChanges(); 13 14 data2.age = data2.age - 4; 15 int result2 = db2.SaveChanges(); //發(fā)現(xiàn)age的值和原先查出來的不一致,會拋異常進(jìn)入cache 16 } 17 catch (DbUpdateConcurrencyException ex) 18 { 19 var entityEntry = ex.Entries.Single(); 20 var original = entityEntry.OriginalValues.ToObject() as T_Concurrency01; //數(shù)據(jù)庫原始值 10 21 var database = entityEntry.GetDatabaseValues().ToObject() as T_Concurrency01; //數(shù)據(jù)庫現(xiàn)在值 8 22 var current = entityEntry.CurrentValues.ToObject() as T_Concurrency01; //當(dāng)前內(nèi)存值 6 23 entityEntry.Reload(); //放棄當(dāng)前內(nèi)存中的實體,重新到數(shù)據(jù)庫中加載當(dāng)前實體 24 25 current.age = database.age - 4; //應(yīng)該拿著當(dāng)前數(shù)據(jù)庫實際的值去處理,即8-4=4 26 entityEntry.CurrentValues.SetValues(current); 27 int result3 = db2.SaveChanges(); 28 } 29 }4. 監(jiān)測整條數(shù)據(jù)
用到的表結(jié)構(gòu):
?
(1). 首先要給該表在數(shù)據(jù)庫中加一個字段(任意命名即可),通常叫“timeStamp”或“rowVersion”,然后進(jìn)行配置:
A. DataAnnotations配置:在對應(yīng)字段上加特性1702462243
B. FluentApi配置: entity.Property(e => e.rowVersion).IsRowVersion();
提交數(shù)據(jù)庫的時候,發(fā)現(xiàn)該表中任意字段中的值被篡改了,就會進(jìn)入DbUpdateConcurrencyException并發(fā)異常中,這里面可以獲取三個值:數(shù)據(jù)庫原始值、?數(shù)據(jù)庫現(xiàn)在值、內(nèi)存中當(dāng)前值。
通常的處理方式:
①. Reload一下,放棄當(dāng)前內(nèi)存中的實體,重新到數(shù)據(jù)庫中加載當(dāng)前實體,然后用當(dāng)前數(shù)據(jù)庫中的值進(jìn)行相應(yīng)的業(yè)務(wù)處理。
②. 直接提示用戶,信息被修改,請重新操作一遍(可以更友好的提示一下)
(2). 案例
保證T_Concurrency02有一條id=01的記錄(age=10),沒別用上面的兩種方式進(jìn)行配置,還是用age來進(jìn)行測試,測試的結(jié)果最終age=4,執(zhí)行正確。
1 { 2 //保證T_Concurrency02有一條id=01的記錄(age=10) 3 ypfContext db1 = new ypfContext(); 4 ypfContext db2 = new ypfContext(); 5 6 try 7 { 8 var data1 = db1.T_Concurrency02.Where(u => u.id == "01").FirstOrDefault(); 9 var data2 = db2.T_Concurrency02.Where(u => u.id == "01").FirstOrDefault(); 10 11 data1.age = data1.age - 2; 12 int result1 = db1.SaveChanges(); 13 14 data2.age = data2.age - 4; 15 int result2 = db2.SaveChanges(); //發(fā)現(xiàn)age的值和原先查出來的不一致,會拋異常進(jìn)入cache 16 } 17 catch (DbUpdateConcurrencyException ex) 18 { 19 var entityEntry = ex.Entries.Single(); 20 var original = entityEntry.OriginalValues.ToObject() as T_Concurrency02; //數(shù)據(jù)庫原始值 10 21 var database = entityEntry.GetDatabaseValues().ToObject() as T_Concurrency02; //數(shù)據(jù)庫現(xiàn)在值 8 22 var current = entityEntry.CurrentValues.ToObject() as T_Concurrency02; //當(dāng)前內(nèi)存值 6 23 entityEntry.Reload(); //放棄當(dāng)前內(nèi)存中的實體,重新到數(shù)據(jù)庫中加載當(dāng)前實體 24 25 current.age = database.age - 4; //應(yīng)該拿著當(dāng)前數(shù)據(jù)庫實際的值去處理,即8-4=4 26 entityEntry.CurrentValues.SetValues(current); 27 int result3 = db2.SaveChanges(); 28 } 29 }?
?
?
!
- 作???????者 : Yaopengfei(姚鵬飛)
- 博客地址 : http://www.cnblogs.com/yaopengfei/
- 聲?????明1 : 本人才疏學(xué)淺,用郭德綱的話說“我是一個小學(xué)生”,如有錯誤,歡迎討論,請勿謾罵^_^。
- 聲?????明2 : 原創(chuàng)博客請在轉(zhuǎn)載時保留原文鏈接或在文章開頭加上本人博客地址,否則保留追究法律責(zé)任的權(quán)利。
轉(zhuǎn)載于:https://www.cnblogs.com/yaopengfei/p/11377090.html
總結(jié)
以上是生活随笔為你收集整理的第四节:EF Core的并发处理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 农行军人信用卡额度一般是多少?资信条件&
- 下一篇: Oracle新建用户并授权