sunpengfei
2025-08-06 b2379f0a27da604de31869137f892629ce99a1da
FlexJobApi.Core/Utils/DbUtils/DbUtils.cs
@@ -16,6 +16,7 @@
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Timers;
namespace FlexJobApi.Core
{
@@ -24,6 +25,105 @@
    /// </summary>
    public static class DbUtils
    {
        /// <summary>
        /// 获取树形数据路径
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="parentId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public static async Task<string> GetTreeDataPath<TEntity>(
             Guid? parentId,
            CancellationToken cancellationToken = default)
            where TEntity : CommonEntity, ITreeData<TEntity>, new()
        {
            var rep = Db.GetRepository<TEntity>();
            if (parentId.HasValue)
            {
                var parent = await rep.AsQueryable().AsNoTracking()
                    .Where(it => it.Id == parentId)
                    .Select(it => new
                    {
                        it.Path,
                        it.Code
                    })
                    .FirstOrDefaultAsync(cancellationToken);
                var summary = typeof(TEntity).GetSummary();
                if (parent == null) throw Oops.Oh(EnumErrorCodeType.s404, $"上级{summary}");
                return $"{parent.Path}{parent.Code}/";
            }
            else
            {
                return "/";
            }
        }
        /// <summary>
        /// 更新树形数据下级路径
        /// </summary>
        /// <param name="oldPath"></param>
        /// <param name="newPath"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public static async Task UpdateTreeDataChildrenPath<TEntity>(
            string oldPath,
            string newPath,
            CancellationToken cancellationToken)
            where TEntity : CommonEntity, ITreeData<TEntity>, new()
        {
            var rep = Db.GetRepository<TEntity>();
            var models = await rep.AsQueryable()
                .Where(it => it.Path.StartsWith(oldPath))
                .ToListAsync(cancellationToken);
            if (models.IsNotNull())
            {
                foreach (var model in models)
                {
                    model.Path = model.Path.Replace(oldPath, newPath);
                }
                await rep.UpdateAsync(models);
            }
        }
        /// <summary>
        /// 查询选择器数据
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <typeparam name="TValue"></typeparam>
        /// <typeparam name="TData"></typeparam>
        /// <param name="request"></param>
        /// <param name="getValue"></param>
        /// <param name="getLabel"></param>
        /// <param name="query"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public static async Task<List<SelectQueryResultOption<TValue, TData>>> GetSelect<TEntity, TValue, TData>(
            this SelectQuery<TValue, TData> request,
            Func<TData, TValue> getValue,
            Func<TData, string> getLabel,
            Func<IQueryable<TEntity>, IQueryable<TEntity>> query = null,
            CancellationToken cancellationToken = default)
            where TEntity : CommonEntity, new()
        {
            var rep = Db.GetRepository<TEntity>();
            var q = rep.AsQueryable().AsNoTracking();
            if (query != null) q = query(q);
            else q = q.OrderBy(it => it.Sort).ThenBy(it => it.CreatedTime);
            var models = await q
                .ProjectToType<TData>()
                .ToListAsync(cancellationToken);
            var options = new List<SelectQueryResultOption<TValue, TData>>();
            foreach (var model in models)
            {
                var option = new SelectQueryResultOption<TValue, TData>();
                option.Data = model;
                option.Value = getValue(model);
                option.Label = getLabel(model);
                options.Add(option);
            }
            return options;
        }
        /// <summary>
        /// 查询分页列表数据
        /// </summary>
