文件内容 LevelHandler.cs 24 KB 23741 字符
using Microsoft.EntityFrameworkCore;
using PasteApeart.Domain.Entity;

namespace PasteApeart.Handler.Level
{
    /// <summary>
    /// 多层级 非递归多层级新增和更新
    /// </summary>
    public class LevelHandler : ILevelHandler
    {

        private readonly DbContext _dbContext;

        /// <summary>
        /// 每层最大支持的排序位数 5表示00000
        /// </summary>
        private int _persize { get; set; } = 4;

        /// <summary>
        /// 最大层级个数,从0开始 比如4就是 0 1 2 3
        /// </summary>
        private int _maxlevel { get; set; } = 6;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="dbContext">数据库链接</param>
        /// <param name="perSize">串长度</param>
        /// <param name="maxLevel">层级</param>
        public LevelHandler(DbContext dbContext, int perSize = 4, int maxLevel = 6)
        {
            _dbContext = dbContext;
            _persize = perSize;
            _maxlevel = maxLevel;
        }


        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="Tkey"></typeparam>
        /// <param name="info"></param>
        /// <returns></returns>
        public async Task AfterAddAsync<T, Tkey>(ILevelEntity<Tkey> info) where T : class, ILevelEntity<Tkey>
        {
            info.SortStr = FullRootSortStr(info.Sort);//.ToString().PadLeft(_persize, '0') + "0".PadLeft((_maxlevel - 1) * _persize, '0');
            //if (EqualityComparer<Tkey>.Default.Equals(info.FatherId, default(Tkey)))
            //{
            //    info.FatherStr = $"{info.Id},";
            //    //info.RootId = info.Id;
            //    return;
            //}

            if (info.FatherId.Equals(default(Tkey)))
            {
                info.FatherStr = $"{info.Id},";
                return;
            }

            var dbSet = _dbContext.Set<T>();
            //var dbType = _dbContext.GetType();
            //var dbProperty = dbType.GetProperty(TableName);
            //if (dbProperty != null)
            //{
            //    var dbSet = dbProperty.GetValue(_dbContext) as IQueryable<ILevelEntity>;
            if (dbSet != null)
            {
                var father = await dbSet
                    //.Where(x => EqualityComparer<Tkey>.Default.Equals(x.Id, info.FatherId))
                    .Where(x => x.Id.Equals(info.FatherId))
                    .AsNoTracking()
                    .FirstOrDefaultAsync();
                if (father != null && father != default)
                {
                    info.FatherStr = $"{father.FatherStr}{info.Id},";
                    info.Level = (father.Level + 1);
                    info.FatherId = father.Id;
                    //info.RootId = father.RootId != 0 ? father.RootId : father.Id;
                    BuildSortStr(info, father);
                }
                else
                {
                    info.FatherId = default(Tkey);
                }
            }
            //}
        }


        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="Tkey"></typeparam>
        /// <param name="info"></param>
        /// <param name="oldFatherStr"></param>
        /// <param name="oldLevel"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public async Task AfterUpdateAsync<T, Tkey>(ILevelEntity<Tkey> info, string oldFatherStr, int oldLevel) where T : class, ILevelEntity<Tkey>
        {
            //IQueryable<ILevelEntity> dbSet = null;
            var dbSet = _dbContext.Set<T>();
            //var dbType = _dbContext.GetType();
            //var dbProperty = dbType.GetProperty(TableName);
            //if (dbProperty != null)
            //{
            //    dbSet = dbProperty.GetValue(_dbContext) as IQueryable<ILevelEntity>;
            //}
            if (dbSet == null)
            {
                return;
            }

            if (!default(Tkey).Equals(info.FatherId))
            {
                var father = await dbSet.Where(x => x.Id.Equals(info.FatherId)).AsNoTracking().FirstOrDefaultAsync();
                if (father != null && father != default)
                {
                    info.Level = father.Level + 1;
                    if (info.Level > _maxlevel)
                    {
                        throw new Exception($"当前业务层级超出最大设定MaxLevel={_maxlevel},请调整业务逻辑后再试!");
                    }
                    info.FatherStr = $"{father.FatherStr}{info.Id},";
                    //info.RootId = father.RootId;
                    BuildSortStr(info, father);
                }
                else
                {
                    info.FatherId = default(Tkey);
                    info.FatherStr = $"{info.Id},";
                    info.Level = 0;
                    //info.RootId = info.Id;
                    BuildSortStr(info, null);
                }
            }
            else
            {
                info.FatherId = default(Tkey);
                info.FatherStr = $"{info.Id},";
                info.Level = 0;
                BuildSortStr(info, null);
            }
            oldLevel = oldLevel - (info.Level);
            if (!String.IsNullOrEmpty(oldFatherStr))
            {
                var suns = await dbSet.Where(x => !x.Id.Equals(info.Id) && x.FatherStr.StartsWith(oldFatherStr)).ToListAsync();
                if (suns != null && suns.Count > 0)
                {
                    foreach (var item in suns)
                    {
                        item.FatherStr = item.FatherStr.Replace(oldFatherStr, info.FatherStr);
                        item.Level = item.Level + oldLevel;
                        //item.RootId = info.RootId;
                        BuildFootSortStr(item, info);
                    }
                }
            }
            else
            {
                //需要执行全部,修正一下
            }
        }


        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="Tkey"></typeparam>
        /// <param name="entities"></param>
        /// <exception cref="Exception"></exception>
        public void AllResortByFatherIdAndSort<T, Tkey>(List<T> entities) where T : ILevelEntity<Tkey>
        {
            if (entities == null || entities.Count == 0) return;

            // 2. 找出顶级节点 (FatherId 为 0 或 null)
            //var roots = entities.Where(x => x.FatherId == 0).ToList();
            var roots = entities
                //.Where(x => EqualityComparer<Tkey>.Default.Equals(x.FatherId, default(Tkey)) || (x.FatherId?.ToString() == "0")  // 字符串"0"的情况
                .Where(x => default(Tkey).Equals(x.FatherId))
                    .ToList();
            // 3. 开启递归重算
            foreach (var root in roots)
            {
                if (root.Sort.ToString().Length > _persize)
                {
                    throw new Exception("排序值过大,请调整后再试");
                }
                root.Level = 0;
                root.FatherStr = $"{root.Id},";
                root.SortStr = BuildUnRootSortStr(0, root.Sort, "");
                RecalculateTree<T, Tkey>(root, entities);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="Tkey"></typeparam>
        /// <param name="node"></param>
        /// <param name="entities"></param>
        /// <exception cref="Exception"></exception>
        private void RecalculateTree<T, Tkey>(T node, List<T> entities) where T : ILevelEntity<Tkey>
        {
            //寻找他的子集
            var childs = entities
                //.Where(x => EqualityComparer<Tkey>.Default.Equals(x.FatherId, node.Id))
                .Where(x => node.Id.Equals(x.FatherId))
                .ToList();
            if (childs?.Count > 0)
            {
                foreach (var child in childs)
                {
                    if (child.Sort.ToString().Length > _persize)
                    {
                        throw new Exception("排序值过大,请调整后再试");
                    }
                    child.Level = node.Level + 1;
                    child.FatherStr = $"{node.FatherStr}{child.Id},";
                    child.SortStr = BuildUnRootSortStr(child.Level, child.Sort, node.SortStr);

                    RecalculateTree<T, Tkey>(child, entities);
                }
            }
        }

        /// <summary>
        /// 基于排序获取默认串 这里指顶级的
        /// </summary>
        /// <param name="sort"></param>
        /// <returns></returns>
        private string FullRootSortStr(int sort)
        {
            return sort.ToString().PadLeft(_persize, '0') + "0".PadLeft((_maxlevel - 1) * _persize, '0');
        }

        /// <summary>
        /// 构建当前层级的Sortstr
        /// </summary>
        /// <param name="currentLevel"></param>
        /// <param name="currentSort"></param>
        /// <param name="fatherSortstr">为空表示当前是顶级</param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        private string BuildUnRootSortStr(int currentLevel, int currentSort, string fatherSortstr = "")
        {
            var fatherLevel = currentLevel - 1;
            if (currentLevel < _maxlevel)
            {
                if (string.IsNullOrEmpty(fatherSortstr))
                {
                    return FullRootSortStr(currentSort);//.ToString().PadLeft(_persize, '0') + "0".PadLeft(_persize * (_maxlevel - 1), '0');
                }
                else
                {
                    var str = fatherSortstr.Substring(0, (fatherLevel + 1) * _persize) + currentSort.ToString().PadLeft(_persize, '0');
                    if (currentLevel < (_maxlevel - 1))
                    {
                        str += "0".PadLeft(_persize * (_maxlevel - 1 - currentLevel), '0');
                    }
                    return str;
                }
            }
            else
            {
                throw new Exception($"当前超过设定的最大层级:{_maxlevel},无法继续执行");
            }
        }

        /// <summary>
        /// 自动排序 基于同层级排序到后面,只有当当前是0的时候生效
        /// </summary>
        /// <param name="TableName">应该是PropertyName</param>
        /// <param name="input"></param>
        /// <param name="step"></param>
        /// <returns></returns>
        public async Task AutoSort<Tkey>(string TableName, ILevelEntity<Tkey> input, int step = 10)
        {
            if (input.Sort == 0)
            {
                var dbType = _dbContext.GetType();
                var dbProperty = dbType.GetProperty(TableName);
                if (dbProperty != null)
                {
                    var dbSet = dbProperty.GetValue(_dbContext) as IQueryable<ILevelEntity<Tkey>>;
                    if (dbSet != null)
                    {

                        var _max = await dbSet
                            //.Where(x => EqualityComparer<Tkey>.Default.Equals(x.FatherId, input.FatherId))
                            .Where(x => x.FatherId.Equals(input.FatherId))
                            .OrderByDescending(x => x.Sort)
                            .Select(x => x.Sort)
                            .FirstOrDefaultAsync();
                        input.Sort = _max + 10;
                    }
                }
            }
        }


        /// <summary>
        /// 基于父级和当前自己的排序信息,构建对应的排序字符串
        /// </summary>
        /// <param name="currentEntity"></param>
        /// <param name="fatherEntity"></param>
        private void BuildSortStr<Tkey>(ILevelEntity<Tkey> currentEntity, ILevelEntity<Tkey> fatherEntity)
        {
            if (currentEntity.Level < _maxlevel)
            {
                if (fatherEntity == null)
                {
                    currentEntity.SortStr = FullRootSortStr(currentEntity.Sort);//.ToString().PadLeft(_persize, '0') + "0".PadLeft(_persize * (_maxlevel - 1), '0');
                }
                else
                {
                    if (!string.IsNullOrEmpty(fatherEntity.SortStr))
                    {
                        currentEntity.SortStr = fatherEntity.SortStr.Substring(0, (fatherEntity.Level + 1) * _persize) + currentEntity.Sort.ToString().PadLeft(_persize, '0');
                        //补充尾巴
                        if (currentEntity.Level < (_maxlevel - 1))
                        {
                            currentEntity.SortStr += "0".PadLeft(_persize * (_maxlevel - 1 - currentEntity.Level), '0');
                        }
                    }
                }
            }
        }


        /// <summary>
        /// 上级或者祖籍变更的替换,自己之后的不变,中间层级也不变 
        /// </summary>
        /// <param name="currentEntity"></param>
        /// <param name="fatherEntity">是自己的上级或者祖级</param>
        private void BuildFootSortStr<Tkey>(ILevelEntity<Tkey> currentEntity, ILevelEntity<Tkey> fatherEntity)
        {
            var _old_sort_str = currentEntity.SortStr;
            currentEntity.SortStr = fatherEntity.SortStr.Substring(0, (fatherEntity.Level + 1) * _persize);
            currentEntity.SortStr += _old_sort_str.Substring((fatherEntity.Level + 1) * _persize);
        }

        #region 历史案例代码

        ///// <summary>
        ///// 这是一个新增案例
        /////</summary>
        ///// <param name="input"></param>
        ///// <returns></returns>
        //public static async Task<RoleInfoDto> RoleAdd(IPasteClawDbContext _dbContext, RoleInfoAddDto input)
        //{
        //    if (input.Sort == 0)
        //    {
        //        var _max = await _dbContext.RoleInfo.Where(x => x.FatherId == input.FatherId)
        //            .OrderByDescending(x => x.Sort)
        //            .Select(x => x.Sort)
        //            .FirstOrDefaultAsync();
        //        input.Sort = _max + 10;
        //    }

        //    if (input.RoleType == 0)
        //    {
        //        if (String.IsNullOrEmpty(input.Model) || String.IsNullOrEmpty(input.Role))
        //        {
        //            throw new PasteCodeException("新增权限的时候,模块和权限必填,请重新填写!");
        //        }
        //        var find = await _dbContext.RoleInfo.Where(x => x.RoleType == 0 && x.Model == input.Model && x.Role == input.Role).Select(x => x.Id).FirstOrDefaultAsync();
        //        if (find > 0)
        //        {
        //            throw new PasteCodeException("已经有这个菜单项了,请勿重复添加!");
        //        }
        //    }
        //    if (input.RoleType == EnumRoleType.Menu)
        //    {
        //        if (!string.IsNullOrEmpty(input.Path))
        //        {
        //            if (input.FatherId == 0)
        //            {
        //                throw new PasteCodeException("非一级菜单,父级必选,请重新选择!");
        //            }
        //            var find = await _dbContext.RoleInfo.Where(x => x.RoleType == EnumRoleType.Menu && x.Path == input.Path).Select(x => x.Id).FirstOrDefaultAsync();
        //            if (find > 0)
        //            {
        //                throw new PasteCodeException("已经有这个菜单项了,请勿重复添加!");
        //            }
        //        }
        //    }

        //    //这里最好用事务包裹下
        //    //var info = ObjectMapper.Map<RoleInfoAddDto, RoleInfo>(input);
        //    var info = input.Adapt<RoleInfo>();
        //    info.IsEnable = true;//添加自定义
        //    _dbContext.Add(info);
        //    await _dbContext.SaveChangesAsync();
        //    //await AfterAdd(_dbContext, nameof(RoleInfo), info);
        //    await NewAfterAddAsync<RoleInfo, long>(_dbContext, info);
        //    await _dbContext.SaveChangesAsync();

        //    //var backinfo = ObjectMapper.Map<RoleInfo, RoleInfoDto>(info);
        //    var backinfo = info.Adapt<RoleInfoDto>();
        //    return backinfo;
        //}

        ///// <summary>
        ///// 这是一个更新案例
        /////</summary>
        ///// <param name="input"></param>
        ///// <returns></returns>
        //public static async Task<RoleInfoDto> RoleUpdate(IPasteClawDbContext _dbContext, RoleInfoUpdateDto input)
        //{
        //    if (input.Sort == 0)
        //    {
        //        var _max = await _dbContext.RoleInfo.Where(x => x.FatherId == input.FatherId)
        //            .OrderByDescending(x => x.Sort)
        //            .Select(x => x.Sort)
        //            .FirstOrDefaultAsync();
        //        input.Sort = _max + 10;
        //    }

        //    if (input.RoleType == 0)
        //    {
        //        if (String.IsNullOrEmpty(input.Model) || String.IsNullOrEmpty(input.Role))
        //        {
        //            throw new PasteCodeException("新增权限的时候,模块和权限必填,请重新填写!");
        //        }
        //        var find = await _dbContext.RoleInfo.Where(x => x.RoleType == 0 && x.Model == input.Model && x.Role == input.Role && x.Id != input.Id).Select(x => x.Id).FirstOrDefaultAsync();
        //        if (find > 0)
        //        {
        //            throw new PasteCodeException("已经有这个菜单项了,请勿重复添加!");
        //        }
        //    }
        //    if (input.RoleType == EnumRoleType.Menu)
        //    {
        //        if (!string.IsNullOrEmpty(input.Path))
        //        {
        //            if (input.FatherId == 0)
        //            {
        //                throw new PasteCodeException("非一级菜单,父级必选,请重新选择!");
        //            }
        //            var find = await _dbContext.RoleInfo.Where(x => x.RoleType == EnumRoleType.Menu && x.Path == input.Path && x.Id != input.Id).Select(x => x.Id).FirstOrDefaultAsync();
        //            if (find > 0)
        //            {
        //                throw new PasteCodeException("已经有这个菜单项了,请勿重复添加!");
        //            }
        //        }
        //    }

        //    var info = await _dbContext.RoleInfo.Where(x => x.Id == input.Id).FirstOrDefaultAsync();
        //    if (info == null || info == default)
        //    {
        //        throw new PasteCodeException("需要查询的信息不存在");
        //    }
        //    var oldFather = info.FatherStr;
        //    var oldLevel = info.Level;
        //    //ObjectMapper.Map<RoleInfoUpdateDto, RoleInfo>(input, info);
        //    input.Adapt(info);
        //    //await AfterUpdate(_dbContext, nameof(RoleInfo), info);
        //    await NewAfterUpdateAsync<RoleInfo, long>(_dbContext, info, oldFather, oldLevel);
        //    //var backinfo = ObjectMapper.Map<RoleInfo, RoleInfoDto>(info);?
        //    var backinfo = info.Adapt<RoleInfoDto>();
        //    await _dbContext.SaveChangesAsync();
        //    return backinfo;
        //}

        ///// <summary>
        ///// 新增后 注意外部要保存下
        ///// </summary>
        ///// <param name="_dbContext"></param>
        ///// <param name="TableName">应该是PropertyName</param>
        ///// <param name="info"></param>
        //[Obsolete("Use NewAfterAddAsync")]
        //public static async Task AfterAdd<Tkey>(IPasteClawDbContext _dbContext, string TableName, ILevelEntity<Tkey> info)
        //{
        //    info.SortStr = info.Sort.ToString().PadLeft(_persize, '0') + "0".PadLeft((_maxlevel - 1) * _persize, '0');
        //    //if (EqualityComparer<Tkey>.Default.Equals(info.FatherId, default(Tkey)))
        //    if (default(Tkey).Equals(info.FatherId))
        //    {
        //        info.FatherStr = $"{info.Id},";
        //        //info.RootId = info.Id;
        //        return;
        //    }

        //    var dbType = _dbContext.GetType();
        //    var dbProperty = dbType.GetProperty(TableName);
        //    if (dbProperty != null)
        //    {
        //        var dbSet = dbProperty.GetValue(_dbContext) as IQueryable<ILevelEntity<Tkey>>;
        //        if (dbSet != null)
        //        {

        //            var father = await dbSet
        //                //.Where(x => EqualityComparer<Tkey>.Default.Equals(x.Id, info.FatherId))
        //                .Where(x => x.Id.Equals(info.FatherId))
        //                .AsNoTracking()
        //                .FirstOrDefaultAsync();
        //            if (father != null && father != default)
        //            {
        //                info.FatherStr = $"{father.FatherStr}{info.Id},";
        //                info.Level = (father.Level + 1);
        //                info.FatherId = father.Id;
        //                //info.RootId = father.RootId != 0 ? father.RootId : father.Id;
        //                BuildSortStr(info, father);
        //            }
        //            else
        //            {
        //                info.FatherId = default(Tkey);
        //            }

        //        }
        //    }
        //}

        ///// <summary>
        ///// 更新后 注意外部要保存下 这里有问题 要基于之前的关系链查找
        ///// </summary>
        ///// <param name="_dbContext"></param>
        ///// <param name="TableName">应该是PropertyName</param>
        ///// <param name="info"></param>
        ///// <returns></returns>
        //[Obsolete("use NewAfterUpdate")]
        //public static async Task AfterUpdate<Tkey>( string TableName, ILevelEntity<Tkey> info)
        //{
        //    IQueryable<ILevelEntity<Tkey>> dbSet = null;
        //    var dbType = _dbContext.GetType();
        //    var dbProperty = dbType.GetProperty(TableName);
        //    if (dbProperty != null)
        //    {
        //        dbSet = dbProperty.GetValue(_dbContext) as IQueryable<ILevelEntity<Tkey>>;
        //    }
        //    if (dbSet == null)
        //    {
        //        return;
        //    }
        //    var old_father_str = info.FatherStr;
        //    var _chat_level = info.Level;

        //    //if (!EqualityComparer<Tkey>.Default.Equals(info.FatherId, default(Tkey)))
        //    if (default(Tkey).Equals(info.FatherId))
        //    {
        //        var father = await dbSet
        //             //.Where(x => EqualityComparer<Tkey>.Default.Equals(x.Id,info.FatherId))
        //             .Where(x => x.Id.Equals(info.FatherId))
        //            .AsNoTracking()
        //            .FirstOrDefaultAsync();
        //        if (father != null && father != default)
        //        {
        //            info.Level = father.Level + 1;
        //            info.FatherStr = $"{father.FatherStr}{info.Id},";
        //            //info.RootId = father.RootId;
        //            BuildSortStr(info, father);
        //        }
        //        else
        //        {
        //            info.FatherId = default(Tkey);
        //            info.FatherStr = $"{info.Id},";
        //            info.Level = 0;
        //            //info.RootId = info.Id;
        //            BuildSortStr(info, null);
        //        }
        //    }
        //    else
        //    {
        //        info.FatherId = default(Tkey);
        //        info.FatherStr = $"{info.Id},";
        //        info.Level = 0;
        //        //info.RootId = info.Id;
        //        BuildSortStr(info, null);
        //    }
        //    _chat_level = _chat_level - (info.Level);
        //    if (!String.IsNullOrEmpty(old_father_str))
        //    {
        //        var suns = await dbSet.Where(x => !x.Id.Equals(info.Id) && x.FatherStr.StartsWith(old_father_str)).ToListAsync();
        //        if (suns != null && suns.Count > 0)
        //        {
        //            foreach (var item in suns)
        //            {
        //                item.FatherStr = item.FatherStr.Replace(old_father_str, info.FatherStr);
        //                item.Level = item.Level + _chat_level;
        //                //item.RootId = info.RootId;
        //                BuildFootSortStr(item, info);
        //            }
        //        }
        //    }
        //}


        #endregion

    }
}
​ ​