mirror of
http://git.coreshop.cn/jianweie/coreshoppro.git
synced 2026-03-24 18:17:22 +08:00
【优化】并发下单场景用户金额变动增加事务锁的悲观锁等待模式,防止出现金额异常情况。
This commit is contained in:
@@ -229,6 +229,18 @@ namespace CoreCms.Net.IRepository
|
|||||||
Task<T> QueryByClauseAsync(Expression<Func<T, bool>> predicate, Expression<Func<T, object>> orderByPredicate,
|
Task<T> QueryByClauseAsync(Expression<Func<T, bool>> predicate, Expression<Func<T, object>> orderByPredicate,
|
||||||
OrderByType orderByType, bool blUseNoLock = false);
|
OrderByType orderByType, bool blUseNoLock = false);
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 根据条件查询数据(悲观锁等待模式)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="predicate">条件表达式树</param>
|
||||||
|
/// <param name="orderByPredicate">排序字段</param>
|
||||||
|
/// <param name="orderByType">排序顺序</param>
|
||||||
|
/// <param name="blUseTranLock">是否使用TranLock</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<T> QueryByClauseWithTranLockAsync(Expression<Func<T, bool>> predicate,
|
||||||
|
Expression<Func<T, object>> orderByPredicate, OrderByType orderByType, bool blUseTranLock = false);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 写入实体数据
|
/// 写入实体数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -230,6 +230,18 @@ namespace CoreCms.Net.IServices
|
|||||||
Task<T> QueryByClauseAsync(Expression<Func<T, bool>> predicate, Expression<Func<T, object>> orderByPredicate,
|
Task<T> QueryByClauseAsync(Expression<Func<T, bool>> predicate, Expression<Func<T, object>> orderByPredicate,
|
||||||
OrderByType orderByType, bool blUseNoLock = false);
|
OrderByType orderByType, bool blUseNoLock = false);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 根据条件查询数据(悲观锁等待模式)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="predicate">条件表达式树</param>
|
||||||
|
/// <param name="orderByPredicate">排序字段</param>
|
||||||
|
/// <param name="orderByType">排序顺序</param>
|
||||||
|
/// <param name="blUseTranLock">是否使用TranLock</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<T> QueryByClauseWithTranLockAsync(Expression<Func<T, bool>> predicate,
|
||||||
|
Expression<Func<T, object>> orderByPredicate, OrderByType orderByType, bool blUseTranLock = false);
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 写入实体数据
|
/// 写入实体数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -373,6 +373,25 @@ namespace CoreCms.Net.Repository
|
|||||||
: await DbBaseClient.Queryable<T>().OrderBy(orderByPredicate, orderByType).FirstAsync(predicate);
|
: await DbBaseClient.Queryable<T>().OrderBy(orderByPredicate, orderByType).FirstAsync(predicate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 根据条件查询数据(悲观锁等待模式)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="predicate">条件表达式树</param>
|
||||||
|
/// <param name="orderByPredicate">排序字段</param>
|
||||||
|
/// <param name="orderByType">排序顺序</param>
|
||||||
|
/// <param name="blUseTranLock">是否使用TranLock</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<T> QueryByClauseWithTranLockAsync(Expression<Func<T, bool>> predicate,
|
||||||
|
Expression<Func<T, object>> orderByPredicate, OrderByType orderByType, bool blUseTranLock = false)
|
||||||
|
{
|
||||||
|
return blUseTranLock
|
||||||
|
? await DbBaseClient.Queryable<T>().TranLock(DbLockType.Wait).OrderBy(orderByPredicate, orderByType)
|
||||||
|
.FirstAsync(predicate)
|
||||||
|
: await DbBaseClient.Queryable<T>().OrderBy(orderByPredicate, orderByType).FirstAsync(predicate);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 写入实体数据
|
/// 写入实体数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -300,6 +300,21 @@ namespace CoreCms.Net.Services
|
|||||||
return await BaseDal.QueryByClauseAsync(predicate, orderByPredicate, orderByType, blUseNoLock);
|
return await BaseDal.QueryByClauseAsync(predicate, orderByPredicate, orderByType, blUseNoLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 根据条件查询数据(悲观锁等待模式)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="predicate">条件表达式树</param>
|
||||||
|
/// <param name="orderByPredicate">排序字段</param>
|
||||||
|
/// <param name="orderByType">排序顺序</param>
|
||||||
|
/// <param name="blUseTranLock">是否使用TranLock</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<T> QueryByClauseWithTranLockAsync(Expression<Func<T, bool>> predicate,
|
||||||
|
Expression<Func<T, object>> orderByPredicate, OrderByType orderByType, bool blUseTranLock = false)
|
||||||
|
{
|
||||||
|
return await BaseDal.QueryByClauseWithTranLockAsync(predicate, orderByPredicate, orderByType, blUseTranLock);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 写入实体数据
|
/// 写入实体数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -64,61 +64,72 @@ namespace CoreCms.Net.Services
|
|||||||
|
|
||||||
if (money != 0)
|
if (money != 0)
|
||||||
{
|
{
|
||||||
//取用户实际余额
|
try
|
||||||
var userInfo = await userServices.QueryByIdAsync(userId);
|
|
||||||
if (userInfo == null)
|
|
||||||
{
|
{
|
||||||
jm.data = jm.code = 11004;
|
_unitOfWork.BeginTran();
|
||||||
jm.msg = GlobalErrorCodeVars.Code11004;
|
|
||||||
return jm;
|
//取用户实际余额
|
||||||
|
//(会员陌小北提供)
|
||||||
|
var userInfo = await userServices.QueryByClauseWithTranLockAsync(p => p.id == userId, p => p.id, OrderByType.Desc, true);
|
||||||
|
|
||||||
|
if (userInfo == null)
|
||||||
|
{
|
||||||
|
jm.data = jm.code = 11004;
|
||||||
|
jm.msg = GlobalErrorCodeVars.Code11004;
|
||||||
|
return jm;
|
||||||
|
}
|
||||||
|
|
||||||
|
//取描述,并简单校验
|
||||||
|
var res = UserHelper.GetMemo(type, money, cateMoney);
|
||||||
|
if (string.IsNullOrEmpty(res))
|
||||||
|
{
|
||||||
|
return jm;
|
||||||
|
}
|
||||||
|
var memo = res;
|
||||||
|
if (type != (int)GlobalEnumVars.UserBalanceSourceTypes.Admin)
|
||||||
|
{
|
||||||
|
//后台充值或调不改绝对值
|
||||||
|
|
||||||
|
}
|
||||||
|
//如果是减余额的操作,还是加余额操作
|
||||||
|
if (type is (int)GlobalEnumVars.UserBalanceSourceTypes.Pay or (int)GlobalEnumVars.UserBalanceSourceTypes.Tocash)
|
||||||
|
{
|
||||||
|
money = -money - cateMoney;
|
||||||
|
}
|
||||||
|
if (type != (int)GlobalEnumVars.UserBalanceSourceTypes.Service)
|
||||||
|
{
|
||||||
|
//后台充值或调不改绝对值
|
||||||
|
}
|
||||||
|
|
||||||
|
var balance = userInfo.balance + money;
|
||||||
|
if (balance < 0)
|
||||||
|
{
|
||||||
|
jm.data = jm.code = 11007;
|
||||||
|
jm.msg = GlobalErrorCodeVars.Code11007;
|
||||||
|
return jm;
|
||||||
|
}
|
||||||
|
var balanceModel = new CoreCmsUserBalance();
|
||||||
|
balanceModel.userId = userId;
|
||||||
|
balanceModel.type = type;
|
||||||
|
balanceModel.money = money;
|
||||||
|
balanceModel.balance = balance;
|
||||||
|
balanceModel.sourceId = sourceId;
|
||||||
|
balanceModel.memo = memo;
|
||||||
|
balanceModel.createTime = DateTime.Now;
|
||||||
|
//增加记录
|
||||||
|
var balanceModelId = await _dal.InsertAsync(balanceModel);
|
||||||
|
balanceModel.id = balanceModelId;
|
||||||
|
//更新用户数据
|
||||||
|
await userServices.UpdateAsync(p => new CoreCmsUser() { balance = balance }, p => p.id == userId);
|
||||||
|
|
||||||
|
jm.data = balanceModel;
|
||||||
|
|
||||||
|
_unitOfWork.CommitTran();
|
||||||
}
|
}
|
||||||
//取描述,并简单校验
|
catch (Exception e)
|
||||||
var res = UserHelper.GetMemo(type, money, cateMoney);
|
|
||||||
if (string.IsNullOrEmpty(res))
|
|
||||||
{
|
{
|
||||||
return jm;
|
_unitOfWork.RollbackTran();
|
||||||
}
|
}
|
||||||
var memo = res;
|
|
||||||
if (type != (int)GlobalEnumVars.UserBalanceSourceTypes.Admin)
|
|
||||||
{
|
|
||||||
//后台充值或调不改绝对值
|
|
||||||
|
|
||||||
}
|
|
||||||
//如果是减余额的操作,还是加余额操作
|
|
||||||
if (type == (int)GlobalEnumVars.UserBalanceSourceTypes.Pay || type == (int)GlobalEnumVars.UserBalanceSourceTypes.Tocash)
|
|
||||||
{
|
|
||||||
money = -money - cateMoney;
|
|
||||||
}
|
|
||||||
if (type != (int)GlobalEnumVars.UserBalanceSourceTypes.Service)
|
|
||||||
{
|
|
||||||
//后台充值或调不改绝对值
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
var balance = userInfo.balance + money;
|
|
||||||
if (balance < 0)
|
|
||||||
{
|
|
||||||
jm.data = jm.code = 11007;
|
|
||||||
jm.msg = GlobalErrorCodeVars.Code11007;
|
|
||||||
return jm;
|
|
||||||
}
|
|
||||||
var balanceModel = new CoreCmsUserBalance();
|
|
||||||
balanceModel.userId = userId;
|
|
||||||
balanceModel.type = type;
|
|
||||||
balanceModel.money = money;
|
|
||||||
balanceModel.balance = balance;
|
|
||||||
balanceModel.sourceId = sourceId;
|
|
||||||
balanceModel.memo = memo;
|
|
||||||
balanceModel.createTime = DateTime.Now;
|
|
||||||
//增加记录
|
|
||||||
var balanceModelId = await _dal.InsertAsync(balanceModel);
|
|
||||||
balanceModel.id = balanceModelId;
|
|
||||||
//更新用户数据
|
|
||||||
await userServices.UpdateAsync(p => new CoreCmsUser() { balance = balance }, p => p.id == userId);
|
|
||||||
|
|
||||||
jm.data = balanceModel;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
jm.status = true;
|
jm.status = true;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user