【优化】仓储单个数据查询增加悲观锁等待模式。

【优化】通过优惠券编码领取优惠券增加事务处理。
This commit is contained in:
jianweie code
2023-05-08 00:05:27 +08:00
parent 8cb980063e
commit 514c63da60
7 changed files with 89 additions and 91 deletions

View File

@@ -246,8 +246,10 @@ namespace CoreCms.Net.IRepository
/// <param name="blUseNoLock">是否使用WITH(NoLock)</param>
/// <param name="isDataCache">是否启用缓存</param>
/// <param name="cacheTimes">缓存时长(分钟)</param>
/// <param name="blUseTranLock">是否使用锁</param>
/// <param name="dbLockType">数据锁类型</param>
/// <returns></returns>
Task<T> QueryByClauseAsync(Expression<Func<T, bool>> predicate, bool blUseNoLock = false, bool isDataCache = false, int cacheTimes = int.MaxValue);
Task<T> QueryByClauseAsync(Expression<Func<T, bool>> predicate, bool blUseNoLock = false, bool isDataCache = false, int cacheTimes = int.MaxValue, bool blUseTranLock = false, DbLockType dbLockType = DbLockType.Wait);
/// <summary>
/// 根据条件查询数据
@@ -271,23 +273,10 @@ namespace CoreCms.Net.IRepository
/// <param name="blUseNoLock">是否使用WITH(NoLock)</param>
/// <param name="isDataCache">是否启用缓存</param>
/// <param name="cacheTimes">缓存时长(分钟)</param>
/// <param name="blUseTranLock">是否使用锁</param>
/// <param name="dbLockType">数据锁类型</param>
/// <returns></returns>
Task<T> QueryByClauseAsync(Expression<Func<T, bool>> predicate, Expression<Func<T, object>> orderByPredicate,
OrderByType orderByType, bool blUseNoLock = false, bool isDataCache = false, int cacheTimes = int.MaxValue);
/// <summary>
/// 根据条件查询数据(悲观锁等待模式)
/// </summary>
/// <param name="predicate">条件表达式树</param>
/// <param name="orderByPredicate">排序字段</param>
/// <param name="orderByType">排序顺序</param>
/// <param name="blUseTranLock">是否使用TranLock</param>
/// <param name="isDataCache">是否启用缓存</param>
/// <param name="cacheTimes">缓存时长(分钟)</param>
/// <returns></returns>
Task<T> QueryByClauseWithTranLockAsync(Expression<Func<T, bool>> predicate,
Expression<Func<T, object>> orderByPredicate, OrderByType orderByType, bool blUseTranLock = false, bool isDataCache = false, int cacheTimes = int.MaxValue);
Task<T> QueryByClauseAsync(Expression<Func<T, bool>> predicate, Expression<Func<T, object>> orderByPredicate, OrderByType orderByType, bool blUseNoLock = false, bool isDataCache = false, int cacheTimes = int.MaxValue, bool blUseTranLock = false, DbLockType dbLockType = DbLockType.Wait);
#endregion

View File

