Net5 EfCore CodeFirst 乐观锁 RowRersion

十年河东,十年河西,莫欺少年穷

学无止境,精益求精

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人以上抢房成功,在此就不做演示了。

@天才卧龙的伯克利

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章