十年河东,十年河西,莫欺少年穷
学无止境,精益求精
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
插入数据
'河南建业',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人以上抢房成功,在此就不做演示了。
@天才卧龙的伯克利