最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

EF Code 如何應(yīng)對高并發(fā)

2023-03-18 07:50 作者:吳小敏63  | 我要投稿

1、高并發(fā)的情況,時(shí)常會發(fā)生數(shù)據(jù)不穩(wěn)定的情況

  在看本節(jié)內(nèi)容之前,請先看上一章SqlServer 高并發(fā)的情況下,如何利用鎖保證數(shù)據(jù)的穩(wěn)定性

  本節(jié)內(nèi)容,也是具體討論如何在EF中實(shí)現(xiàn)這些操作

2、場景模擬,同上一章,搶券

  EF 不考慮高并發(fā)的情況下,搶券代碼為:

string _currOwner = Console.ReadLine();//當(dāng)前用戶using var ctx = new MyDBContext();var cop = ctx.Coupons.Single(x => x.Id == 2);if (!string.IsNullOrEmpty(cop.Owner)) { ? ?Console.WriteLine($"券被搶了"); }else{ ? ?cop.Owner = _currOwner; ? ?Thread.Sleep(5000); ? ?ctx.SaveChanges(); ? ?Console.WriteLine($"恭喜{_currOwner}搶到券{cop.Id}了"); } Console.ReadLine();

  打開兩個進(jìn)程,讓tom和jerry同時(shí)先后進(jìn)行搶券,模擬出一個券同時(shí)被兩個用戶搶到的情況

  

  

  上圖可用直觀看出,都提示搶券成功,但是owner是晚一點(diǎn)點(diǎn)執(zhí)行update的jerry,在實(shí)際生產(chǎn)中,無法給tom一個交代

3、解決并發(fā)問題

  3.1 通過updlock,悲觀并發(fā)控制

string _currOwner = Console.ReadLine();//當(dāng)前用戶using var ctx = new MyDBContext();using var tx = ctx.Database.BeginTransaction(); FormattableString sql = $@"select * from Coupons with(updlock) where id=2";var cop = ctx.Coupons.FromSqlInterpolated(sql).Single();if (!string.IsNullOrEmpty(cop.Owner)) { ? ?Console.WriteLine($"券被搶了"); }else{ ? ?cop.Owner = _currOwner; ? ?Thread.Sleep(5000); ? ?ctx.SaveChanges(); ? ?Console.WriteLine($"恭喜{_currOwner}搶到券{cop.Id}了"); } tx.Commit(); Console.ReadLine();

  解決:但這個是排他鎖,有可能造成線程卡頓問題

    

  3.2 通過定義鑒權(quán)字段,樂觀并發(fā)控制

    CouponConfig添加配置

? ? ? ? ? ?builder.Property(x => x.Owner).IsConcurrencyToken();

    搶券代碼:

string _currOwner = Console.ReadLine();//當(dāng)前用戶using var ctx = new MyDBContext();var cop = ctx.Coupons.Single(x => x.Id == 2);if (!string.IsNullOrEmpty(cop.Owner)) { ? ?Console.WriteLine($"券被搶了"); }else{ ? ?Thread.Sleep(5000); ? ?try ? ?{ ? ? ? ?cop.Owner = _currOwner; ? ? ? ?await ctx.SaveChangesAsync(); ? ? ? ?Console.WriteLine($"恭喜{_currOwner}搶到券{cop.Id}了"); ? ?} ? ?catch (DbUpdateConcurrencyException ex) ? ?{ ? ? ? ?var entry = ex.Entries.First(); ? ? ? ?var dbValues = entry.GetDatabaseValues(); ? ? ? ?var newOwner = dbValues.GetValue<string>(nameof(Coupon.Owner)); ? ? ? ?Console.WriteLine($"并發(fā)沖突,{newOwner}已經(jīng)搶到該券了"); ? ?} }

    結(jié)果:

      

    根據(jù)update語句,可用看出where加了owner=舊值,來判斷是否發(fā)生過更改

  3.3 添加數(shù)據(jù)版本標(biāo)識

    如果無法定義一個明確的鑒權(quán)字段,那么可用通過新增一個字段,來標(biāo)識數(shù)據(jù)來進(jìn)行鑒權(quán)

? ?public class Coupon ? ?{ ? ? ? ?public int Id { get; set; } ? ? ? ?public string Name { get; set; } ? ? ? ?public string? Description { get; set; } ? ? ? ?public string? Owner { get; set; } ? ? ? ?public byte[] RowVersion { get; set; } #遷移到數(shù)據(jù)庫,類型為rowversion,當(dāng)數(shù)據(jù)更新時(shí),版本會自動遞增 ? ?}

    遷移后數(shù)據(jù)庫表代碼

CREATE TABLE [dbo].[Coupons] ( ? ?[Id] ? ? ? ? ?INT ? ? ? ? ? ?IDENTITY (1, 1) NOT NULL, ? ?[Name] ? ? ? ?NVARCHAR (MAX) NOT NULL, ? ?[Description] NVARCHAR (MAX) NULL, ? ?[Owner] ? ? ? NVARCHAR (MAX) NULL, ? ?[RowVersion] ?ROWVERSION ? ? NOT NULL, ? ?CONSTRAINT [PK_Coupons] PRIMARY KEY CLUSTERED ([Id] ASC) );

    CouponConfig添加配置

? ? ? ? ? ?builder.Property(x => x.RowVersion).IsRowVersion();

    搶券代碼同3.2

    結(jié)果:

  

  理論和3.2相同,where會做一個rowversion的舊值判斷

?

  總結(jié):這三種方法由淺入深,各有利弊,在并發(fā)量不大的情況下使用3.1,并發(fā)量較大的情況下使用3.2&3.3


EF Code 如何應(yīng)對高并發(fā)的評論 (共 條)

分享到微博請遵守國家法律
建水县| 微山县| 金门县| 县级市| 奉节县| 左贡县| 扎鲁特旗| 平阴县| 太和县| 通河县| 出国| 师宗县| 孝昌县| 福建省| 海宁市| 江都市| 阳原县| 攀枝花市| 无棣县| 饶阳县| 普安县| 上蔡县| 辛集市| 新田县| 通辽市| 丹江口市| 栾城县| 沂水县| 曲麻莱县| 黄石市| 华亭县| 肥东县| 阆中市| 阜平县| 嘉祥县| 佛教| 随州市| 威信县| 扎兰屯市| 黄山市| 溆浦县|