@@ -247,8 +247,10 @@ namespace CoreCms.Net.IServices
/// <param name="blUseNoLock">是否使用WITH(NoLock)</param>
/// <param name="isDataCache">是否启用缓存</param>
/// <param name="cacheTimes">缓存时长(分钟)</param>
/// <param name="blUseTranLock">是否使用锁</param>
/// <param name="dbLockType">数据锁类型</param>
/// <returns></returns>
Task<T> QueryByClauseAsync(Expression<Func<T, bool>> predicate, bool blUseNoLock = false, bool isDataCache = false, int cacheTimes = int.MaxValue);
Task<T> QueryByClauseAsync(Expression<Func<T, bool>> predicate, bool blUseNoLock = false, bool isDataCache = false, int cacheTimes = int.MaxValue, bool blUseTranLock = false, DbLockType dbLockType = DbLockType.Wait);
/// <summary>
/// 根据条件查询数据
@@ -272,24 +274,12 @@ namespace CoreCms.Net.IServices
/// <param name="blUseNoLock">是否使用WITH(NoLock)</param>
/// <param name="isDataCache">是否启用缓存</param>
/// <param name="cacheTimes">缓存时长(分钟)</param>
/// <param name="blUseTranLock">是否使用锁</param>
/// <param name="dbLockType">数据锁类型</param>
/// <returns></returns>
Task<T> QueryByClauseAsync(Expression<Func<T, bool>> predicate, Expression<Func<T, object>> orderByPredicate,
OrderByType orderByType, bool blUseNoLock = false, bool isDataCache = false, int cacheTimes = int.MaxValue);
Task<T> QueryByClauseAsync(Expression<Func<T, bool>> predicate, Expression<Func<T, object>> orderByPredicate, OrderByType orderByType, bool blUseNoLock = false, bool isDataCache = false, int cacheTimes = int.MaxValue, bool blUseTranLock = false, DbLockType dbLockType = DbLockType.Wait);
/// <summary>
/// 根据条件查询数据(悲观锁等待模式)
/// </summary>
/// <param name="predicate">条件表达式树</param>
/// <param name="orderByPredicate">排序字段</param>
/// <param name="orderByType">排序顺序</param>
/// <param name="blUseTranLock">是否使用TranLock</param>
/// <param name="isDataCache">是否启用缓存</param>
/// <param name="cacheTimes">缓存时长(分钟)</param>
/// <returns></returns>
Task<T> QueryByClauseWithTranLockAsync(Expression<Func<T, bool>> predicate,
Expression<Func<T, object>> orderByPredicate, OrderByType orderByType, bool blUseTranLock = false, bool isDataCache = false, int cacheTimes = int.MaxValue);
#endregion
#region

View File

@@ -364,13 +364,12 @@ namespace CoreCms.Net.Repository
/// <param name="blUseNoLock">是否使用WITH(NoLock)</param>
/// <param name="isDataCache">是否启用缓存</param>
/// <param name="cacheTimes">缓存时长(分钟)</param>
/// <param name="blUseTranLock">是否使用锁</param>
/// <param name="dbLockType">数据锁类型</param>
/// <returns></returns>
public async Task<T> QueryByClauseAsync(Expression<Func<T, bool>> predicate, bool blUseNoLock = false, bool isDataCache = false, int cacheTimes = int.MaxValue)
public async Task<T> QueryByClauseAsync(Expression<Func<T, bool>> predicate, bool blUseNoLock = false, bool isDataCache = false, int cacheTimes = int.MaxValue, bool blUseTranLock = false, DbLockType dbLockType = DbLockType.Wait)
{
return await DbBaseClient.Queryable<T>()
.WithNoLockOrNot(blUseNoLock)
.WithCacheIF(isDataCache, cacheTimes)
.FirstAsync(predicate);
return await DbBaseClient.Queryable<T>().WithNoLockOrNot(blUseNoLock).WithUseTranLockOrNot(blUseTranLock, dbLockType).WithCacheIF(isDataCache, cacheTimes).FirstAsync(predicate);
}
/// <summary>
@@ -397,27 +396,14 @@ namespace CoreCms.Net.Repository
/// <param name="blUseNoLock">是否使用WITH(NoLock)</param>
/// <param name="isDataCache">是否启用缓存</param>
/// <param name="cacheTimes">缓存时长(分钟)</param>
/// <param name="blUseTranLock">是否使用锁</param>
/// <param name="dbLockType">数据锁类型</param>
/// <returns></returns>
public async Task<T> QueryByClauseAsync(Expression<Func<T, bool>> predicate, Expression<Func<T, object>> orderByPredicate, OrderByType orderByType, bool blUseNoLock = false, bool isDataCache = false, int cacheTimes = int.MaxValue)
public async Task<T> QueryByClauseAsync(Expression<Func<T, bool>> predicate, Expression<Func<T, object>> orderByPredicate, OrderByType orderByType, bool blUseNoLock = false, bool isDataCache = false, int cacheTimes = int.MaxValue, bool blUseTranLock = false, DbLockType dbLockType = DbLockType.Wait)
{
return await DbBaseClient.Queryable<T>().OrderBy(orderByPredicate, orderByType).WithNoLockOrNot(blUseNoLock).WithCacheIF(isDataCache, cacheTimes).FirstAsync(predicate);
return await DbBaseClient.Queryable<T>().OrderBy(orderByPredicate, orderByType).WithNoLockOrNot(blUseNoLock).WithUseTranLockOrNot(blUseTranLock, dbLockType).WithCacheIF(isDataCache, cacheTimes).FirstAsync(predicate);
}
/// <summary>
/// 根据条件查询数据(悲观锁等待模式)
/// </summary>
/// <param name="predicate">条件表达式树</param>
/// <param name="orderByPredicate">排序字段</param>
/// <param name="orderByType">排序顺序</param>
/// <param name="blUseTranLock">是否使用TranLock</param>
/// <param name="isDataCache">是否启用缓存</param>
/// <param name="cacheTimes">缓存时长(分钟)</param>
/// <returns></returns>
public async Task<T> QueryByClauseWithTranLockAsync(Expression<Func<T, bool>> predicate, Expression<Func<T, object>> orderByPredicate, OrderByType orderByType, bool blUseTranLock = false, bool isDataCache = false, int cacheTimes = int.MaxValue)
{
return await DbBaseClient.Queryable<T>().TranLock(DbLockType.Wait).OrderBy(orderByPredicate, orderByType).WithCacheIF(isDataCache, cacheTimes).FirstAsync(predicate);
}
#endregion
#region

