Files
QYZH.InteractiveMagazine/QYZH.InteractiveMagazine.Repository/BaseRepository.cs
glz cbdee5068a feat: 新增消息Outbox机制、雪花ID配置优化及多项功能完善
1.  新增数据库唯一约束和Message_Outbox表脚本
2.  新增雪花ID、Hangfire存储、MQ重试等配置实体
3.  重构各项目雪花ID生成逻辑,改为从配置读取WorkerId
4.  优化积分服务分页查询、用户背包更新逻辑
5.  新增JWT令牌Redis过期刷新逻辑
6.  完善RabbitMQ死信队列消息头信息
7.  新增可靠MQ消息发布服务和Outbox派发后台服务
8.  替换原有RabbitMQ直接发送为Outbox可靠发布
9.  优化签到服务逻辑,新增重复签到校验和补签卡扣减逻辑
10. 修复自动铺码消费逻辑,新增点阵页预占和释放机制
2026-07-10 10:44:00 +08:00

295 lines
10 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using Mapster;
using Microsoft.Extensions.Logging;
using QYZH.InteractiveMagazine.Infrastructure.Context;
using QYZH.InteractiveMagazine.Models.Dto;
using SqlSugar;
using SqlSugar.IOC;
using System.Data;
using System.Linq.Expressions;
namespace QYZH.InteractiveMagazine.Repository
{
/// <summary>
/// 数据仓库类
/// </summary>
/// <typeparam name="T"></typeparam>
public class BaseRepository<T> : SimpleClient<T> where T : class, new()
{
private readonly ILogger<BaseRepository<T>> _logger;
public BaseRepository(ISqlSugarClient context = null) : base(context)
{
// 优先使用注入的 context如果没有注入则使用 DbScoped.SugarScope
Context = context ?? DbScoped.SugarScope;
_logger = ServiceContext.GetService<ILogger<BaseRepository<T>>>();
}
#region add
public IInsertable<T> Insertable(T t)
{
return Context.Insertable(t);
}
#endregion add
#region update
public IUpdateable<T> Updateable(T t)
{
return Context.Updateable(t);
}
public IUpdateable<T> Updateable()
{
return Context.Updateable<T>();
}
public IUpdateable<T1> Updateable<T1>() where T1 : class, new()
{
return Context.Updateable<T1>();
}
/// <summary>
/// 根据指定条件更新指定列 egUpdate(new SysUser(){ Status = 1 }, it => new { it.Status }, f => f.Userid == 1));
/// 只更新Status列条件是包含
/// </summary>
/// <param name="entity">实体类</param>
/// <param name="expression">要更新列的表达式</param>
/// <param name="where">where表达式</param>
/// <returns></returns>
public async Task<bool> UpdateAsync(Expression<Func<T, bool>> columns, Expression<Func<T, bool>> where)
{
return await Context.Updateable<T>().SetColumns(columns).Where(where).ExecuteCommandAsync() > 0;
}
#endregion update
/// <summary>
/// 事务 异步 无返回值
/// </summary>
/// <param name="action"></param>
/// <returns></returns>
public async Task UseTranAsync(Func<Task> action)
{
Context.Ado.BeginTran();//using不能少
try
{
await action();
Context.Ado.CommitTran();
}
catch (Exception ex)
{
Context.Ado.RollbackTran();
_logger.LogError($"UseTran 异常:{ex.StackTrace}{ex.Message}");
throw;
}
}
/// <summary>
/// 事务 异步 返回bool
/// </summary>
/// <param name="action"></param>
/// <returns></returns>
public async Task<bool> UseTranAsync(Func<Task<bool>> action)
{
Context.Ado.BeginTran();//using不能少
try
{
var result = await action();
if (result)
{
Context.Ado.CommitTran();
return true;
}
else
{
Context.Ado.RollbackTran();
return false;
}
}
catch (Exception ex)
{
Context.Ado.RollbackTran();
_logger.LogError($"UseTran 异常:{ex.StackTrace}{ex.Message}");
throw;
}
}
#region delete
public IDeleteable<T> Deleteable()
{
return Context.Deleteable<T>();
}
#endregion delete
#region query
public bool Any(Expression<Func<T, bool>> expression)
{
return Context.Queryable<T>().Any(expression);
}
public ISugarQueryable<T> Queryable()
{
return Context.Queryable<T>();
}
public ISugarQueryable<T1> Queryable<T1>()
{
return Context.Queryable<T1>();
}
/// <summary>
/// 根据条件表达式查询单条数据
/// </summary>
/// <param name="expression">表达式</param>
/// <returns>泛型实体</returns>
public Task<R> GetByIdAsync<R>(Expression<Func<T, bool>> expression) where R : class
{
return Context.Queryable<T>().Where(expression).Select<R>().FirstAsync();
}
public Task<R> GetByExpressionAsync<R>(Expression<Func<T, bool>> expression) where R : class
{
return Context.Queryable<T>().Where(expression).Select<R>().FirstAsync();
}
public Task<List<T2>> GetListByExpression<T2>(Expression<Func<T, bool>> expression) where T2 : class
{
return Context.Queryable<T>().Where(expression).Select<T2>().ToListAsync();
}
/// <summary>
/// 根据条件查询分页数据
/// </summary>
/// <param name="where"></param>
/// <param name="parm"></param>
/// <returns></returns>
public PageListModel<T> GetPages(Expression<Func<T, bool>> where, PageQueryModel parm)
{
var source = Context.Queryable<T>().Where(where);
return source.ToPage(parm);
}
/// <summary>
/// 分页获取数据
/// </summary>
/// <param name="where">条件表达式</param>
/// <param name="parm"></param>
/// <param name="order"></param>
/// <param name="orderEnum"></param>
/// <returns></returns>
public PageListModel<T> GetPages(Expression<Func<T, bool>> where, PageQueryModel parm, Expression<Func<T, object>> order, OrderByType orderEnum = OrderByType.Asc)
{
var source = Context
.Queryable<T>()
.Where(where)
.OrderByIF(orderEnum == OrderByType.Asc, order, OrderByType.Asc)
.OrderByIF(orderEnum == OrderByType.Desc, order, OrderByType.Desc);
return source.ToPage(parm);
}
public PageListModel<T> GetPages(Expression<Func<T, bool>> where, PageQueryModel parm, Expression<Func<T, object>> order, string orderByType)
{
return GetPages(where, parm, order, orderByType == "desc" ? OrderByType.Desc : OrderByType.Asc);
}
/// <summary>
/// 查询所有数据(无分页,请慎用)
/// </summary>
/// <returns></returns>
public List<T> GetAll(bool useCache = false, int cacheSecond = 3600)
{
return Context.Queryable<T>().WithCacheIF(useCache, cacheSecond).ToList();
}
#endregion query
/// <summary>
/// 此方法不带output返回值
/// var list = new List<SugarParameter>();
/// list.Add(new SugarParameter(ParaName, ParaValue)); input
/// </summary>
/// <param name="procedureName"></param>
/// <param name="parameters"></param>
/// <returns></returns>
public DataTable UseStoredProcedureToDataTable(string procedureName, List<SugarParameter> parameters)
{
return Context.Ado.UseStoredProcedure().GetDataTable(procedureName, parameters);
}
/// <summary>
/// 带output返回值
/// var list = new List<SugarParameter>();
/// list.Add(new SugarParameter(ParaName, ParaValue, true)); output
/// list.Add(new SugarParameter(ParaName, ParaValue)); input
/// </summary>
/// <param name="procedureName"></param>
/// <param name="parameters"></param>
/// <returns></returns>
public (DataTable, List<SugarParameter>) UseStoredProcedureToTuple(string procedureName, List<SugarParameter> parameters)
{
var result = (Context.Ado.UseStoredProcedure().GetDataTable(procedureName, parameters), parameters);
return result;
}
}
/// <summary>
/// 分页查询扩展
/// </summary>
public static class QueryableExtension
{
/// <summary>
/// 读取列表
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source">查询表单式</param>
/// <param name="parm">分页参数</param>
/// <returns></returns>
public static PageListModel<T> ToPage<T>(this ISugarQueryable<T> source, PageQueryModel parm)
{
var page = new PageListModel<T>();
var total = 0;
page.PageSize = parm.PageSize;
page.PageIndex = parm.PageIndex;
if (!string.IsNullOrWhiteSpace(parm.Sort))
{
source.OrderByPropertyName(parm.Sort, parm.SortType?.Contains("desc", StringComparison.OrdinalIgnoreCase) == true ? OrderByType.Desc : OrderByType.Asc);
}
page.Result = source
//.OrderByIF(parm.Sort.IsNotEmpty(), $"{parm.Sort.ToSqlFilter()} {(!string.IsNullOrWhiteSpace(parm.SortType) && parm.SortType.Contains("desc") ? "desc" : "asc")}")
.ToPageList(parm.PageIndex, parm.PageSize, ref total);
page.TotalNum = total;
return page;
}
/// <summary>
/// 转指定实体类Dto
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="T2"></typeparam>
/// <param name="source"></param>
/// <param name="parm"></param>
/// <returns></returns>
public static PageListModel<T2> ToPage<T, T2>(this ISugarQueryable<T> source, PageQueryModel parm)
{
var page = new PageListModel<T2>();
var total = 0;
page.PageSize = parm.PageSize;
page.PageIndex = parm.PageIndex;
if (!string.IsNullOrWhiteSpace(parm.Sort))
{
source.OrderByPropertyName(parm.Sort, parm.SortType?.Contains("desc", StringComparison.OrdinalIgnoreCase) == true ? OrderByType.Desc : OrderByType.Asc);
}
var result = source
//.OrderByIF(parm.Sort.IsNotEmpty(), $"{parm.Sort.ToSqlFilter()} {(!string.IsNullOrWhiteSpace(parm.SortType) && parm.SortType.Contains("desc") ? "desc" : "asc")}")
.ToPageList(parm.PageIndex, parm.PageSize, ref total);
page.TotalNum = total;
page.Result = result.Adapt<List<T2>>();
return page;
}
}
}