日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

第四节:EF Core的并发处理

發(fā)布時間:2023/12/13 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 第四节:EF Core的并发处理 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

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)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。