View File

@@ -14,6 +14,23 @@ namespace CoreCms.Net.Repository
return query;
}
/// <summary>
/// 是否启用锁
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="query"></param>
/// <param name="lock"></param>
/// <param name="dbLockType"></param>
/// <returns></returns>
internal static ISugarQueryable<T> WithUseTranLockOrNot<T>(this ISugarQueryable<T> query, bool @lock = false, DbLockType dbLockType = DbLockType.Wait)
{
if (@lock)
{
query = query.TranLock(dbLockType);
}
return query;
}
}
}

View File

@@ -298,10 +298,12 @@ namespace CoreCms.Net.Services
/// <param name="blUseNoLock">是否使用WITH(NoLock)</param>
/// <param name="isDataCache">是否启用缓存</param>
/// <param name="cacheTimes">缓存时长(分钟)</param>
/// <param name="blUseTranLock">是否使用锁</param>
/// <param name="dbLockType">数据锁类型</param>
/// <returns></returns>
public async Task<T> QueryByClauseAsync(Expression<Func<T, bool>> predicate, bool blUseNoLock = false, bool isDataCache = false, int cacheTimes = int.MaxValue)
public async Task<T> QueryByClauseAsync(Expression<Func<T, bool>> predicate, bool blUseNoLock = false, bool isDataCache = false, int cacheTimes = int.MaxValue, bool blUseTranLock = false, DbLockType dbLockType = DbLockType.Wait)
{
return await BaseDal.QueryByClauseAsync(predicate, blUseNoLock, isDataCache, cacheTimes);
return await BaseDal.QueryByClauseAsync(predicate, blUseNoLock, isDataCache, cacheTimes, blUseTranLock, dbLockType);
}
/// <summary>
@@ -329,28 +331,15 @@ namespace CoreCms.Net.Services
/// <param name="blUseNoLock">是否使用WITH(NoLock)</param>
/// <param name="isDataCache">是否启用缓存</param>
/// <param name="cacheTimes">缓存时长(分钟)</param>
/// <param name="blUseTranLock">是否使用锁</param>
/// <param name="dbLockType">数据锁类型</param>
/// <returns></returns>
public async Task<T> QueryByClauseAsync(Expression<Func<T, bool>> predicate, Expression<Func<T, object>> orderByPredicate, OrderByType orderByType, bool blUseNoLock = false, bool isDataCache = false, int cacheTimes = int.MaxValue)
public async Task<T> QueryByClauseAsync(Expression<Func<T, bool>> predicate, Expression<Func<T, object>> orderByPredicate, OrderByType orderByType, bool blUseNoLock = false, bool isDataCache = false, int cacheTimes = int.MaxValue, bool blUseTranLock = false, DbLockType dbLockType = DbLockType.Wait)
{
return await BaseDal.QueryByClauseAsync(predicate, orderByPredicate, orderByType, blUseNoLock, isDataCache, cacheTimes);
return await BaseDal.QueryByClauseAsync(predicate, orderByPredicate, orderByType, blUseNoLock, isDataCache, cacheTimes, blUseTranLock, dbLockType);
}
/// <summary>
/// 根据条件查询数据(悲观锁等待模式)
/// </summary>
/// <param name="predicate">条件表达式树</param>
/// <param name="orderByPredicate">排序字段</param>
/// <param name="orderByType">排序顺序</param>
/// <param name="blUseTranLock">是否使用TranLock</param>
/// <param name="isDataCache">是否启用缓存</param>
/// <param name="cacheTimes">缓存时长(分钟)</param>
/// <returns></returns>
public async Task<T> QueryByClauseWithTranLockAsync(Expression<Func<T, bool>> predicate, Expression<Func<T, object>> orderByPredicate, OrderByType orderByType, bool blUseTranLock = false, bool isDataCache = false, int cacheTimes = int.MaxValue)
{
return await BaseDal.QueryByClauseWithTranLockAsync(predicate, orderByPredicate, orderByType, blUseTranLock, isDataCache, cacheTimes);
}
#endregion
#region

