十年河東,十年河西,莫欺少年窮
學無止境,精益求精
1、新建帶有RowRersion的實體
/// <summary> ///房子 -- 用於演示搶房子 /// </summary> public class House { public string HouseId { get; set; } public string HouseName { get; set; } public string Onwer { get; set; } public int HouseCount { get; set; } public DateTime? CreateTime { get; set; } public byte[] RowRersion { get; set; } }
2、配置樂觀鎖令牌,並加入DbSet
public class HouseConfig : IEntityTypeConfiguration<House> { public void Configure(EntityTypeBuilder<House> builder) { builder.ToTable("T_House"); //表名 builder.HasKey(A => A.HouseId);//主鍵 builder.Property(A => A.HouseId).HasMaxLength(50); builder.Property(A => A.RowRersion).IsRowVersion();//樂觀鎖令牌 } } public class wechatDbContext : DbContext { public DbSet<House> Houses { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { base.OnConfiguring(optionsBuilder);//;MultipleActiveResultSets=true optionsBuilder.UseSqlServer("Data Source=LAPTOP-84R6S0FB;Initial Catalog=demo1;Integrated Security=True;MultipleActiveResultSets=true"); } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); //從當前程序集命名空間加載所有的IEntityTypeConfiguration modelBuilder.ApplyConfigurationsFromAssembly(this.GetType().Assembly); } }
3、通過指令更新數據庫 並在數據庫插入測試數據
Add-Migration initHouse
update-database
插入數據
insert into [demo1].[dbo].[T_House]([HouseId],[Onwer],[HouseCount],[CreateTime]) values(newid(),'河南建業',10,getdate())
4、書寫測試代碼
using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; using System.Data.Common; using System.Linq; using System.Threading; using System.Threading.Tasks; namespace EfCore { internal class Program { static int hourseCount = 0; static void Main(string[] args) { for (int i = 1; i < 101; i++) { Task.Run(() => { GetHouse(); }); } Thread.Sleep(20000);//20秒執行時間 // Console.WriteLine($"總共{hourseCount}人搶房成功"); Console.Read(); } static void GetHouse() { using (wechatDbContext context = new wechatDbContext()) { var house = context.Houses.FirstOrDefault(A => A.Onwer == "河南建業"); if (house.HouseCount > 0) { house.HouseCount = house.HouseCount - 1; try { context.SaveChanges(); hourseCount++; } catch (DbUpdateConcurrencyException ex) { //Console.WriteLine("數據庫訪問併發衝突"); //var entity = ex.Entries.FirstOrDefault(); //string newValue = entity.GetDatabaseValues().GetValue<string>("Onwer"); //Console.WriteLine($"您沒能搶到該房子,房子已被{newValue}搶走"); } } } } } }
通過 DbUpdateConcurrencyException Laura捕獲數據庫併發異常
通過異步模仿併發搶房場景
5、測試如下
如果不加樂觀鎖,髒讀誤讀的情況下,有可能會出現10人以上搶房成功,在此就不做演示了。
@天才臥龍的伯克利