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

@天才臥龍的伯克利

 

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