@@ -34,7 +134,7 @@
        /// <param name="selector"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public static async Task<PagedListQueryResult<TItem>> ToPagedListAsync<TEntity, TItem>(
        public static async Task<PagedListQueryResult<TItem>> GetPagedListAsync<TEntity, TItem>(
            this PagedListQueryPageModel page, 
            Func<IQueryable<TEntity>, IQueryable<TEntity>> query = null,
            Expression<Func<TEntity, TItem>> selector = null,
@@ -45,6 +145,7 @@
            var rep = Db.GetRepository<TEntity>();
            var q = rep.AsQueryable().AsNoTracking();
            if (query != null) q = query(q);
            else q = q.OrderBy(it => it.Sort).ThenBy(it => it.CreatedTime);
            q = q.OrderBy(page.OrderInput);
            var s = selector == null
                ? q.ProjectToType<TItem>()
@@ -65,7 +166,9 @@
        /// <param name="q"></param>
        /// <param name="orders"></param>
        /// <returns></returns>
        public static IQueryable<T> OrderBy<T>(this IQueryable<T> q, List<PagedListQueryPageModelOrderInput> orders)
        public static IQueryable<T> OrderBy<T>(
            this IQueryable<T> q,
            List<PagedListQueryPageModelOrderInput> orders)
        {
            if (orders.IsNull()) return q;
@@ -126,7 +229,10 @@
        /// <param name="query"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public static async Task<int> SetIsDisable<TEntity>(this SetIsDisabledCommand request, Func<IQueryable<TEntity>, IQueryable<TEntity>> query = null, CancellationToken cancellationToken = default)
        public static async Task<int> SetIsDisabled<TEntity>(
            this SetIsDisabledCommand request,
            Func<IQueryable<TEntity>, IQueryable<TEntity>> query = null,
            CancellationToken cancellationToken = default)
            where TEntity : CommonEntity, IIsDisabled, new()
        {
            var rep = Db.GetRepository<TEntity>();
@@ -150,7 +256,10 @@
        /// <param name="query"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public static async Task<int> DeleteData<TEntity>(this DeleteDataCommand request, Func<IQueryable<TEntity>, IQueryable<TEntity>> query = null, CancellationToken cancellationToken = default)
        public static async Task<int> DeleteData<TEntity>(
            this DeleteDataCommand request, Func<IQueryable<TEntity>,
            IQueryable<TEntity>> query = null,
            CancellationToken cancellationToken = default)
            where TEntity : CommonEntity, new()
        {
            var rep = Db.GetRepository<TEntity>();
@@ -171,29 +280,36 @@
        /// <typeparam name="TRequest"></typeparam>
        /// <param name="request"></param>
        /// <param name="checkExist"></param>
        /// <param name="update"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public static async Task<Guid> SaveData<TEntity, TRequest>(this TRequest request, Func<IQueryable<TEntity>, TEntity, TRequest, bool> checkExist = null, CancellationToken cancellationToken = default)
        public static async Task<Guid> SaveData<TEntity, TRequest>(
            this TRequest request,
            Expression<Func<TEntity, bool>> checkExist = null,
            Action<TEntity> update = null,
            CancellationToken cancellationToken = default)
            where TEntity : CommonEntity, new()
            where TRequest : SaveDataCommand, new()
        {
            var xmlDoc = await XmlDocUtils.GetXmlDocAsync();
            var summary = await typeof(TEntity).GetSummary(xmlDoc);
            var rep = Db.GetRepository<TEntity>();
            if (checkExist != null && await rep.AsQueryable().AsNoTracking().AnyAsync(checkExist))
                throw Oops.Oh(EnumErrorCodeType.s405, $"该{summary ?? "信息"}");
            if (request.Id.HasValue)
            {
                var entity = await rep.AsQueryable().FirstOrDefaultAsync(it => it.Id == request.Id, cancellationToken);
                if (entity == null) throw Oops.Oh(EnumErrorCodeType.s404, $"该{summary ?? "信息"}");
                if (checkExist != null && checkExist(rep.AsQueryable().AsNoTracking(), entity, request)) throw Oops.Oh(EnumErrorCodeType.s405, $"该{summary ?? "信息"}");
                request.Adapt(entity);
                if (update != null) update(entity);
                else request.Adapt(entity);
                await rep.UpdateAsync(entity);
                return entity.Id;
            }
            else
            {
                var entity = new TEntity();
                if (checkExist != null && checkExist(rep.AsQueryable().AsNoTracking(), entity, request)) throw Oops.Oh(EnumErrorCodeType.s405, $"该{summary ?? "信息"}");
                request.Adapt(entity);
                if (update != null) update(entity);
                else request.Adapt(entity);
                await rep.InsertAsync(entity);
                return entity.Id;
            }