From 91ee5d1d0eb16c1a3cac0edbbabca724725b5f75 Mon Sep 17 00:00:00 2001 From: sunkaixuan <610262374@qq.com> Date: Sun, 24 Jul 2022 16:39:29 +0800 Subject: [PATCH] Add new optimistic lock --- .../UpdateProvider/UpdateableProvider.cs | 39 ++++++++++++++++++- Src/Asp.Net/SqlSugar/Interface/IUpdateable.cs | 2 + Src/Asp.Net/SqlSugar/Utilities/UtilMethods.cs | 24 ++++++++++++ 3 files changed, 64 insertions(+), 1 deletion(-) diff --git a/Src/Asp.Net/SqlSugar/Abstract/UpdateProvider/UpdateableProvider.cs b/Src/Asp.Net/SqlSugar/Abstract/UpdateProvider/UpdateableProvider.cs index a1d01657f..32f21cdb5 100644 --- a/Src/Asp.Net/SqlSugar/Abstract/UpdateProvider/UpdateableProvider.cs +++ b/Src/Asp.Net/SqlSugar/Abstract/UpdateProvider/UpdateableProvider.cs @@ -59,6 +59,15 @@ namespace SqlSugar var sqlObj = this.ToSql(); this.Context.Queues.Add(sqlObj.Key, sqlObj.Value); } + + public virtual int ExecuteCommandWithOptLock() + { + var updateData = UpdateObjs.FirstOrDefault(); + if (updateData == null) return 0; + _ExecuteCommandWithOptLock(updateData); + return this.ExecuteCommand(); + } + public virtual int ExecuteCommand() { string sql = _ExecuteCommand(); @@ -74,6 +83,13 @@ namespace SqlSugar { return this.ExecuteCommand() > 0; } + public virtual async Task ExecuteCommandWithOptLockAsync() + { + var updateData = UpdateObjs.FirstOrDefault(); + if (updateData == null) return 0; + _ExecuteCommandWithOptLock(updateData); + return await this.ExecuteCommandAsync(); + } public virtual async Task ExecuteCommandAsync() { string sql = _ExecuteCommand(); @@ -852,7 +868,28 @@ namespace SqlSugar this.RemoveCacheFunc(); } } - + private void _ExecuteCommandWithOptLock(T updateData) + { + Check.ExceptionEasy(UpdateParameterIsNull == true, "Optimistic lock can only be an entity update method", "乐观锁只能是实体更新方式"); + var verColumn = this.EntityInfo.Columns.FirstOrDefault(it => it.IsEnableUpdateVersionValidation); + Check.ExceptionEasy(verColumn == null, $" {this.EntityInfo.EntityName } need IsEnableUpdateVersionValidation=true ", $"实体{this.EntityInfo.EntityName}没有找到版本标识特性 IsEnableUpdateVersionValidation"); + Check.ExceptionEasy(UpdateObjs.Length > 1, $"Optimistic lock can only handle a single update ", $"乐观锁只能处理单条更新"); + Check.ExceptionEasy(!verColumn.UnderType.IsIn(UtilConstants.StringType, UtilConstants.LongType, UtilConstants.GuidType, UtilConstants.DateType), $"Optimistic locks can only be guid, long, and string types", $"乐观锁只能是Guid、Long和字符串类型"); + var oldValue = verColumn.PropertyInfo.GetValue(updateData); + var newValue = UtilMethods.GetRandomByType(verColumn.UnderType); + verColumn.PropertyInfo.SetValue(updateData, newValue); + var data = this.UpdateBuilder.DbColumnInfoList.First(it => + it.PropertyName.EqualCase(verColumn.PropertyName)); + data.Value = newValue; + var pks = GetPrimaryKeys(); + this.Where(verColumn.DbColumnName, "=", oldValue); + foreach (var p in pks) + { + var pkColumn = this.EntityInfo.Columns.FirstOrDefault( + it => it.DbColumnName.EqualCase(p) || it.PropertyName.EqualCase(p)); + this.Where(pkColumn.DbColumnName, "=", pkColumn.PropertyInfo.GetValue(updateData)); + } + } private void Before(string sql) { if (this.IsEnableDiffLogEvent) diff --git a/Src/Asp.Net/SqlSugar/Interface/IUpdateable.cs b/Src/Asp.Net/SqlSugar/Interface/IUpdateable.cs index 56e5703b4..430e830d6 100644 --- a/Src/Asp.Net/SqlSugar/Interface/IUpdateable.cs +++ b/Src/Asp.Net/SqlSugar/Interface/IUpdateable.cs @@ -12,6 +12,8 @@ namespace SqlSugar UpdateBuilder UpdateBuilder { get; set; } bool UpdateParameterIsNull { get; set; } + int ExecuteCommandWithOptLock(); + Task ExecuteCommandWithOptLockAsync(); int ExecuteCommand(); bool ExecuteCommandHasChange(); Task ExecuteCommandAsync(); diff --git a/Src/Asp.Net/SqlSugar/Utilities/UtilMethods.cs b/Src/Asp.Net/SqlSugar/Utilities/UtilMethods.cs index 8ff8b35f1..2ac280d1c 100644 --- a/Src/Asp.Net/SqlSugar/Utilities/UtilMethods.cs +++ b/Src/Asp.Net/SqlSugar/Utilities/UtilMethods.cs @@ -133,6 +133,30 @@ namespace SqlSugar }; } + internal static object GetRandomByType(Type underType) + { + if (underType == UtilConstants.GuidType) + { + return Guid.NewGuid(); + } + else if (underType == UtilConstants.LongType) + { + return SnowFlakeSingle.Instance.NextId(); + } + else if (underType == UtilConstants.StringType) + { + return Guid.NewGuid() + ""; + } + else if (underType == UtilConstants.DateType) + { + return System.DateTime.Now; + } + else + { + return Guid.NewGuid() + ""; + } + } + public static bool IsAsyncMethod(MethodBase method) { if (method == null)