View File

@@ -694,7 +694,7 @@ namespace CoreCms.Net.Services
where = where.And(p => p.isDel == false); //是否被删除
var info = await _dal.QueryByClauseAsync(where);
var info = await _dal.QueryByClauseAsync(where, false, true);
if (info != null)
{
jm.data = info;

View File

@@ -14,6 +14,7 @@ using System.Threading.Tasks;
using CoreCms.Net.Auth.HttpContextUser;
using CoreCms.Net.Caching.AutoMate.RedisCache;
using CoreCms.Net.Configuration;
using CoreCms.Net.IRepository.UnitOfWork;
using CoreCms.Net.IServices;
using CoreCms.Net.Model.Entities;
using CoreCms.Net.Model.FromBody;
@@ -35,18 +36,19 @@ namespace CoreCms.Net.Web.WebApi.Controllers
private readonly ICoreCmsCouponServices _couponServices;
private readonly ICoreCmsPromotionServices _promotionServices;
private readonly IRedisOperationRepository _redisOperationRepository;
private readonly IUnitOfWork _unionOfWork;
/// <summary>
/// 构造函数
/// </summary>
public CouponController(IHttpContextUser user
, ICoreCmsCouponServices couponServices, ICoreCmsPromotionServices promotionServices, IRedisOperationRepository redisOperationRepository)
, ICoreCmsCouponServices couponServices, ICoreCmsPromotionServices promotionServices, IRedisOperationRepository redisOperationRepository, IUnitOfWork unionOfWork)
{
_user = user;
_couponServices = couponServices;
_promotionServices = promotionServices;
_redisOperationRepository = redisOperationRepository;
_unionOfWork = unionOfWork;
}
//公共接口====================================================================================================
@@ -225,25 +227,50 @@ namespace CoreCms.Net.Web.WebApi.Controllers
return jm;
}
//判断优惠券是否可以领取?
var promotionModel = await _promotionServices.ReceiveCoupon(coupon.promotionId);
if (promotionModel.status == false)
try
{
return promotionModel;
}
//判断用户是否已领取?
if (promotionModel.data is CoreCmsPromotion { maxNums: > 0 } info)
{
//判断用户是否已领取?领取次数
var couponResult = await _couponServices.GetMyCoupon(_user.ID, coupon.promotionId, "all", 1, 9999);
if (couponResult.status && couponResult.code > info.maxNums)
_unionOfWork.BeginTran();
//判断优惠券是否可以领取?
var promotionModel = await _promotionServices.ReceiveCoupon(coupon.promotionId);
if (promotionModel.status == false)
{
jm.msg = GlobalErrorCodeVars.Code15018;
_unionOfWork.RollbackTran();
return promotionModel;
}
var promotion = (CoreCmsPromotion)promotionModel.data;
if (promotion == null)
{
_unionOfWork.RollbackTran();
jm.msg = GlobalErrorCodeVars.Code15019;
return jm;
}
if (promotion.maxNums > 0)
{
//判断用户是否已领取?领取次数
var couponResult = await _couponServices.GetMyCoupon(_user.ID, coupon.promotionId, "all", 1, 9999);
if (couponResult.status && couponResult.code >= promotion.maxNums)
{
_unionOfWork.RollbackTran();
jm.msg = GlobalErrorCodeVars.Code15018;
return jm;
}
}
jm = await _couponServices.ReceiveCoupon(_user.ID, entity.key);
_unionOfWork.CommitTran();
jm.otherData = promotionModel;
}
catch (Exception e)
{
_unionOfWork.RollbackTran();
jm.msg = GlobalErrorCodeVars.Code10000;
jm.data = e;
}
//
jm = await _couponServices.ReceiveCoupon(_user.ID, entity.key);
return jm;
}