国产精品天干天干,亚洲毛片在线,日韩gay小鲜肉啪啪18禁,女同Gay自慰喷水

歡迎光臨散文網(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ā)的評論 (共 條)

分享到微博請遵守國家法律
勐海县| 谷城县| 景德镇市| 旺苍县| 衡山县| 醴陵市| 上高县| 梓潼县| 江口县| 阳新县| 鄯善县| 文成县| 股票| 陇南市| 澄城县| 贵南县| 安顺市| 清徐县| 辰溪县| 确山县| 兰溪市| 梧州市| 东明县| 体育| 普宁市| 大埔区| 合肥市| 乌鲁木齐市| 甘泉县| 新巴尔虎右旗| 枣庄市| 轮台县| 塘沽区| 桐梓县| 吉木萨尔县| 伊通| 盈江县| 柏乡县| 永年县| 渭源县| 新泰市|