Compare commits
	
		
			20 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					fb1699ce80 | ||
| 
						 | 
					44adddbcd4 | ||
| 
						 | 
					0eab889452 | ||
| 
						 | 
					e14d39a459 | ||
| 
						 | 
					7575264ede | ||
| 
						 | 
					3e1a077b96 | ||
| 
						 | 
					a921cb8400 | ||
| 
						 | 
					4de7c31ed7 | ||
| 
						 | 
					08326a2cfd | ||
| 
						 | 
					e045de5acb | ||
| 
						 | 
					d3bef31aa6 | ||
| 
						 | 
					347d4d6e5d | ||
| 
						 | 
					b006a066e1 | ||
| 
						 | 
					e331bc5d3c | ||
| 
						 | 
					2e81806231 | ||
| 
						 | 
					37b48cf221 | ||
| 
						 | 
					5997487434 | ||
| 
						 | 
					4ce843182f | ||
| 
						 | 
					a4aa000cf0 | ||
| 
						 | 
					01aa6ca066 | 
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -367,3 +367,4 @@ FodyWeavers.xsd
 | 
			
		||||
/src/*pro*
 | 
			
		||||
/src/*pro*/
 | 
			
		||||
/src/ThingsGateway.Server/Configuration/GiteeOAuthSettings.json
 | 
			
		||||
/src/.idea/
 | 
			
		||||
 
 | 
			
		||||
@@ -122,6 +122,7 @@ using Microsoft.AspNetCore.Components;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
#pragma warning disable CA1849
 | 
			
		||||
#pragma warning disable CA2007
 | 
			
		||||
#pragma warning disable CS0162
 | 
			
		||||
#pragma warning disable CS8632
 | 
			
		||||
@@ -276,6 +277,7 @@ namespace {namespaceName}
 | 
			
		||||
#pragma warning restore CS8632
 | 
			
		||||
#pragma warning restore CS0162
 | 
			
		||||
#pragma warning restore CA2007
 | 
			
		||||
#pragma warning restore CA1849
 | 
			
		||||
");
 | 
			
		||||
        var bases = class_symbol.GetTypeHierarchy().Where(t => !SymbolEqualityComparer.Default.Equals(t, class_symbol));
 | 
			
		||||
        var members = class_symbol.GetMembers() // members of the type itself
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
 | 
			
		||||
<div align="center"><h1 align="center">ThingsBlazor</a></h1></div>
 | 
			
		||||
<div align="center"><h1 align="center">ThingsBlazor</h1></div>
 | 
			
		||||
<div align="center"><h3 align="center">权限管理框架</h3></div>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -38,9 +38,9 @@ public sealed class OperDescAttribute : MoAttribute
 | 
			
		||||
 | 
			
		||||
    static OperDescAttribute()
 | 
			
		||||
    {
 | 
			
		||||
        // 创建长时间运行的后台任务,并将日志消息队列中数据写入存储中
 | 
			
		||||
        Task.Factory.StartNew(ProcessQueue, TaskCreationOptions.LongRunning);
 | 
			
		||||
        AppService = App.RootServices.GetService<IAppService>();
 | 
			
		||||
        // 创建长时间运行的后台任务,并将日志消息队列中数据写入存储中
 | 
			
		||||
        Task.Factory.StartNew(ProcessQueueAsync, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public OperDescAttribute(string description, bool isRecordPar = true, object localizerType = null)
 | 
			
		||||
@@ -93,7 +93,7 @@ public sealed class OperDescAttribute : MoAttribute
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 将日志消息写入数据库中
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    private static async Task ProcessQueue()
 | 
			
		||||
    private static async Task ProcessQueueAsync()
 | 
			
		||||
    {
 | 
			
		||||
        var appLifetime = App.RootServices!.GetService<IHostApplicationLifetime>()!;
 | 
			
		||||
        while (!appLifetime.ApplicationStopping.IsCancellationRequested)
 | 
			
		||||
 
 | 
			
		||||
@@ -34,12 +34,16 @@ public class FileController : ControllerBase
 | 
			
		||||
            return BadRequest("Invalid file name.");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        var filePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", fileName);
 | 
			
		||||
 | 
			
		||||
        if (!System.IO.File.Exists(filePath))
 | 
			
		||||
        var root = Directory.GetCurrentDirectory();
 | 
			
		||||
        var wwwroot = Path.Combine(root, "wwwroot");
 | 
			
		||||
        var filePath = Path.Combine(wwwroot, fileName);
 | 
			
		||||
        // 防止路径穿越攻击
 | 
			
		||||
#pragma warning disable CA3003
 | 
			
		||||
        if (!filePath.StartsWith(wwwroot, StringComparison.OrdinalIgnoreCase) || !System.IO.File.Exists(filePath))
 | 
			
		||||
        {
 | 
			
		||||
            return NotFound();
 | 
			
		||||
        }
 | 
			
		||||
#pragma warning restore CA3003
 | 
			
		||||
 | 
			
		||||
        var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -30,7 +30,7 @@ public class AdminOAuthHandler<TOptions>(
 | 
			
		||||
{
 | 
			
		||||
    static AdminOAuthHandler()
 | 
			
		||||
    {
 | 
			
		||||
        Task.Factory.StartNew(Insertable, TaskCreationOptions.LongRunning);
 | 
			
		||||
        Task.Factory.StartNew(InsertableAsync, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -41,7 +41,7 @@ public class AdminOAuthHandler<TOptions>(
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 创建访问日志
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    private static async Task Insertable()
 | 
			
		||||
    private static async Task InsertableAsync()
 | 
			
		||||
    {
 | 
			
		||||
        var db = DbContext.GetDB<SysOperateLog>();
 | 
			
		||||
        var appLifetime = App.RootServices!.GetService<IHostApplicationLifetime>()!;
 | 
			
		||||
 
 | 
			
		||||
@@ -128,18 +128,19 @@ internal sealed class SysOrgService : BaseService<SysOrg>, ISysOrgService
 | 
			
		||||
    [OperDesc("DeleteOrg")]
 | 
			
		||||
    public async Task<bool> DeleteOrgAsync(IEnumerable<long> ids)
 | 
			
		||||
    {
 | 
			
		||||
        var sysDeleteOrgList = new List<long>();//需要删除的组织ID集合
 | 
			
		||||
        var sysOrgList = await GetAllAsync().ConfigureAwait(false);//获取所有组织
 | 
			
		||||
        foreach (var it in ids)
 | 
			
		||||
        {
 | 
			
		||||
            var children = SysOrgService.GetSysOrgChildren(sysOrgList, it);//查找下级组织
 | 
			
		||||
            sysDeleteOrgList.AddRange(children.Select(it => it.Id).ToList());
 | 
			
		||||
            sysDeleteOrgList.Add(it);
 | 
			
		||||
        }
 | 
			
		||||
        //获取所有ID
 | 
			
		||||
        if (ids.Any())
 | 
			
		||||
        if (sysDeleteOrgList.Count != 0)
 | 
			
		||||
        {
 | 
			
		||||
            using var db = GetDB();
 | 
			
		||||
            var sysOrgList = await GetAllAsync().ConfigureAwait(false);//获取所有组织
 | 
			
		||||
            var sysDeleteOrgList = new List<long>();//需要删除的组织ID集合
 | 
			
		||||
            foreach (var it in ids)
 | 
			
		||||
            {
 | 
			
		||||
                var children = SysOrgService.GetSysOrgChildren(sysOrgList, it);//查找下级组织
 | 
			
		||||
                sysDeleteOrgList.AddRange(children.Select(it => it.Id).ToList());
 | 
			
		||||
                sysDeleteOrgList.Add(it);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            //如果组织下有用户则不能删除
 | 
			
		||||
            if (await db.Queryable<SysUser>().AnyAsync(it => sysDeleteOrgList.Contains(it.OrgId)).ConfigureAwait(false))
 | 
			
		||||
            {
 | 
			
		||||
 
 | 
			
		||||
@@ -75,7 +75,7 @@ public class SysPositionService : BaseService<SysPosition>, ISysPositionService
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var dels = (await GetAllAsync().ConfigureAwait(false)).Where(a => ids.Contains(a.Id));
 | 
			
		||||
            await SysUserService.CheckApiDataScopeAsync(dels.Select(a => a.OrgId).ToList(), dels.Select(a => a.CreateUserId).ToList()).ConfigureAwait(false);
 | 
			
		||||
            await SysUserService.CheckApiDataScopeAsync(dels.Select(a => a.OrgId), dels.Select(a => a.CreateUserId)).ConfigureAwait(false);
 | 
			
		||||
            //删除职位
 | 
			
		||||
            var result = await base.DeleteAsync(ids).ConfigureAwait(false);
 | 
			
		||||
            if (result)
 | 
			
		||||
 
 | 
			
		||||
@@ -29,7 +29,7 @@ public interface ISysResourceService
 | 
			
		||||
    /// <param name="resourceList">资源列表</param>
 | 
			
		||||
    /// <param name="parentId">父ID</param>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    IEnumerable<SysResource> ConstructMenuTrees(IEnumerable<SysResource> resourceList, long parentId = 0);
 | 
			
		||||
    IEnumerable<SysResource> ConstructMenuTrees(List<SysResource> resourceList, long parentId = 0);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 复制资源到其他模块
 | 
			
		||||
@@ -44,7 +44,7 @@ public interface ISysResourceService
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="ids">id列表</param>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    Task<bool> DeleteResourceAsync(IEnumerable<long> ids);
 | 
			
		||||
    Task<bool> DeleteResourceAsync(HashSet<long> ids);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 从缓存/数据库读取全部资源列表
 | 
			
		||||
 
 | 
			
		||||
@@ -75,10 +75,10 @@ internal sealed class SysResourceService : BaseService<SysResource>, ISysResourc
 | 
			
		||||
    /// <param name="ids">id列表</param>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    [OperDesc("DeleteResource")]
 | 
			
		||||
    public async Task<bool> DeleteResourceAsync(IEnumerable<long> ids)
 | 
			
		||||
    public async Task<bool> DeleteResourceAsync(HashSet<long> ids)
 | 
			
		||||
    {
 | 
			
		||||
        //删除
 | 
			
		||||
        if (ids.Any())
 | 
			
		||||
        if (ids.Count != 0)
 | 
			
		||||
        {
 | 
			
		||||
            //获取所有菜单和按钮
 | 
			
		||||
            var resourceList = await GetAllAsync().ConfigureAwait(false);
 | 
			
		||||
@@ -86,10 +86,11 @@ internal sealed class SysResourceService : BaseService<SysResource>, ISysResourc
 | 
			
		||||
            var delSysResources = resourceList.Where(it => ids.Contains(it.Id));
 | 
			
		||||
            //找到要删除的模块
 | 
			
		||||
            var delModules = resourceList.Where(a => a.Category == ResourceCategoryEnum.Module).Where(it => ids.Contains(it.Id));
 | 
			
		||||
            if (delModules.Any())
 | 
			
		||||
 | 
			
		||||
            //获取模块下的所有列表
 | 
			
		||||
            var delHashSet = delModules.Select(a => a.Id).ToHashSet();
 | 
			
		||||
            if (delHashSet.Count != 0)
 | 
			
		||||
            {
 | 
			
		||||
                //获取模块下的所有列表
 | 
			
		||||
                var delHashSet = delModules.Select(a => a.Id).ToHashSet();
 | 
			
		||||
                var delModuleResources = resourceList.Where(it => delHashSet.Contains(it.Module));
 | 
			
		||||
                delSysResources = delSysResources.Concat(delModuleResources).ToHashSet();
 | 
			
		||||
            }
 | 
			
		||||
@@ -345,17 +346,14 @@ internal sealed class SysResourceService : BaseService<SysResource>, ISysResourc
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public IEnumerable<SysResource> ConstructMenuTrees(IEnumerable<SysResource> resourceList, long parentId = 0)
 | 
			
		||||
    public IEnumerable<SysResource> ConstructMenuTrees(List<SysResource> resourceList, long parentId = 0)
 | 
			
		||||
    {
 | 
			
		||||
        //找下级资源ID列表
 | 
			
		||||
        var resources = resourceList.Where(it => it.ParentId == parentId).OrderBy(it => it.SortCode);
 | 
			
		||||
        if (resources.Any())//如果数量大于0
 | 
			
		||||
        foreach (var item in resources)//遍历资源
 | 
			
		||||
        {
 | 
			
		||||
            foreach (var item in resources)//遍历资源
 | 
			
		||||
            {
 | 
			
		||||
                var children = ConstructMenuTrees(resourceList, item.Id).ToList();//添加子节点
 | 
			
		||||
                item.Children = children.Count > 0 ? children : null;
 | 
			
		||||
            }
 | 
			
		||||
            var children = ConstructMenuTrees(resourceList, item.Id).ToList();//添加子节点
 | 
			
		||||
            item.Children = children.Count > 0 ? children : null;
 | 
			
		||||
        }
 | 
			
		||||
        return resources;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -30,7 +30,7 @@ public interface ISysRoleService
 | 
			
		||||
    /// 删除角色
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="ids">id列表</param>
 | 
			
		||||
    Task<bool> DeleteRoleAsync(IEnumerable<long> ids);
 | 
			
		||||
    Task<bool> DeleteRoleAsync(HashSet<long> ids);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 从缓存/数据库获取全部角色信息
 | 
			
		||||
@@ -43,7 +43,7 @@ public interface ISysRoleService
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="input">角色id列表</param>
 | 
			
		||||
    /// <returns>角色列表</returns>
 | 
			
		||||
    Task<IEnumerable<SysRole>> GetRoleListByIdListAsync(IEnumerable<long> input);
 | 
			
		||||
    Task<IEnumerable<SysRole>> GetRoleListByIdListAsync(HashSet<long> input);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 根据用户id获取角色列表
 | 
			
		||||
 
 | 
			
		||||
@@ -61,42 +61,46 @@ internal sealed class SysRoleService : BaseService<SysRole>, ISysRoleService
 | 
			
		||||
 | 
			
		||||
        var topOrgList = sysOrgList.Where(it => it.ParentId == 0);//获取顶级机构
 | 
			
		||||
        var globalRole = sysRoles.Where(it => it.Category == RoleCategoryEnum.Global);//获取全局角色
 | 
			
		||||
        if (globalRole.Any())
 | 
			
		||||
        var children = globalRole.Select(it => new RoleTreeOutput
 | 
			
		||||
        {
 | 
			
		||||
            result.Add(new RoleTreeOutput()
 | 
			
		||||
            {
 | 
			
		||||
                Id = CommonUtils.GetSingleId(),
 | 
			
		||||
                Name = Localizer["Global"],
 | 
			
		||||
                Children = globalRole.Select(it => new RoleTreeOutput
 | 
			
		||||
                {
 | 
			
		||||
                    Id = it.Id,
 | 
			
		||||
                    Name = it.Name,
 | 
			
		||||
                    IsRole = true
 | 
			
		||||
                }).ToList()
 | 
			
		||||
            });//添加全局角色
 | 
			
		||||
        }
 | 
			
		||||
            Id = it.Id,
 | 
			
		||||
            Name = it.Name,
 | 
			
		||||
            IsRole = true
 | 
			
		||||
        }).ToList();
 | 
			
		||||
 | 
			
		||||
        result.Add(new RoleTreeOutput()
 | 
			
		||||
        {
 | 
			
		||||
            Id = CommonUtils.GetSingleId(),
 | 
			
		||||
            Name = Localizer["Global"],
 | 
			
		||||
            Children = children
 | 
			
		||||
        });//添加全局角色
 | 
			
		||||
        //遍历顶级机构
 | 
			
		||||
        foreach (var org in topOrgList)
 | 
			
		||||
        {
 | 
			
		||||
            var childIds = await _sysOrgService.GetOrgChildIdsAsync(org.Id, true, sysOrgList).ConfigureAwait(false);//获取机构下的所有子级ID
 | 
			
		||||
            var childRoles = sysRoles.Where(it => it.OrgId != 0 && childIds.Contains(it.OrgId));//获取机构下的所有角色
 | 
			
		||||
            if (childRoles.Any())
 | 
			
		||||
 | 
			
		||||
            List<RoleTreeOutput> childrenRoleTreeOutputs = new();
 | 
			
		||||
 | 
			
		||||
            foreach (var it in childRoles)
 | 
			
		||||
            {
 | 
			
		||||
                childrenRoleTreeOutputs.Add(new RoleTreeOutput()
 | 
			
		||||
                {
 | 
			
		||||
                    Id = it.Id,
 | 
			
		||||
                    Name = it.Name,
 | 
			
		||||
                    IsRole = true
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
            if (childrenRoleTreeOutputs.Count > 0)
 | 
			
		||||
 | 
			
		||||
            {
 | 
			
		||||
                var roleTreeOutput = new RoleTreeOutput
 | 
			
		||||
                {
 | 
			
		||||
                    Id = org.Id,
 | 
			
		||||
                    Name = org.Name,
 | 
			
		||||
                    IsRole = false
 | 
			
		||||
                    IsRole = false,
 | 
			
		||||
                    Children = childrenRoleTreeOutputs
 | 
			
		||||
                };//实例化角色树
 | 
			
		||||
                foreach (var it in childRoles)
 | 
			
		||||
                {
 | 
			
		||||
                    roleTreeOutput.Children.Add(new RoleTreeOutput()
 | 
			
		||||
                    {
 | 
			
		||||
                        Id = it.Id,
 | 
			
		||||
                        Name = it.Name,
 | 
			
		||||
                        IsRole = true
 | 
			
		||||
                    });
 | 
			
		||||
                }
 | 
			
		||||
                result.Add(roleTreeOutput);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@@ -147,7 +151,7 @@ internal sealed class SysRoleService : BaseService<SysRole>, ISysRoleService
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="input">角色id列表</param>
 | 
			
		||||
    /// <returns>角色列表</returns>
 | 
			
		||||
    public async Task<IEnumerable<SysRole>> GetRoleListByIdListAsync(IEnumerable<long> input)
 | 
			
		||||
    public async Task<IEnumerable<SysRole>> GetRoleListByIdListAsync(HashSet<long> input)
 | 
			
		||||
    {
 | 
			
		||||
        var roles = await GetAllAsync().ConfigureAwait(false);
 | 
			
		||||
        var roleList = roles.Where(it => input.Contains(it.Id));
 | 
			
		||||
@@ -162,7 +166,7 @@ internal sealed class SysRoleService : BaseService<SysRole>, ISysRoleService
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="ids">id列表</param>
 | 
			
		||||
    [OperDesc("DeleteRole")]
 | 
			
		||||
    public async Task<bool> DeleteRoleAsync(IEnumerable<long> ids)
 | 
			
		||||
    public async Task<bool> DeleteRoleAsync(HashSet<long> ids)
 | 
			
		||||
    {
 | 
			
		||||
        var sysRoles = await GetAllAsync().ConfigureAwait(false);//获取所有角色
 | 
			
		||||
        var hasSuperAdmin = sysRoles.Any(it => it.Id == RoleConst.SuperAdminRoleId && ids.Contains(it.Id));//判断是否有超级管理员
 | 
			
		||||
@@ -170,10 +174,10 @@ internal sealed class SysRoleService : BaseService<SysRole>, ISysRoleService
 | 
			
		||||
            throw Oops.Bah(Localizer["CanotDeleteAdmin"]);
 | 
			
		||||
 | 
			
		||||
        var dels = (await GetAllAsync().ConfigureAwait(false)).Where(a => ids.Contains(a.Id));
 | 
			
		||||
        await SysUserService.CheckApiDataScopeAsync(dels.Select(a => a.OrgId).ToList(), dels.Select(a => a.CreateUserId).ToList()).ConfigureAwait(false);
 | 
			
		||||
        await SysUserService.CheckApiDataScopeAsync(dels.Select(a => a.OrgId), dels.Select(a => a.CreateUserId)).ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
        //数据库是string所以这里转下
 | 
			
		||||
        var targetIds = ids.Select(it => it.ToString());
 | 
			
		||||
        var targetIds = ids.Select(it => it.ToString()).ToList();
 | 
			
		||||
        //定义删除的关系
 | 
			
		||||
        var delRelations = new List<RelationCategoryEnum> {
 | 
			
		||||
            RelationCategoryEnum.RoleHasResource,
 | 
			
		||||
@@ -184,7 +188,7 @@ internal sealed class SysRoleService : BaseService<SysRole>, ISysRoleService
 | 
			
		||||
        //事务
 | 
			
		||||
        var result = await db.UseTranAsync(async () =>
 | 
			
		||||
        {
 | 
			
		||||
            await db.Deleteable<SysRole>().In(ids.ToList()).ExecuteCommandHasChangeAsync().ConfigureAwait(false);//删除
 | 
			
		||||
            await db.Deleteable<SysRole>().In(ids).ExecuteCommandHasChangeAsync().ConfigureAwait(false);//删除
 | 
			
		||||
            //删除关系表角色与资源关系,角色与权限关系
 | 
			
		||||
            await db.Deleteable<SysRelation>(it => ids.Contains(it.ObjectId) && delRelations.Contains(it.Category)).ExecuteCommandAsync().ConfigureAwait(false);
 | 
			
		||||
            //删除关系表角色与用户关系
 | 
			
		||||
@@ -317,7 +321,7 @@ internal sealed class SysRoleService : BaseService<SysRole>, ISysRoleService
 | 
			
		||||
            #region 角色权限处理.
 | 
			
		||||
            var defaultDataScope = sysRole.DefaultDataScope;//获取默认数据范围
 | 
			
		||||
 | 
			
		||||
            if (menusList.Any())
 | 
			
		||||
            if (relationRoles.Count != 0)
 | 
			
		||||
            {
 | 
			
		||||
                //获取权限授权树
 | 
			
		||||
                var permissions = App.GetService<IApiPermissionService>().PermissionTreeSelector(menusList.Select(it => it.Href));
 | 
			
		||||
 
 | 
			
		||||
@@ -58,7 +58,7 @@ public interface ISysUserService
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="ids">用户ID列表。</param>
 | 
			
		||||
    /// <returns>是否删除成功。</returns>
 | 
			
		||||
    Task<bool> DeleteUserAsync(IEnumerable<long> ids);
 | 
			
		||||
    Task<bool> DeleteUserAsync(HashSet<long> ids);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 从缓存中删除用户信息。
 | 
			
		||||
 
 | 
			
		||||
@@ -587,7 +587,7 @@ internal sealed class SysUserService : BaseService<SysUser>, ISysUserService
 | 
			
		||||
            #region 用户权限处理.
 | 
			
		||||
 | 
			
		||||
            //获取菜单信息
 | 
			
		||||
            if (menusList.Any())
 | 
			
		||||
            if (relationUsers.Count != 0)
 | 
			
		||||
            {
 | 
			
		||||
                //获取权限授权树
 | 
			
		||||
                var permissions = App.GetService<IApiPermissionService>().PermissionTreeSelector(menusList.Select(it => it.Href));
 | 
			
		||||
@@ -642,7 +642,7 @@ internal sealed class SysUserService : BaseService<SysUser>, ISysUserService
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    [OperDesc("DeleteUser")]
 | 
			
		||||
    public async Task<bool> DeleteUserAsync(IEnumerable<long> ids)
 | 
			
		||||
    public async Task<bool> DeleteUserAsync(HashSet<long> ids)
 | 
			
		||||
    {
 | 
			
		||||
        using var db = GetDB();
 | 
			
		||||
        var containsSuperAdmin = await db.Queryable<SysUser>().Where(it => it.Id == RoleConst.SuperAdminId && ids.Contains(it.Id)).AnyAsync().ConfigureAwait(false);//判断是否有超管
 | 
			
		||||
@@ -672,7 +672,7 @@ internal sealed class SysUserService : BaseService<SysUser>, ISysUserService
 | 
			
		||||
            .ExecuteCommandAsync().ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
            //删除用户
 | 
			
		||||
            await db.Deleteable<SysUser>().In(ids.ToList()).ExecuteCommandHasChangeAsync().ConfigureAwait(false);//删除
 | 
			
		||||
            await db.Deleteable<SysUser>().In(ids).ExecuteCommandHasChangeAsync().ConfigureAwait(false);//删除
 | 
			
		||||
 | 
			
		||||
            //删除关系表用户与资源关系,用户与权限关系,用户与角色关系
 | 
			
		||||
            await db.Deleteable<SysRelation>(it => ids.Contains(it.ObjectId) && delRelations.Contains(it.Category)).ExecuteCommandAsync().ConfigureAwait(false);
 | 
			
		||||
@@ -718,16 +718,16 @@ internal sealed class SysUserService : BaseService<SysUser>, ISysUserService
 | 
			
		||||
    public void DeleteUserFromCache(IEnumerable<long> ids)
 | 
			
		||||
    {
 | 
			
		||||
        var userIds = ids.Select(it => it.ToString()).ToArray();//id转string列表
 | 
			
		||||
        var sysUsers = App.CacheService.HashGet<SysUser>(CacheConst.Cache_SysUser, userIds).Where(it => it != null);//获取用户列表
 | 
			
		||||
        if (sysUsers.Any() == true)
 | 
			
		||||
        var sysUsers = App.CacheService.HashGet<SysUser>(CacheConst.Cache_SysUser, userIds);//获取用户列表
 | 
			
		||||
        if (sysUsers.Count != 0)
 | 
			
		||||
        {
 | 
			
		||||
            var accounts = sysUsers.Where(it => it != null).Select(it => it.Account).ToArray();//账号集合
 | 
			
		||||
            var phones = sysUsers.Select(it => it.Phone);//手机号集合
 | 
			
		||||
            var phones = sysUsers.Select(it => it?.Phone);//手机号集合
 | 
			
		||||
 | 
			
		||||
            if (sysUsers.Any(it => it.TenantId != null))//如果有租户id不是空的表示是多租户模式
 | 
			
		||||
            if (sysUsers.Any(it => it?.TenantId != null))//如果有租户id不是空的表示是多租户模式
 | 
			
		||||
            {
 | 
			
		||||
                var userAccountKey = CacheConst.Cache_SysUserAccount;
 | 
			
		||||
                var tenantIds = sysUsers.Where(it => it.TenantId != null).Select(it => it.TenantId.Value).Distinct().ToArray();//租户id列表
 | 
			
		||||
                var tenantIds = sysUsers.Where(it => it?.TenantId != null).Select(it => it.TenantId.Value).Distinct().ToArray();//租户id列表
 | 
			
		||||
                foreach (var tenantId in tenantIds)
 | 
			
		||||
                {
 | 
			
		||||
                    userAccountKey = $"{userAccountKey}:{tenantId}";
 | 
			
		||||
 
 | 
			
		||||
@@ -145,7 +145,7 @@ internal sealed class VerificatInfoService : BaseService<VerificatInfo>, IVerifi
 | 
			
		||||
    public void Delete(long id)
 | 
			
		||||
    {
 | 
			
		||||
        using var db = GetDB();
 | 
			
		||||
        db.Deleteable<VerificatInfo>(id).ExecuteCommand();
 | 
			
		||||
        db.Deleteable<VerificatInfo>(a => a.Id == id).ExecuteCommand();
 | 
			
		||||
        VerificatInfoService.RemoveCache(id);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -31,12 +31,13 @@ public partial class ChoiceTable<TItem> where TItem : class, new()
 | 
			
		||||
 | 
			
		||||
    public async Task OnAddAsync(IEnumerable<TItem> selectorOutputs)
 | 
			
		||||
    {
 | 
			
		||||
        if (MaxCount > 0 && selectorOutputs.Count() + SelectedRows.Count > MaxCount)
 | 
			
		||||
        var data = selectorOutputs is IReadOnlyCollection<TItem> list ? list : selectorOutputs.ToList();
 | 
			
		||||
        if (MaxCount > 0 && data.Count + SelectedRows.Count > MaxCount)
 | 
			
		||||
        {
 | 
			
		||||
            await ToastService.Warning(AdminLocalizer["MaxCount"]);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        foreach (var item in selectorOutputs)
 | 
			
		||||
        foreach (var item in data)
 | 
			
		||||
        {
 | 
			
		||||
            SelectedRows.Add(item);
 | 
			
		||||
            await table2.QueryAsync();
 | 
			
		||||
 
 | 
			
		||||
@@ -93,7 +93,7 @@ public partial class SysResourcePage
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            var result = await SysResourceService.DeleteResourceAsync(sysResources.Select(a => a.Id));
 | 
			
		||||
            var result = await SysResourceService.DeleteResourceAsync(sysResources.Select(a => a.Id).ToHashSet());
 | 
			
		||||
            if (ReloadUser != null)
 | 
			
		||||
            {
 | 
			
		||||
                await ReloadUser();
 | 
			
		||||
 
 | 
			
		||||
@@ -50,7 +50,7 @@ public partial class SysRolePage
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            return await SysRoleService.DeleteRoleAsync(sysRoles.Select(a => a.Id));
 | 
			
		||||
            return await SysRoleService.DeleteRoleAsync(sysRoles.Select(a => a.Id).ToHashSet());
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -45,7 +45,7 @@ public partial class SysUserPage
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            return await SysUserService.DeleteUserAsync(sysUsers.Select(a => a.Id));
 | 
			
		||||
            return await SysUserService.DeleteUserAsync(sysUsers.Select(a => a.Id).ToHashSet());
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -443,10 +443,7 @@ public static class ObjectExtensions
 | 
			
		||||
        where TAttribute : Attribute
 | 
			
		||||
    {
 | 
			
		||||
        // 空检查
 | 
			
		||||
        if (type == null)
 | 
			
		||||
        {
 | 
			
		||||
            throw new ArgumentNullException(nameof(type));
 | 
			
		||||
        }
 | 
			
		||||
        ArgumentNullException.ThrowIfNull(type);
 | 
			
		||||
 | 
			
		||||
        // 检查特性并获取特性对象
 | 
			
		||||
        return type.IsDefined(typeof(TAttribute), inherit)
 | 
			
		||||
 
 | 
			
		||||
@@ -28,6 +28,10 @@ public class WebsiteOptions : IConfigurableOptions
 | 
			
		||||
    public bool Demo { get; set; }
 | 
			
		||||
 | 
			
		||||
    public bool WebPageEnable { get; set; } = true;
 | 
			
		||||
 | 
			
		||||
    public int MaxBlazorConnections { get; set; } = 5;
 | 
			
		||||
    public bool BlazorConnectionLimitEnable { get; set; } = false;
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 是否显示关于页面
 | 
			
		||||
    /// </summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -13,7 +13,7 @@
 | 
			
		||||
	<ItemGroup>
 | 
			
		||||
		<PackageReference Include="BootstrapBlazor.TableExport" Version="9.2.6" />
 | 
			
		||||
		<PackageReference Include="Yitter.IdGenerator" Version="1.0.14" />
 | 
			
		||||
		<PackageReference Include="BootstrapBlazor" Version="9.8.1" />
 | 
			
		||||
		<PackageReference Include="BootstrapBlazor" Version="9.9.0" />
 | 
			
		||||
	</ItemGroup>
 | 
			
		||||
 | 
			
		||||
	<ItemGroup>
 | 
			
		||||
 
 | 
			
		||||
@@ -43,12 +43,12 @@ public class SugarAopService : ISugarAopService
 | 
			
		||||
                }
 | 
			
		||||
                if (sql.StartsWith("INSERT"))
 | 
			
		||||
                {
 | 
			
		||||
                    Console.ForegroundColor = ConsoleColor.Yellow;
 | 
			
		||||
                    Console.ForegroundColor = ConsoleColor.Blue;
 | 
			
		||||
                    DbContext.WriteLog($"添加{config.ConfigId}库操作");
 | 
			
		||||
                }
 | 
			
		||||
                if (sql.StartsWith("DELETE"))
 | 
			
		||||
                {
 | 
			
		||||
                    Console.ForegroundColor = ConsoleColor.Red;
 | 
			
		||||
                    Console.ForegroundColor = ConsoleColor.Blue;
 | 
			
		||||
                    DbContext.WriteLog($"删除{config.ConfigId}库操作");
 | 
			
		||||
                }
 | 
			
		||||
                DbContext.WriteLogWithSql(UtilMethods.GetNativeSql(sql, pars));
 | 
			
		||||
@@ -62,7 +62,7 @@ public class SugarAopService : ISugarAopService
 | 
			
		||||
            if (ex.Parameters == null) return;
 | 
			
		||||
            Console.ForegroundColor = ConsoleColor.Red;
 | 
			
		||||
            DbContext.WriteLog($"{config.ConfigId}库操作异常");
 | 
			
		||||
            DbContext.WriteErrorLogWithSql(UtilMethods.GetNativeSql(ex.Sql, (SugarParameter[])ex.Parameters));
 | 
			
		||||
            DbContext.WriteErrorLogWithSql(UtilMethods.GetNativeSql(ex.Sql, ex.Parameters));
 | 
			
		||||
            NewLife.Log.XTrace.WriteException(ex);
 | 
			
		||||
            Console.ForegroundColor = ConsoleColor.White;
 | 
			
		||||
        };
 | 
			
		||||
@@ -110,10 +110,6 @@ public class SugarAopService : ISugarAopService
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        //查询数据转换
 | 
			
		||||
        db.Aop.DataExecuted = (value, entity) =>
 | 
			
		||||
        {
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        db.Aop.OnLogExecuted = (sql, pars) =>
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -42,7 +42,6 @@ public static class CodeFirstUtils
 | 
			
		||||
        var seedDataTypes = App.EffectiveTypes
 | 
			
		||||
    .Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass
 | 
			
		||||
    && u.GetInterfaces().Any(i => i.HasImplementedRawGeneric(typeof(ISqlSugarEntitySeedData<>))) && u.Assembly.FullName == assemblyName);
 | 
			
		||||
        if (!seedDataTypes.Any()) return;
 | 
			
		||||
        foreach (var seedType in seedDataTypes)//遍历种子类
 | 
			
		||||
        {
 | 
			
		||||
            //使用与指定参数匹配程度最高的构造函数来创建指定类型的实例。
 | 
			
		||||
@@ -62,10 +61,12 @@ public static class CodeFirstUtils
 | 
			
		||||
            // seedDataTable.TableName = db.EntityMaintenance.GetEntityInfo(entityType).DbTableName;//获取表名
 | 
			
		||||
            var ignoreAdd = seedDataMethod!.GetCustomAttribute<IgnoreSeedDataAddAttribute>();//读取忽略插入特性
 | 
			
		||||
            var ignoreUpdate = seedDataMethod!.GetCustomAttribute<IgnoreSeedDataUpdateAttribute>();//读取忽略更新特性
 | 
			
		||||
 | 
			
		||||
            var seedDataList = seedData.ToList();
 | 
			
		||||
            if (entityInfo.Columns.Any(u => u.IsPrimarykey))//判断种子数据是否有主键
 | 
			
		||||
            {
 | 
			
		||||
                // 按主键进行批量增加和更新
 | 
			
		||||
                var storage = db.StorageableByObject(seedData.ToList()).ToStorage();
 | 
			
		||||
                var storage = db.StorageableByObject(seedDataList).ToStorage();
 | 
			
		||||
                if (ignoreAdd == null)
 | 
			
		||||
                    storage.AsInsertable.ExecuteCommand();//执行插入
 | 
			
		||||
                if (ignoreUpdate == null && config.IsUpdateSeedData) storage.AsUpdateable.ExecuteCommand();//只有没有忽略更新的特性才执行更新
 | 
			
		||||
@@ -75,7 +76,7 @@ public static class CodeFirstUtils
 | 
			
		||||
                //全量插入
 | 
			
		||||
                // 无主键则只进行插入
 | 
			
		||||
                if (!db.Queryable(entityInfo.DbTableName, entityInfo.DbTableName).Any() && ignoreAdd == null)
 | 
			
		||||
                    db.InsertableByObject(seedData.ToList()).ExecuteCommand();
 | 
			
		||||
                    db.InsertableByObject(seedDataList).ExecuteCommand();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@@ -89,7 +90,6 @@ public static class CodeFirstUtils
 | 
			
		||||
        // 获取所有实体表-初始化表结构
 | 
			
		||||
        var entityTypes = App.EffectiveTypes.Where(u =>
 | 
			
		||||
            !u.IsInterface && !u.IsAbstract && u.IsClass && u.IsDefined(typeof(SugarTable), false) && u.Assembly.FullName == assemblyName);
 | 
			
		||||
        if (!entityTypes.Any()) return;//没有就退出
 | 
			
		||||
        foreach (var entityType in entityTypes)
 | 
			
		||||
        {
 | 
			
		||||
            var tenantAtt = entityType.GetCustomAttribute<TenantAttribute>();//获取Sqlsugar多库特性
 | 
			
		||||
 
 | 
			
		||||
@@ -136,7 +136,7 @@ public static class DbContext
 | 
			
		||||
                await db.Fastest<TITEM>().PageSize(size).BulkCopyAsync(datas).ConfigureAwait(false);
 | 
			
		||||
                break;
 | 
			
		||||
            default:
 | 
			
		||||
                await db.Insertable(datas is IReadOnlyList<TITEM> values ? values : datas.ToList()).PageSize(size).ExecuteCommandAsync().ConfigureAwait(false);
 | 
			
		||||
                await db.Insertable(datas is IReadOnlyCollection<TITEM> values ? values : datas.ToList()).PageSize(size).ExecuteCommandAsync().ConfigureAwait(false);
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@@ -155,7 +155,7 @@ public static class DbContext
 | 
			
		||||
                await db.Fastest<TITEM>().PageSize(size).BulkUpdateAsync(datas).ConfigureAwait(false);
 | 
			
		||||
                break;
 | 
			
		||||
            default:
 | 
			
		||||
                await db.Updateable(datas is IReadOnlyList<TITEM> values ? values : datas.ToList()).PageSize(size).ExecuteCommandAsync().ConfigureAwait(false);
 | 
			
		||||
                await db.Updateable(datas is IReadOnlyCollection<TITEM> values ? values : datas.ToList()).PageSize(size).ExecuteCommandAsync().ConfigureAwait(false);
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -278,7 +278,6 @@ public static class AppServiceCollectionExtensions
 | 
			
		||||
                    && u.GetParameters().Length > 0
 | 
			
		||||
                    && u.GetParameters().First().ParameterType == typeof(IServiceCollection));
 | 
			
		||||
 | 
			
		||||
            if (!serviceMethods.Any()) continue;
 | 
			
		||||
 | 
			
		||||
            // 自动安装属性调用
 | 
			
		||||
            foreach (var method in serviceMethods)
 | 
			
		||||
 
 | 
			
		||||
@@ -18,6 +18,8 @@ using System.Runtime.CompilerServices;
 | 
			
		||||
using System.Text.Json;
 | 
			
		||||
using System.Text.RegularExpressions;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.NewLife;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Extensions;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
@@ -187,7 +189,7 @@ public static class ObjectExtensions
 | 
			
		||||
            {
 | 
			
		||||
                if (current == last) func(arg);
 | 
			
		||||
                task.Dispose();
 | 
			
		||||
            });
 | 
			
		||||
            }, CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.Default);
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -207,8 +209,8 @@ public static class ObjectExtensions
 | 
			
		||||
            Task.Delay(milliseconds).ContinueWith(task =>
 | 
			
		||||
            {
 | 
			
		||||
                if (current == last) func();
 | 
			
		||||
                task.Dispose();
 | 
			
		||||
            });
 | 
			
		||||
                task.TryDispose();
 | 
			
		||||
            }, CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.Default);
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -908,7 +908,6 @@ public static class Serve
 | 
			
		||||
                    && u.GetParameters().Length > 0
 | 
			
		||||
                    && u.GetParameters().First().ParameterType == typeof(IServiceProvider));
 | 
			
		||||
 | 
			
		||||
            if (!configureMethods.Any()) continue;
 | 
			
		||||
 | 
			
		||||
            // 自动安装属性调用
 | 
			
		||||
            foreach (var method in configureMethods)
 | 
			
		||||
@@ -935,7 +934,6 @@ public static class Serve
 | 
			
		||||
                    && u.GetParameters().Length > 0
 | 
			
		||||
                    && u.GetParameters().First().ParameterType == typeof(IApplicationBuilder));
 | 
			
		||||
 | 
			
		||||
            if (!configureMethods.Any()) continue;
 | 
			
		||||
 | 
			
		||||
            // 自动安装属性调用
 | 
			
		||||
            foreach (var method in configureMethods)
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,6 @@
 | 
			
		||||
 | 
			
		||||
using Microsoft.AspNetCore.Builder;
 | 
			
		||||
using Microsoft.Extensions.DependencyInjection;
 | 
			
		||||
#pragma warning disable CA1822 // 将成员标记为 static
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -150,18 +150,18 @@ public static class DependencyInjectionServiceCollectionExtensions
 | 
			
		||||
        {
 | 
			
		||||
            Register(services, dependencyType, type, injectionAttribute);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!canInjectInterfaces.Any()) return;
 | 
			
		||||
        var list = canInjectInterfaces.ToList();
 | 
			
		||||
        if (list.Count == 0) return;
 | 
			
		||||
 | 
			
		||||
        // 只注册第一个接口
 | 
			
		||||
        if (injectionAttribute.Pattern is InjectionPatterns.FirstInterface or InjectionPatterns.SelfWithFirstInterface)
 | 
			
		||||
        {
 | 
			
		||||
            Register(services, dependencyType, type, injectionAttribute, canInjectInterfaces.Last());
 | 
			
		||||
            Register(services, dependencyType, type, injectionAttribute, list.Last());
 | 
			
		||||
        }
 | 
			
		||||
        // 注册多个接口
 | 
			
		||||
        else if (injectionAttribute.Pattern is InjectionPatterns.ImplementedInterfaces or InjectionPatterns.All)
 | 
			
		||||
        {
 | 
			
		||||
            foreach (var inter in canInjectInterfaces)
 | 
			
		||||
            foreach (var inter in list)
 | 
			
		||||
            {
 | 
			
		||||
                Register(services, dependencyType, type, injectionAttribute, inter);
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
@@ -47,12 +47,14 @@ internal sealed class NamedServiceProvider<TService> : INamedServiceProvider<TSe
 | 
			
		||||
    {
 | 
			
		||||
        var services = _serviceProvider.GetServices<TService>();
 | 
			
		||||
 | 
			
		||||
#pragma warning disable CA1851
 | 
			
		||||
        if (services
 | 
			
		||||
            .OfType<AspectDispatchProxy>()
 | 
			
		||||
            .FirstOrDefault(u => ResovleServiceName(((dynamic)u).Target.GetType()) == serviceName) is not TService service)
 | 
			
		||||
        {
 | 
			
		||||
            service = services.FirstOrDefault(u => ResovleServiceName(u.GetType()) == serviceName);
 | 
			
		||||
        }
 | 
			
		||||
#pragma warning restore CA1851
 | 
			
		||||
 | 
			
		||||
        return service;
 | 
			
		||||
    }
 | 
			
		||||
@@ -80,12 +82,14 @@ internal sealed class NamedServiceProvider<TService> : INamedServiceProvider<TSe
 | 
			
		||||
        // 解析所有实现
 | 
			
		||||
        var services = _serviceProvider.GetServices<TService>();
 | 
			
		||||
 | 
			
		||||
#pragma warning disable CA1851
 | 
			
		||||
        if (services
 | 
			
		||||
            .OfType<AspectDispatchProxy>()
 | 
			
		||||
            .FirstOrDefault(u => ResovleServiceName(((dynamic)u).Target.GetType()) == serviceName) is not TService service)
 | 
			
		||||
        {
 | 
			
		||||
            service = services.FirstOrDefault(u => ResovleServiceName(u.GetType()) == serviceName);
 | 
			
		||||
        }
 | 
			
		||||
#pragma warning restore CA1851
 | 
			
		||||
 | 
			
		||||
        // 如果服务不存在,抛出异常
 | 
			
		||||
        return service ?? throw new InvalidOperationException($"Named service `{serviceName}` is not registered in container.");
 | 
			
		||||
 
 | 
			
		||||
@@ -356,7 +356,7 @@ internal sealed class EventBusHostedService : BackgroundService
 | 
			
		||||
                        GC.WaitForPendingFinalizers();
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }, stoppingToken);
 | 
			
		||||
            }, stoppingToken, TaskCreationOptions.None, TaskScheduler.Default);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -60,7 +60,7 @@ internal sealed partial class ChannelEventPublisher : IEventPublisher
 | 
			
		||||
            await Task.Delay(TimeSpan.FromMilliseconds(delay), eventSource.CancellationToken).ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
            await _eventSourceStorer.WriteAsync(eventSource, eventSource.CancellationToken).ConfigureAwait(false);
 | 
			
		||||
        }, eventSource.CancellationToken);
 | 
			
		||||
        }, eventSource.CancellationToken, TaskCreationOptions.None, TaskScheduler.Default);
 | 
			
		||||
 | 
			
		||||
        return Task.CompletedTask;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -38,6 +38,7 @@ public static class IEndpointRouteBuilderExtensions
 | 
			
		||||
            && u.IsDefined(typeof(MapHubAttribute), true)
 | 
			
		||||
            && (typeof(Hub).IsAssignableFrom(u) || u.HasImplementedRawGeneric(typeof(Hub<>))));
 | 
			
		||||
 | 
			
		||||
#pragma warning disable CA1851
 | 
			
		||||
        if (!hubs.Any()) return;
 | 
			
		||||
 | 
			
		||||
        // 反射获取 MapHub 拓展方法
 | 
			
		||||
@@ -65,5 +66,6 @@ public static class IEndpointRouteBuilderExtensions
 | 
			
		||||
            hub.GetMethod("HubEndpointConventionBuilderSettings", BindingFlags.Public | BindingFlags.Static)
 | 
			
		||||
                ?.Invoke(null, new object[] { hubEndpointConventionBuilder });
 | 
			
		||||
        }
 | 
			
		||||
#pragma warning restore CA1851
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -162,8 +162,8 @@ public sealed class DatabaseLoggerProvider : ILoggerProvider, ISupportExternalSc
 | 
			
		||||
        _databaseLoggingWriter = _serviceScope.ServiceProvider.GetRequiredService(databaseLoggingWriterType) as IDatabaseLoggingWriter;
 | 
			
		||||
 | 
			
		||||
        // 创建长时间运行的后台任务,并将日志消息队列中数据写入存储中
 | 
			
		||||
        _processQueueTask = Task.Factory.StartNew(ProcessQueueAsync
 | 
			
		||||
            , TaskCreationOptions.LongRunning);
 | 
			
		||||
        _processQueueTask = Task.Factory.StartNew(ProcessQueueAsync, CancellationToken.None
 | 
			
		||||
            , TaskCreationOptions.LongRunning, TaskScheduler.Default);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -91,7 +91,7 @@ public sealed class FileLoggerProvider : ILoggerProvider, ISupportExternalScope
 | 
			
		||||
        _fileLoggingWriter = new FileLoggingWriter(this);
 | 
			
		||||
 | 
			
		||||
        // 创建长时间运行的后台任务,并将日志消息队列中数据写入文件中
 | 
			
		||||
        _processQueueTask = Task.Factory.StartNew(ProcessQueueAsync, TaskCreationOptions.LongRunning);
 | 
			
		||||
        _processQueueTask = Task.Factory.StartNew(ProcessQueueAsync, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -85,6 +85,7 @@ public static class OptionsBuilderExtensions
 | 
			
		||||
        var builderInterfaces = optionsBuilderType.GetInterfaces()
 | 
			
		||||
            .Where(u => optionsBuilderDependency.IsAssignableFrom(u) && u != optionsBuilderDependency);
 | 
			
		||||
 | 
			
		||||
#pragma warning disable CA1851
 | 
			
		||||
        if (!builderInterfaces.Any())
 | 
			
		||||
        {
 | 
			
		||||
            return optionsBuilder;
 | 
			
		||||
@@ -95,6 +96,7 @@ public static class OptionsBuilderExtensions
 | 
			
		||||
        {
 | 
			
		||||
            InvokeMapMethod(optionsBuilder, optionsBuilderType, builderInterface);
 | 
			
		||||
        }
 | 
			
		||||
#pragma warning restore CA1851
 | 
			
		||||
 | 
			
		||||
        return optionsBuilder;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -115,7 +115,7 @@ internal sealed partial class SchedulerFactory : ISchedulerFactory
 | 
			
		||||
        if (Persistence is not null)
 | 
			
		||||
        {
 | 
			
		||||
            // 创建长时间运行的后台任务,并将作业运行消息写入持久化中
 | 
			
		||||
            _processQueueTask = Task.Factory.StartNew(ProcessQueueAsync, TaskCreationOptions.LongRunning);
 | 
			
		||||
            _processQueueTask = Task.Factory.StartNew(ProcessQueueAsync, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -163,19 +163,16 @@ internal sealed partial class SchedulerFactory : ISchedulerFactory
 | 
			
		||||
            var initialSchedulerBuilders = _schedulerBuilders.Concat(preloadSchedulerBuilders ?? Enumerable.Empty<SchedulerBuilder>());
 | 
			
		||||
 | 
			
		||||
            // 如果作业调度器中包含作业计划构建器
 | 
			
		||||
            if (initialSchedulerBuilders.Any())
 | 
			
		||||
            // 逐条遍历并加载到内存中
 | 
			
		||||
            foreach (var schedulerBuilder in initialSchedulerBuilders)
 | 
			
		||||
            {
 | 
			
		||||
                // 逐条遍历并加载到内存中
 | 
			
		||||
                foreach (var schedulerBuilder in initialSchedulerBuilders)
 | 
			
		||||
                SchedulerBuilder schedulerBuilderObj = null;
 | 
			
		||||
                if (isSetPersistence)
 | 
			
		||||
                {
 | 
			
		||||
                    SchedulerBuilder schedulerBuilderObj = null;
 | 
			
		||||
                    if (isSetPersistence)
 | 
			
		||||
                    {
 | 
			
		||||
                        schedulerBuilderObj = await Persistence.OnLoadingAsync(schedulerBuilder, stoppingToken).ConfigureAwait(false);
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    _ = TrySaveJob(schedulerBuilderObj ?? schedulerBuilder, out _, false);
 | 
			
		||||
                    schedulerBuilderObj = await Persistence.OnLoadingAsync(schedulerBuilder, stoppingToken).ConfigureAwait(false);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                _ = TrySaveJob(schedulerBuilderObj ?? schedulerBuilder, out _, false);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
@@ -484,11 +481,12 @@ internal sealed partial class SchedulerFactory : ISchedulerFactory
 | 
			
		||||
                .Where(t => t.NextShouldRun(startAt))
 | 
			
		||||
                .Select(t => t.NextRunTime.Value));
 | 
			
		||||
 | 
			
		||||
        // 空检查
 | 
			
		||||
#pragma warning disable CA1851
 | 
			
		||||
        if (!nextRunTimes.Any()) return null;
 | 
			
		||||
 | 
			
		||||
        // 获取最早触发的时间
 | 
			
		||||
        var earliestTriggerTime = nextRunTimes.Min();
 | 
			
		||||
#pragma warning restore CA1851
 | 
			
		||||
 | 
			
		||||
        // 计算总休眠时间
 | 
			
		||||
        var sleepMilliseconds = (earliestTriggerTime - startAt).TotalMilliseconds;
 | 
			
		||||
 
 | 
			
		||||
@@ -400,7 +400,7 @@ internal sealed class ScheduleHostedService : BackgroundService
 | 
			
		||||
                            // 通知 GC 垃圾回收器回收
 | 
			
		||||
                            //_schedulerFactory.GCCollect();
 | 
			
		||||
                        }
 | 
			
		||||
                    }, stoppingToken);
 | 
			
		||||
                    }, stoppingToken, TaskCreationOptions.None, TaskScheduler.Default);
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 
 | 
			
		||||
@@ -31,6 +31,7 @@
 | 
			
		||||
 | 
			
		||||
	<ItemGroup>
 | 
			
		||||
		<PackageReference Include="Swashbuckle.AspNetCore" Version="9.0.3" />
 | 
			
		||||
		<PackageReference Include="System.Text.Encoding.CodePages" Version="$(NET9Version)" />
 | 
			
		||||
	</ItemGroup>
 | 
			
		||||
 | 
			
		||||
	<ItemGroup Condition=" '$(TargetFramework)' == 'net8.0' ">
 | 
			
		||||
@@ -43,6 +44,7 @@
 | 
			
		||||
		<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="$(NET9Version)" />
 | 
			
		||||
		<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="$(NET9Version)" />
 | 
			
		||||
		<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="$(NET9Version)" />
 | 
			
		||||
		
 | 
			
		||||
 | 
			
		||||
	</ItemGroup>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -31,10 +31,8 @@ internal readonly struct ComponentMetadata
 | 
			
		||||
        Version = version?.ToString();
 | 
			
		||||
        Description = description;
 | 
			
		||||
 | 
			
		||||
#pragma warning disable CA1863 // 使用 "CompositeFormat"
 | 
			
		||||
        NuGetPage = string.Format(Constants.NUGET_PACKAGE_PAGE, name, version?.ToString() ?? string.Empty);
 | 
			
		||||
        DocumentationPage = string.Format(Constants.FURION_COMPONENT_DOCS_PAGE, Name);
 | 
			
		||||
#pragma warning restore CA1863 // 使用 "CompositeFormat"
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -546,7 +546,9 @@ internal sealed partial class HttpRemoteService : IHttpRemoteService
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                // ReSharper disable once MethodHasAsyncOverload
 | 
			
		||||
#pragma warning disable CA1849
 | 
			
		||||
                InvokeStatusCodeHandlers(httpRequestBuilder, httpResponseMessage, timeoutCancellationToken);
 | 
			
		||||
#pragma warning restore CA1849
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // 检查 HTTP 响应内容长度是否在设定的最大缓冲区大小限制内
 | 
			
		||||
 
 | 
			
		||||
@@ -232,7 +232,7 @@ public abstract class Cache : DisposeBase, ICache
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    public virtual Int64 Increment(String key, Int64 value)
 | 
			
		||||
    {
 | 
			
		||||
        lock (this)
 | 
			
		||||
        lock (lockThis)
 | 
			
		||||
        {
 | 
			
		||||
            var v = Get<Int64>(key);
 | 
			
		||||
            v += value;
 | 
			
		||||
@@ -248,7 +248,7 @@ public abstract class Cache : DisposeBase, ICache
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    public virtual Double Increment(String key, Double value)
 | 
			
		||||
    {
 | 
			
		||||
        lock (this)
 | 
			
		||||
        lock (lockThis)
 | 
			
		||||
        {
 | 
			
		||||
            var v = Get<Double>(key);
 | 
			
		||||
            v += value;
 | 
			
		||||
@@ -264,7 +264,7 @@ public abstract class Cache : DisposeBase, ICache
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    public virtual Int64 Decrement(String key, Int64 value)
 | 
			
		||||
    {
 | 
			
		||||
        lock (this)
 | 
			
		||||
        lock (lockThis)
 | 
			
		||||
        {
 | 
			
		||||
            var v = Get<Int64>(key);
 | 
			
		||||
            v -= value;
 | 
			
		||||
@@ -273,14 +273,14 @@ public abstract class Cache : DisposeBase, ICache
 | 
			
		||||
            return v;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected object lockThis = new();
 | 
			
		||||
    /// <summary>递减,原子操作</summary>
 | 
			
		||||
    /// <param name="key">键</param>
 | 
			
		||||
    /// <param name="value">变化量</param>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    public virtual Double Decrement(String key, Double value)
 | 
			
		||||
    {
 | 
			
		||||
        lock (this)
 | 
			
		||||
        lock (lockThis)
 | 
			
		||||
        {
 | 
			
		||||
            var v = Get<Double>(key);
 | 
			
		||||
            v -= value;
 | 
			
		||||
 
 | 
			
		||||
@@ -865,7 +865,7 @@ public class MemoryCache : Cache
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public override void HashAdd<T>(string key, string hashKey, T value)
 | 
			
		||||
    {
 | 
			
		||||
        lock (this)
 | 
			
		||||
        lock (lockThis)
 | 
			
		||||
        {
 | 
			
		||||
            //获取字典
 | 
			
		||||
            var exist = GetDictionary<T>(key);
 | 
			
		||||
@@ -879,7 +879,7 @@ public class MemoryCache : Cache
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public override bool HashSet<T>(string key, Dictionary<string, T> dic)
 | 
			
		||||
    {
 | 
			
		||||
        lock (this)
 | 
			
		||||
        lock (lockThis)
 | 
			
		||||
        {
 | 
			
		||||
            //获取字典
 | 
			
		||||
            var exist = GetDictionary<T>(key);
 | 
			
		||||
 
 | 
			
		||||
@@ -80,7 +80,7 @@ public class ObjectPool<T> : DisposeBase, IPool<T> where T : notnull
 | 
			
		||||
    {
 | 
			
		||||
        if (_inited) return;
 | 
			
		||||
 | 
			
		||||
        lock (this)
 | 
			
		||||
        lock (lockThis)
 | 
			
		||||
        {
 | 
			
		||||
            if (_inited) return;
 | 
			
		||||
            _inited = true;
 | 
			
		||||
@@ -274,6 +274,7 @@ public class ObjectPool<T> : DisposeBase, IPool<T> where T : notnull
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    protected virtual T? OnCreate() => (T?)typeof(T).CreateInstance();
 | 
			
		||||
    #endregion
 | 
			
		||||
    protected object lockThis = new();
 | 
			
		||||
 | 
			
		||||
    #region 定期清理
 | 
			
		||||
    private TimerX? _timer;
 | 
			
		||||
@@ -281,7 +282,7 @@ public class ObjectPool<T> : DisposeBase, IPool<T> where T : notnull
 | 
			
		||||
    private void StartTimer()
 | 
			
		||||
    {
 | 
			
		||||
        if (_timer != null) return;
 | 
			
		||||
        lock (this)
 | 
			
		||||
        lock (lockThis)
 | 
			
		||||
        {
 | 
			
		||||
            if (_timer != null) return;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -25,6 +25,7 @@ public class Pool<T> : IPool<T> where T : class
 | 
			
		||||
        public T? Value;
 | 
			
		||||
    }
 | 
			
		||||
    #endregion
 | 
			
		||||
    protected object lockThis = new();
 | 
			
		||||
 | 
			
		||||
    #region 构造
 | 
			
		||||
    /// <summary>实例化对象池。默认大小CPU*2</summary>
 | 
			
		||||
@@ -63,7 +64,7 @@ public class Pool<T> : IPool<T> where T : class
 | 
			
		||||
    private void Init()
 | 
			
		||||
    {
 | 
			
		||||
        if (_items != null) return;
 | 
			
		||||
        lock (this)
 | 
			
		||||
        lock (lockThis)
 | 
			
		||||
        {
 | 
			
		||||
            if (_items != null) return;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -18,6 +18,7 @@ public sealed class IncrementCount
 | 
			
		||||
    private long _current = 0;
 | 
			
		||||
    private long _max = long.MaxValue;
 | 
			
		||||
    private long _start = 0;
 | 
			
		||||
    private object lockThis = new();
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc cref="IncrementCount"/>
 | 
			
		||||
    public IncrementCount(long max, long start = 0, int tick = 1)
 | 
			
		||||
@@ -43,7 +44,7 @@ public sealed class IncrementCount
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public long GetCurrentValue()
 | 
			
		||||
    {
 | 
			
		||||
        lock (this)
 | 
			
		||||
        lock (lockThis)
 | 
			
		||||
        {
 | 
			
		||||
            long current = _current;
 | 
			
		||||
            _current += IncreaseTick;
 | 
			
		||||
@@ -65,7 +66,7 @@ public sealed class IncrementCount
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public void ResetCurrentValue()
 | 
			
		||||
    {
 | 
			
		||||
        lock (this)
 | 
			
		||||
        lock (lockThis)
 | 
			
		||||
        {
 | 
			
		||||
            _current = _start;
 | 
			
		||||
        }
 | 
			
		||||
@@ -77,7 +78,7 @@ public sealed class IncrementCount
 | 
			
		||||
    /// <param name="value">指定值</param>
 | 
			
		||||
    public void ResetCurrentValue(long value)
 | 
			
		||||
    {
 | 
			
		||||
        lock (this)
 | 
			
		||||
        lock (lockThis)
 | 
			
		||||
        {
 | 
			
		||||
            _current = value <= _max ? value >= _start ? value : _start : _max;
 | 
			
		||||
        }
 | 
			
		||||
@@ -88,7 +89,7 @@ public sealed class IncrementCount
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public void ResetMaxValue(long max)
 | 
			
		||||
    {
 | 
			
		||||
        lock (this)
 | 
			
		||||
        lock (lockThis)
 | 
			
		||||
        {
 | 
			
		||||
            if (max > _start)
 | 
			
		||||
            {
 | 
			
		||||
@@ -108,7 +109,7 @@ public sealed class IncrementCount
 | 
			
		||||
    /// <param name="start">初始值</param>
 | 
			
		||||
    public void ResetStartValue(long start)
 | 
			
		||||
    {
 | 
			
		||||
        lock (this)
 | 
			
		||||
        lock (lockThis)
 | 
			
		||||
        {
 | 
			
		||||
            if (start < _max)
 | 
			
		||||
            {
 | 
			
		||||
 
 | 
			
		||||
@@ -132,17 +132,6 @@ public class MachineInfo : IExtend
 | 
			
		||||
    /// <summary>机器信息提供者。外部实现可修改部分行为</summary>
 | 
			
		||||
    public static IMachineInfo? Provider { get; set; }
 | 
			
		||||
 | 
			
		||||
    //static MachineInfo() => RegisterAsync().Wait(100);
 | 
			
		||||
 | 
			
		||||
    private static Task<MachineInfo>? _task;
 | 
			
		||||
    /// <summary>异步注册一个初始化后的机器信息实例</summary>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    public static Task<MachineInfo> RegisterAsync()
 | 
			
		||||
    {
 | 
			
		||||
        if (_task != null) return _task;
 | 
			
		||||
 | 
			
		||||
        return _task = Task.Factory.StartNew(() => Register());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static MachineInfo Register()
 | 
			
		||||
    {
 | 
			
		||||
 
 | 
			
		||||
@@ -39,7 +39,7 @@ public class Config<TConfig> where TConfig : Config<TConfig>, new()
 | 
			
		||||
 | 
			
		||||
        Provider = prv;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static readonly Object _lock = new Object();
 | 
			
		||||
    private static TConfig? _Current;
 | 
			
		||||
    /// <summary>当前实例。通过置空可以使其重新加载。</summary>
 | 
			
		||||
    public static TConfig Current
 | 
			
		||||
@@ -47,7 +47,7 @@ public class Config<TConfig> where TConfig : Config<TConfig>, new()
 | 
			
		||||
        get
 | 
			
		||||
        {
 | 
			
		||||
            if (_Current != null) return _Current;
 | 
			
		||||
            lock (typeof(TConfig))
 | 
			
		||||
            lock (_lock)
 | 
			
		||||
            {
 | 
			
		||||
                if (_Current != null) return _Current;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -110,7 +110,7 @@ public abstract class FileConfigProvider : ConfigProvider
 | 
			
		||||
        if (model == null) return false;
 | 
			
		||||
 | 
			
		||||
        // 加锁,避免多线程冲突
 | 
			
		||||
        lock (this)
 | 
			
		||||
        lock (lockThis)
 | 
			
		||||
        {
 | 
			
		||||
            // 文件存储,直接覆盖Root
 | 
			
		||||
            Root.Childs?.Clear();
 | 
			
		||||
@@ -168,7 +168,7 @@ public abstract class FileConfigProvider : ConfigProvider
 | 
			
		||||
    private void InitTimer()
 | 
			
		||||
    {
 | 
			
		||||
        if (_timer != null) return;
 | 
			
		||||
        lock (this)
 | 
			
		||||
        lock (lockThis)
 | 
			
		||||
        {
 | 
			
		||||
            if (_timer != null) return;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -180,6 +180,7 @@ public abstract class ConfigProvider : DisposeBase, IConfigProvider
 | 
			
		||||
    /// <param name="value"></param>
 | 
			
		||||
    public virtual void Init(String value) { }
 | 
			
		||||
    #endregion
 | 
			
		||||
    protected object lockThis = new();
 | 
			
		||||
 | 
			
		||||
    #region 加载/保存
 | 
			
		||||
    /// <summary>从数据源加载数据到配置树</summary>
 | 
			
		||||
@@ -189,7 +190,7 @@ public abstract class ConfigProvider : DisposeBase, IConfigProvider
 | 
			
		||||
    private void EnsureLoad()
 | 
			
		||||
    {
 | 
			
		||||
        if (_Loaded) return;
 | 
			
		||||
        lock (this)
 | 
			
		||||
        lock (lockThis)
 | 
			
		||||
        {
 | 
			
		||||
            if (_Loaded) return;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -84,13 +84,14 @@ public class Snowflake
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    #endregion
 | 
			
		||||
    protected object lockThis = new();
 | 
			
		||||
 | 
			
		||||
    #region 核心方法
 | 
			
		||||
    private Boolean _inited;
 | 
			
		||||
    private void Init()
 | 
			
		||||
    {
 | 
			
		||||
        if (_inited) return;
 | 
			
		||||
        lock (this)
 | 
			
		||||
        lock (lockThis)
 | 
			
		||||
        {
 | 
			
		||||
            if (_inited) return;
 | 
			
		||||
 | 
			
		||||
@@ -152,7 +153,7 @@ public class Snowflake
 | 
			
		||||
 | 
			
		||||
        // 核心理念:时间不同时序号置零,时间相同时序号递增
 | 
			
		||||
        var seq = 0;
 | 
			
		||||
        lock (this)
 | 
			
		||||
        lock (lockThis)
 | 
			
		||||
        {
 | 
			
		||||
            while (true)
 | 
			
		||||
            {
 | 
			
		||||
@@ -180,7 +181,7 @@ public class Snowflake
 | 
			
		||||
        //{
 | 
			
		||||
        //    if (ms > origin)
 | 
			
		||||
        //    {
 | 
			
		||||
        //        lock (this)
 | 
			
		||||
        //        lock (lockThis)
 | 
			
		||||
        //        {
 | 
			
		||||
        //            origin = Volatile.Read(ref _lastTime);
 | 
			
		||||
        //            if (ms > origin)
 | 
			
		||||
@@ -209,7 +210,7 @@ public class Snowflake
 | 
			
		||||
        //    origin = Volatile.Read(ref _lastTime);
 | 
			
		||||
        //    if (ms == origin)
 | 
			
		||||
        //    {
 | 
			
		||||
        //        lock (this)
 | 
			
		||||
        //        lock (lockThis)
 | 
			
		||||
        //        {
 | 
			
		||||
        //            origin = Volatile.Read(ref _lastTime);
 | 
			
		||||
        //            if (ms == origin)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										9
									
								
								src/Admin/ThingsGateway.NewLife.X/GlobalSuppressions.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/Admin/ThingsGateway.NewLife.X/GlobalSuppressions.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
			
		||||
// This file is used by Code Analysis to maintain SuppressMessage
 | 
			
		||||
// attributes that are applied to this project.
 | 
			
		||||
// Project-level suppressions either have no target or are given
 | 
			
		||||
// a specific target and scoped to a namespace, type, member, etc.
 | 
			
		||||
 | 
			
		||||
using System.Diagnostics.CodeAnalysis;
 | 
			
		||||
 | 
			
		||||
[assembly: SuppressMessage("Reliability", "CA1849", Justification = "<挂起>", Scope = "module")]
 | 
			
		||||
 | 
			
		||||
@@ -67,6 +67,7 @@ public class CsvDb<T> : DisposeBase where T : new()
 | 
			
		||||
        _cache = null;
 | 
			
		||||
    }
 | 
			
		||||
    #endregion
 | 
			
		||||
    protected object lockThis = new();
 | 
			
		||||
 | 
			
		||||
    #region 添删改查
 | 
			
		||||
    /// <summary>批量写入数据(高性能)</summary>
 | 
			
		||||
@@ -74,7 +75,6 @@ public class CsvDb<T> : DisposeBase where T : new()
 | 
			
		||||
    /// <param name="append">是否附加在尾部。为false时从头写入,覆盖已有数据</param>
 | 
			
		||||
    public void Write(IEnumerable<T> models, Boolean append)
 | 
			
		||||
    {
 | 
			
		||||
        if (!models.Any() && append) return;
 | 
			
		||||
 | 
			
		||||
        var file = GetFile();
 | 
			
		||||
        file.EnsureDirectory(true);
 | 
			
		||||
@@ -146,7 +146,7 @@ public class CsvDb<T> : DisposeBase where T : new()
 | 
			
		||||
    {
 | 
			
		||||
        if (predicate == null) throw new ArgumentNullException(nameof(predicate));
 | 
			
		||||
 | 
			
		||||
        lock (this)
 | 
			
		||||
        lock (lockThis)
 | 
			
		||||
        {
 | 
			
		||||
            if (_cache != null) return _cache.RemoveAll(x => predicate(x));
 | 
			
		||||
 | 
			
		||||
@@ -190,7 +190,7 @@ public class CsvDb<T> : DisposeBase where T : new()
 | 
			
		||||
    {
 | 
			
		||||
        if (Comparer == null) throw new ArgumentNullException(nameof(Comparer));
 | 
			
		||||
 | 
			
		||||
        lock (this)
 | 
			
		||||
        lock (lockThis)
 | 
			
		||||
        {
 | 
			
		||||
            var list = _cache ?? FindAll();
 | 
			
		||||
            if (!add && list.Count == 0) return false;
 | 
			
		||||
@@ -266,7 +266,7 @@ public class CsvDb<T> : DisposeBase where T : new()
 | 
			
		||||
        var file = GetFile();
 | 
			
		||||
        if (!File.Exists(file)) yield break;
 | 
			
		||||
 | 
			
		||||
        lock (this)
 | 
			
		||||
        lock (lockThis)
 | 
			
		||||
        {
 | 
			
		||||
            using var csv = new CsvFile(file, false) { Encoding = Encoding };
 | 
			
		||||
 | 
			
		||||
@@ -334,7 +334,7 @@ public class CsvDb<T> : DisposeBase where T : new()
 | 
			
		||||
    {
 | 
			
		||||
        if (_cache != null) return _cache!.Count;
 | 
			
		||||
 | 
			
		||||
        lock (this)
 | 
			
		||||
        lock (lockThis)
 | 
			
		||||
        {
 | 
			
		||||
            var file = GetFile();
 | 
			
		||||
            if (!File.Exists(file)) return 0;
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,7 @@ public class ConsoleLog : Logger
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            lock (this)
 | 
			
		||||
            lock (lockThis)
 | 
			
		||||
            {
 | 
			
		||||
                var cc = Console.ForegroundColor;
 | 
			
		||||
                cc = level switch
 | 
			
		||||
 
 | 
			
		||||
@@ -271,4 +271,7 @@ public abstract class Logger : ILog
 | 
			
		||||
        return sb.ToString();
 | 
			
		||||
    }
 | 
			
		||||
    #endregion
 | 
			
		||||
 | 
			
		||||
    protected object lockThis = new();
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -33,6 +33,7 @@ public class PerfCounter : DisposeBase, ICounter
 | 
			
		||||
        _Timer.TryDispose();
 | 
			
		||||
    }
 | 
			
		||||
    #endregion
 | 
			
		||||
    protected object lockThis = new();
 | 
			
		||||
 | 
			
		||||
    #region 核心方法
 | 
			
		||||
    /// <summary>增加</summary>
 | 
			
		||||
@@ -49,7 +50,7 @@ public class PerfCounter : DisposeBase, ICounter
 | 
			
		||||
 | 
			
		||||
        if (_Timer == null)
 | 
			
		||||
        {
 | 
			
		||||
            lock (this)
 | 
			
		||||
            lock (lockThis)
 | 
			
		||||
            {
 | 
			
		||||
                _Timer ??= new TimerX(DoWork, null, Interval, Interval) { Async = true };
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
@@ -43,6 +43,7 @@ public class PacketCodec
 | 
			
		||||
    /// <summary>APM性能追踪器</summary>
 | 
			
		||||
    public ITracer? Tracer { get; set; }
 | 
			
		||||
    #endregion
 | 
			
		||||
    protected object lockThis = new();
 | 
			
		||||
 | 
			
		||||
    /// <summary>数据包加入缓存数据末尾,分析数据流,得到一帧或多帧数据</summary>
 | 
			
		||||
    /// <param name="pk">待分析数据包</param>
 | 
			
		||||
@@ -96,7 +97,7 @@ public class PacketCodec
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 加锁,避免多线程冲突
 | 
			
		||||
        lock (this)
 | 
			
		||||
        lock (lockThis)
 | 
			
		||||
        {
 | 
			
		||||
            // 检查缓存,内部可能创建或清空
 | 
			
		||||
            CheckCache();
 | 
			
		||||
 
 | 
			
		||||
@@ -102,6 +102,7 @@ public abstract class Actor : DisposeBase, IActor
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    public override String ToString() => Name;
 | 
			
		||||
    #endregion
 | 
			
		||||
    protected object lockThis = new();
 | 
			
		||||
 | 
			
		||||
    #region 方法
 | 
			
		||||
 | 
			
		||||
@@ -114,7 +115,7 @@ public abstract class Actor : DisposeBase, IActor
 | 
			
		||||
    public virtual Task? Start(CancellationToken cancellationToken = default)
 | 
			
		||||
    {
 | 
			
		||||
        if (Active) return _task;
 | 
			
		||||
        lock (this)
 | 
			
		||||
        lock (lockThis)
 | 
			
		||||
        {
 | 
			
		||||
            if (Active) return _task;
 | 
			
		||||
 | 
			
		||||
@@ -128,7 +129,7 @@ public abstract class Actor : DisposeBase, IActor
 | 
			
		||||
            // 启动异步
 | 
			
		||||
            if (_task == null)
 | 
			
		||||
            {
 | 
			
		||||
                lock (this)
 | 
			
		||||
                lock (lockThis)
 | 
			
		||||
                {
 | 
			
		||||
                    _task ??= OnStart(_source.Token);
 | 
			
		||||
                }
 | 
			
		||||
 
 | 
			
		||||
@@ -55,6 +55,7 @@ public class DeferredQueue : DisposeBase
 | 
			
		||||
    /// <summary>批次处理失败时</summary>
 | 
			
		||||
    public Action<IList<Object>, Exception>? Error;
 | 
			
		||||
    #endregion
 | 
			
		||||
    protected object lockThis = new();
 | 
			
		||||
 | 
			
		||||
    #region 构造
 | 
			
		||||
    /// <summary>实例化</summary>
 | 
			
		||||
@@ -76,7 +77,7 @@ public class DeferredQueue : DisposeBase
 | 
			
		||||
        // 首次使用时初始化定时器
 | 
			
		||||
        if (_Timer == null)
 | 
			
		||||
        {
 | 
			
		||||
            lock (this)
 | 
			
		||||
            lock (lockThis)
 | 
			
		||||
            {
 | 
			
		||||
                _Timer ??= OnInit();
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
@@ -32,6 +32,7 @@ public class DefaultMatchQueue : IMatchQueue
 | 
			
		||||
    private readonly ItemWrap[] Items;
 | 
			
		||||
    private Int32 _Count;
 | 
			
		||||
    private TimerX? _Timer;
 | 
			
		||||
    protected object lockThis = new();
 | 
			
		||||
 | 
			
		||||
    /// <summary>按指定大小来初始化队列</summary>
 | 
			
		||||
    /// <param name="size"></param>
 | 
			
		||||
@@ -76,7 +77,7 @@ public class DefaultMatchQueue : IMatchQueue
 | 
			
		||||
 | 
			
		||||
        if (_Timer == null)
 | 
			
		||||
        {
 | 
			
		||||
            lock (this)
 | 
			
		||||
            lock (lockThis)
 | 
			
		||||
            {
 | 
			
		||||
                _Timer ??= new TimerX(Check, null, 1000, 1000, "Match")
 | 
			
		||||
                {
 | 
			
		||||
 
 | 
			
		||||
@@ -93,6 +93,7 @@ public abstract class SessionBase : DisposeBase, ISocketClient, ITransport, ILog
 | 
			
		||||
    public override String ToString() => Local + string.Empty;
 | 
			
		||||
 | 
			
		||||
    #endregion 构造
 | 
			
		||||
    protected object lockThis = new();
 | 
			
		||||
 | 
			
		||||
    #region 打开关闭
 | 
			
		||||
 | 
			
		||||
@@ -101,14 +102,14 @@ public abstract class SessionBase : DisposeBase, ISocketClient, ITransport, ILog
 | 
			
		||||
    public virtual Boolean Open()
 | 
			
		||||
    {
 | 
			
		||||
        if (Active) return true;
 | 
			
		||||
        if (!Monitor.TryEnter(this, Timeout + 100)) return false;
 | 
			
		||||
        if (!Monitor.TryEnter(lockThis, Timeout + 100)) return false;
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            return OpenAsync().ConfigureAwait(false).GetAwaiter().GetResult();
 | 
			
		||||
        }
 | 
			
		||||
        finally
 | 
			
		||||
        {
 | 
			
		||||
            Monitor.Exit(this);
 | 
			
		||||
            Monitor.Exit(lockThis);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -177,14 +178,14 @@ public abstract class SessionBase : DisposeBase, ISocketClient, ITransport, ILog
 | 
			
		||||
    public virtual Boolean Close(String reason)
 | 
			
		||||
    {
 | 
			
		||||
        if (!Active) return true;
 | 
			
		||||
        if (!Monitor.TryEnter(this, Timeout + 100)) return false;
 | 
			
		||||
        if (!Monitor.TryEnter(lockThis, Timeout + 100)) return false;
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            return CloseAsync(reason).ConfigureAwait(false).GetAwaiter().GetResult();
 | 
			
		||||
        }
 | 
			
		||||
        finally
 | 
			
		||||
        {
 | 
			
		||||
            Monitor.Exit(this);
 | 
			
		||||
            Monitor.Exit(lockThis);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -240,7 +240,7 @@ public class TcpServer : DisposeBase, ISocketServer, ILogFeature
 | 
			
		||||
            if (io)
 | 
			
		||||
                ProcessAccept(se);
 | 
			
		||||
            else
 | 
			
		||||
                Task.Factory.StartNew(() => ProcessAccept(se));
 | 
			
		||||
                Task.Factory.StartNew(() => ProcessAccept(se), CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
 
 | 
			
		||||
@@ -149,7 +149,7 @@ public class FullRedis : Redis
 | 
			
		||||
    public void InitCluster()
 | 
			
		||||
    {
 | 
			
		||||
        if (_initCluster) return;
 | 
			
		||||
        lock (this)
 | 
			
		||||
        lock (lockThis)
 | 
			
		||||
        {
 | 
			
		||||
            if (_initCluster) return;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -53,6 +53,8 @@ public abstract class QueueBase : RedisBase
 | 
			
		||||
    }
 | 
			
		||||
    #endregion
 | 
			
		||||
 | 
			
		||||
    protected object lockThis = new();
 | 
			
		||||
 | 
			
		||||
    #region 方法
 | 
			
		||||
    /// <summary>验证失败</summary>
 | 
			
		||||
    /// <param name="span"></param>
 | 
			
		||||
 
 | 
			
		||||
@@ -263,14 +263,14 @@ public class RedisReliableQueue<T> : QueueBase, IProducerConsumer<T>, IDisposabl
 | 
			
		||||
    {
 | 
			
		||||
        if (_delay == null)
 | 
			
		||||
        {
 | 
			
		||||
            lock (this)
 | 
			
		||||
            lock (lockThis)
 | 
			
		||||
            {
 | 
			
		||||
                _delay ??= new RedisDelayQueue<T>(Redis, $"{Key}:Delay");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if (_delayTask?.IsCompleted != false)
 | 
			
		||||
        {
 | 
			
		||||
            lock (this)
 | 
			
		||||
            lock (lockThis)
 | 
			
		||||
            {
 | 
			
		||||
                if (_delayTask?.IsCompleted != false)
 | 
			
		||||
                {
 | 
			
		||||
 
 | 
			
		||||
@@ -387,7 +387,7 @@ public abstract class Redis : Cache, IConfigMapping, ILogFeature
 | 
			
		||||
        get
 | 
			
		||||
        {
 | 
			
		||||
            if (_Pool != null) return _Pool;
 | 
			
		||||
            lock (this)
 | 
			
		||||
            lock (lockThis)
 | 
			
		||||
            {
 | 
			
		||||
                if (_Pool != null) return _Pool;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -53,6 +53,7 @@ public class RedisDeferred : DisposeBase
 | 
			
		||||
        _timer.TryDispose();
 | 
			
		||||
    }
 | 
			
		||||
    #endregion
 | 
			
		||||
    protected object lockThis = new();
 | 
			
		||||
 | 
			
		||||
    #region 方法
 | 
			
		||||
    /// <summary>放入队列。后面定时批量处理</summary>
 | 
			
		||||
@@ -68,7 +69,7 @@ public class RedisDeferred : DisposeBase
 | 
			
		||||
    {
 | 
			
		||||
        if (_timer == null)
 | 
			
		||||
        {
 | 
			
		||||
            lock (this)
 | 
			
		||||
            lock (lockThis)
 | 
			
		||||
            {
 | 
			
		||||
                if (_timer == null)
 | 
			
		||||
                {
 | 
			
		||||
 
 | 
			
		||||
@@ -47,7 +47,7 @@ public class RedisStat : DisposeBase
 | 
			
		||||
        _redis2.Log = _redis.Log;
 | 
			
		||||
        _queue = _redis2.GetReliableQueue<String>(name);
 | 
			
		||||
        _source = new CancellationTokenSource();
 | 
			
		||||
        Task.Factory.StartNew(() => _queue.ConsumeAsync<String>(OnProcess, _source.Token, null));
 | 
			
		||||
        Task.Factory.StartNew(() => _queue.ConsumeAsync<String>(OnProcess, _source.Token, null), CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>销毁</summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,6 @@
 | 
			
		||||
using System.ComponentModel;
 | 
			
		||||
using System.Runtime.Serialization;
 | 
			
		||||
using System.Xml.Serialization;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.NewLife.Common;
 | 
			
		||||
using ThingsGateway.NewLife.Configuration;
 | 
			
		||||
@@ -13,7 +15,7 @@ namespace ThingsGateway.NewLife;
 | 
			
		||||
/// 文档 https://newlifex.com/core/setting
 | 
			
		||||
/// </remarks>
 | 
			
		||||
[DisplayName("核心设置")]
 | 
			
		||||
[Config("Core")]
 | 
			
		||||
[Config("LogConfig", Provider = "json")]
 | 
			
		||||
public class Setting : Config<Setting>
 | 
			
		||||
{
 | 
			
		||||
    #region 属性
 | 
			
		||||
@@ -23,6 +25,7 @@ public class Setting : Config<Setting>
 | 
			
		||||
 | 
			
		||||
    /// <summary>日志等级,只输出大于等于该级别的日志,All/Debug/Info/Warn/Error/Fatal,默认Info</summary>
 | 
			
		||||
    [Description("日志等级。只输出大于等于该级别的日志,All/Debug/Info/Warn/Error/Fatal,默认Info")]
 | 
			
		||||
    [XmlIgnore, IgnoreDataMember]
 | 
			
		||||
    public LogLevel LogLevel { get; set; } = LogLevel.Info;
 | 
			
		||||
 | 
			
		||||
    /// <summary>文件日志目录。默认Log子目录</summary>
 | 
			
		||||
@@ -43,30 +46,37 @@ public class Setting : Config<Setting>
 | 
			
		||||
 | 
			
		||||
    /// <summary>日志行格式。默认Time|ThreadId|Kind|Name|Message,还支持Level</summary>
 | 
			
		||||
    [Description("日志行格式。默认Time|ThreadId|Kind|Name|Message,还支持Level")]
 | 
			
		||||
    [XmlIgnore, IgnoreDataMember]
 | 
			
		||||
    public String LogLineFormat { get; set; } = "Time|ThreadId|Kind|Name|Message";
 | 
			
		||||
 | 
			
		||||
    /// <summary>网络日志。本地子网日志广播udp://255.255.255.255:514,或者http://xxx:80/log</summary>
 | 
			
		||||
    [Description("网络日志。本地子网日志广播udp://255.255.255.255:514,或者http://xxx:80/log")]
 | 
			
		||||
    [XmlIgnore, IgnoreDataMember]
 | 
			
		||||
    public String NetworkLog { get; set; } = string.Empty;
 | 
			
		||||
 | 
			
		||||
    /// <summary>日志记录时间UTC校正,单位:小时。默认0表示使用的是本地时间,使用UTC时间的系统转换成本地时间则相差8小时</summary>
 | 
			
		||||
    [Description("日志记录时间UTC校正,小时")]
 | 
			
		||||
    [XmlIgnore, IgnoreDataMember]
 | 
			
		||||
    public Int32 UtcIntervalHours { get; set; } = 0;
 | 
			
		||||
 | 
			
		||||
    /// <summary>数据目录。本地数据库目录,默认Data子目录</summary>
 | 
			
		||||
    [Description("数据目录。本地数据库目录,默认Data子目录")]
 | 
			
		||||
    [XmlIgnore, IgnoreDataMember]
 | 
			
		||||
    public String DataPath { get; set; } = string.Empty;
 | 
			
		||||
 | 
			
		||||
    /// <summary>备份目录。备份数据库时存放的目录,默认Backup子目录</summary>
 | 
			
		||||
    [Description("备份目录。备份数据库时存放的目录,默认Backup子目录")]
 | 
			
		||||
    [XmlIgnore, IgnoreDataMember]
 | 
			
		||||
    public String BackupPath { get; set; } = string.Empty;
 | 
			
		||||
 | 
			
		||||
    /// <summary>插件目录</summary>
 | 
			
		||||
    [Description("插件目录")]
 | 
			
		||||
    [XmlIgnore, IgnoreDataMember]
 | 
			
		||||
    public String PluginPath { get; set; } = string.Empty;
 | 
			
		||||
 | 
			
		||||
    /// <summary>辅助解析程序集。程序集加载过程中,被依赖程序集未能解析时,是否协助解析,默认false</summary>
 | 
			
		||||
    [Description("辅助解析程序集。程序集加载过程中,被依赖程序集未能解析时,是否协助解析,默认false")]
 | 
			
		||||
    [XmlIgnore, IgnoreDataMember]
 | 
			
		||||
    public Boolean AssemblyResolve { get; set; }
 | 
			
		||||
 | 
			
		||||
    #endregion
 | 
			
		||||
 
 | 
			
		||||
@@ -12,6 +12,8 @@
 | 
			
		||||
		<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
 | 
			
		||||
		<SignAssembly>True</SignAssembly>
 | 
			
		||||
		<AssemblyOriginatorKeyFile>newlife.snk</AssemblyOriginatorKeyFile>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	</PropertyGroup>
 | 
			
		||||
 | 
			
		||||
	<ItemGroup>
 | 
			
		||||
 
 | 
			
		||||
@@ -62,6 +62,7 @@ public class TimerScheduler : ILogFeature
 | 
			
		||||
    private TimerX[] Timers = [];
 | 
			
		||||
    #endregion
 | 
			
		||||
 | 
			
		||||
    protected object lockThis = new();
 | 
			
		||||
    /// <summary>把定时器加入队列</summary>
 | 
			
		||||
    /// <param name="timer"></param>
 | 
			
		||||
    public void Add(TimerX timer)
 | 
			
		||||
@@ -73,7 +74,7 @@ public class TimerScheduler : ILogFeature
 | 
			
		||||
        timer.Id = Interlocked.Increment(ref _tid);
 | 
			
		||||
        WriteLog("Timer.Add {0}", timer);
 | 
			
		||||
 | 
			
		||||
        lock (this)
 | 
			
		||||
        lock (lockThis)
 | 
			
		||||
        {
 | 
			
		||||
            var list = new List<TimerX>(Timers);
 | 
			
		||||
            if (list.Contains(timer)) return;
 | 
			
		||||
@@ -109,7 +110,7 @@ public class TimerScheduler : ILogFeature
 | 
			
		||||
        using var span = DefaultTracer.Instance?.NewSpan("timer:Remove", reason + " " + timer);
 | 
			
		||||
        WriteLog("Timer.Remove {0} reason:{1}", timer, reason);
 | 
			
		||||
 | 
			
		||||
        lock (this)
 | 
			
		||||
        lock (lockThis)
 | 
			
		||||
        {
 | 
			
		||||
            timer.Id = 0;
 | 
			
		||||
 | 
			
		||||
@@ -172,7 +173,7 @@ public class TimerScheduler : ILogFeature
 | 
			
		||||
                        // 必须在主线程设置状态,否则可能异步线程还没来得及设置开始状态,主线程又开始了新的一轮调度
 | 
			
		||||
                        timer.Calling = true;
 | 
			
		||||
                        if (timer.IsAsyncTask)
 | 
			
		||||
                            Task.Factory.StartNew(ExecuteAsync, timer);
 | 
			
		||||
                            Task.Factory.StartNew(ExecuteAsync, timer, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default);
 | 
			
		||||
                        else if (!timer.Async)
 | 
			
		||||
                            Execute(timer);
 | 
			
		||||
                        else
 | 
			
		||||
 
 | 
			
		||||
@@ -1,121 +0,0 @@
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.NewLife.Log;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.NewLife.Web;
 | 
			
		||||
 | 
			
		||||
/// <summary>插件助手</summary>
 | 
			
		||||
public static class PluginHelper
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>创建客户端。便于外部自定义</summary>
 | 
			
		||||
    public static Func<String, WebClientX> CreateClient { get; set; } = linkName => new WebClientX { AuthKey = "NewLife", Log = XTrace.Log };
 | 
			
		||||
 | 
			
		||||
    /// <summary>加载插件</summary>
 | 
			
		||||
    /// <param name="typeName">插件类型</param>
 | 
			
		||||
    /// <param name="disname">显示名</param>
 | 
			
		||||
    /// <param name="dll">DLL文件</param>
 | 
			
		||||
    /// <param name="linkName">链接名。要在下载页面中搜索的链接名</param>
 | 
			
		||||
    /// <param name="urls">提供下载地址的多个目标页面</param>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    public static Type? LoadPlugin(String typeName, String? disname, String? dll, String? linkName, String? urls = null)
 | 
			
		||||
    {
 | 
			
		||||
        if (typeName.IsNullOrEmpty()) throw new ArgumentNullException(nameof(typeName));
 | 
			
		||||
 | 
			
		||||
        //var type = typeName.GetTypeEx(true);
 | 
			
		||||
        var type = Type.GetType(typeName);
 | 
			
		||||
        if (type != null) return type;
 | 
			
		||||
 | 
			
		||||
        if (dll.IsNullOrEmpty()) return null;
 | 
			
		||||
 | 
			
		||||
        var set = Setting.Current;
 | 
			
		||||
 | 
			
		||||
        var file = string.Empty;
 | 
			
		||||
        if (!dll.IsNullOrEmpty())
 | 
			
		||||
        {
 | 
			
		||||
            // 先检查程序集所在目录,再检查当前目录、基准目录和插件目录。在应用发布时,插件很可能跟常规应用程序集放在同一目录下
 | 
			
		||||
            var exe = Assembly.GetEntryAssembly()?.Location;
 | 
			
		||||
            if (exe.IsNullOrEmpty()) exe = Assembly.GetCallingAssembly()?.Location;
 | 
			
		||||
            if (exe.IsNullOrEmpty()) exe = Assembly.GetExecutingAssembly()?.Location;
 | 
			
		||||
            if (!exe.IsNullOrEmpty()) file = Path.GetDirectoryName(exe).CombinePath(dll).GetFullPath();
 | 
			
		||||
            if (!File.Exists(file)) file = dll.GetCurrentPath();
 | 
			
		||||
            if (!File.Exists(file)) file = dll.GetFullPath();
 | 
			
		||||
            if (!File.Exists(file)) file = dll.GetBasePath();
 | 
			
		||||
            if (!File.Exists(file)) file = set.PluginPath.CombinePath(dll).GetFullPath();
 | 
			
		||||
            if (!File.Exists(file)) file = set.PluginPath.CombinePath(dll).GetBasePath();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 尝试直接加载DLL
 | 
			
		||||
        if (File.Exists(file))
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                var asm = Assembly.LoadFrom(file);
 | 
			
		||||
                type = asm.GetType(typeName);
 | 
			
		||||
                if (type != null) return type;
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
                XTrace.WriteException(ex);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (linkName.IsNullOrEmpty()) return null;
 | 
			
		||||
 | 
			
		||||
        // 按类型名锁定,超时取不到锁,则放弃
 | 
			
		||||
        if (!Monitor.TryEnter(typeName, 15_000)) return null;
 | 
			
		||||
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            type = Type.GetType(typeName);
 | 
			
		||||
            if (type != null) return type;
 | 
			
		||||
 | 
			
		||||
            //if (urls.IsNullOrEmpty()) urls = set.PluginServer;
 | 
			
		||||
 | 
			
		||||
            // 如果本地没有数据库,则从网络下载
 | 
			
		||||
            if (!File.Exists(file))
 | 
			
		||||
            {
 | 
			
		||||
                XTrace.WriteLine("{0}不存在或平台版本不正确,准备联网获取 {1}", !disname.IsNullOrEmpty() ? disname : dll, urls);
 | 
			
		||||
 | 
			
		||||
                //var client = new WebClientX()
 | 
			
		||||
                //{
 | 
			
		||||
                //    Log = XTrace.Log
 | 
			
		||||
                //};
 | 
			
		||||
                using var client = CreateClient(linkName);
 | 
			
		||||
                var dir = Path.GetDirectoryName(file);
 | 
			
		||||
                var file2 = client.DownloadLinkAndExtract(urls, linkName, dir!, true);
 | 
			
		||||
                //client.TryDispose();
 | 
			
		||||
            }
 | 
			
		||||
            if (!File.Exists(file))
 | 
			
		||||
            {
 | 
			
		||||
                XTrace.WriteLine("未找到 {0} {1}", disname, dll);
 | 
			
		||||
                return null;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            //return Assembly.LoadFrom(file).GetType(typeName);
 | 
			
		||||
 | 
			
		||||
            type = Type.GetType(typeName);
 | 
			
		||||
            if (type != null) return type;
 | 
			
		||||
 | 
			
		||||
            // 尝试直接加载DLL
 | 
			
		||||
            if (File.Exists(file))
 | 
			
		||||
            {
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    var asm = Assembly.LoadFrom(file);
 | 
			
		||||
                    type = asm.GetType(typeName);
 | 
			
		||||
                    if (type != null) return type;
 | 
			
		||||
                }
 | 
			
		||||
                catch (Exception ex)
 | 
			
		||||
                {
 | 
			
		||||
                    XTrace.WriteException(ex);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
        finally
 | 
			
		||||
        {
 | 
			
		||||
            Monitor.Exit(typeName);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -22,9 +22,11 @@ namespace ThingsGateway.NewLife.Xml;
 | 
			
		||||
/// <typeparam name="TConfig"></typeparam>
 | 
			
		||||
public class XmlConfig<TConfig> : DisposeBase where TConfig : XmlConfig<TConfig>, new()
 | 
			
		||||
{
 | 
			
		||||
    protected object lockThis = new();
 | 
			
		||||
    #region 静态
 | 
			
		||||
    private static Boolean _loading;
 | 
			
		||||
    private static TConfig? _Current;
 | 
			
		||||
    private static WaitLock _WaitLock = new WaitLock(typeof(TConfig).FullName ?? "XmlConfig");
 | 
			
		||||
    /// <summary>当前实例。通过置空可以使其重新加载。</summary>
 | 
			
		||||
    public static TConfig Current
 | 
			
		||||
    {
 | 
			
		||||
@@ -58,7 +60,8 @@ public class XmlConfig<TConfig> : DisposeBase where TConfig : XmlConfig<TConfig>
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // 现在没有对象,尝试加载,若返回null则实例化一个新的
 | 
			
		||||
            lock (dcf)
 | 
			
		||||
            _WaitLock.Wait();
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                if (_Current != null) return _Current;
 | 
			
		||||
 | 
			
		||||
@@ -87,7 +90,10 @@ public class XmlConfig<TConfig> : DisposeBase where TConfig : XmlConfig<TConfig>
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                _WaitLock.Release();
 | 
			
		||||
            }
 | 
			
		||||
            return config;
 | 
			
		||||
        }
 | 
			
		||||
        set { _Current = value; }
 | 
			
		||||
@@ -295,7 +301,7 @@ public class XmlConfig<TConfig> : DisposeBase where TConfig : XmlConfig<TConfig>
 | 
			
		||||
        filename = filename.GetBasePath();
 | 
			
		||||
 | 
			
		||||
        // 加锁避免多线程保存同一个文件冲突
 | 
			
		||||
        lock (filename)
 | 
			
		||||
        lock (lockThis)
 | 
			
		||||
        {
 | 
			
		||||
            var xml1 = File.Exists(filename) ? File.ReadAllText(filename).Trim() : null;
 | 
			
		||||
            var xml2 = GetXml();
 | 
			
		||||
@@ -326,7 +332,7 @@ public class XmlConfig<TConfig> : DisposeBase where TConfig : XmlConfig<TConfig>
 | 
			
		||||
    {
 | 
			
		||||
        if (_Timer == null)
 | 
			
		||||
        {
 | 
			
		||||
            lock (this)
 | 
			
		||||
            lock (lockThis)
 | 
			
		||||
            {
 | 
			
		||||
                _Timer ??= new TimerX(DoSave, null, 1000, 5000)
 | 
			
		||||
                {
 | 
			
		||||
 
 | 
			
		||||
@@ -101,7 +101,9 @@ namespace Photino.Blazor
 | 
			
		||||
                while (true)
 | 
			
		||||
                {
 | 
			
		||||
                    var message = await reader.ReadAsync();
 | 
			
		||||
#pragma warning disable CA1849
 | 
			
		||||
                    _window.SendWebMessage(message);
 | 
			
		||||
#pragma warning restore CA1849
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            catch (ChannelClosedException) { }
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,7 @@
 | 
			
		||||
		<TargetFrameworks>net8.0</TargetFrameworks>
 | 
			
		||||
	</PropertyGroup>
 | 
			
		||||
	<ItemGroup>
 | 
			
		||||
		<PackageReference Include="BootstrapBlazor.FontAwesome" Version="9.0.2" />
 | 
			
		||||
		<PackageReference Include="BootstrapBlazor.FontAwesome" Version="9.1.0" />
 | 
			
		||||
	</ItemGroup>
 | 
			
		||||
 | 
			
		||||
	<ItemGroup>
 | 
			
		||||
 
 | 
			
		||||
@@ -23,7 +23,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <param name="propertyInfo">可选的属性信息数组,若为空则通过反射获取</param>
 | 
			
		||||
        /// <param name="sqlParameterKeyWord">SQL参数前缀,例如 "@"</param>
 | 
			
		||||
        /// <returns>SugarParameter 数组</returns>
 | 
			
		||||
        protected virtual IReadOnlyList<SugarParameter> GetParameters(object parameters, PropertyInfo[] propertyInfo, string sqlParameterKeyWord)
 | 
			
		||||
        protected virtual IReadOnlyCollection<SugarParameter> GetParameters(object parameters, PropertyInfo[] propertyInfo, string sqlParameterKeyWord)
 | 
			
		||||
        {
 | 
			
		||||
            if (parameters != null)
 | 
			
		||||
            {
 | 
			
		||||
@@ -37,7 +37,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
                    // 字典类型转参数
 | 
			
		||||
                    return DictionaryToParameters(parameters, sqlParameterKeyWord, entityType);
 | 
			
		||||
                }
 | 
			
		||||
                else if (parameters is IReadOnlyList<SugarParameter> sugarParamArray)
 | 
			
		||||
                else if (parameters is IReadOnlyCollection<SugarParameter> sugarParamArray)
 | 
			
		||||
                {
 | 
			
		||||
                    // 如果是 SugarParameter 数组,转 List
 | 
			
		||||
                    return sugarParamArray;
 | 
			
		||||
@@ -96,7 +96,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 将字典类型的参数转换为参数集合
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        protected IReadOnlyList<SugarParameter> DictionaryToParameters(object parameters, string sqlParameterKeyWord, Type entityType)
 | 
			
		||||
        protected IReadOnlyCollection<SugarParameter> DictionaryToParameters(object parameters, string sqlParameterKeyWord, Type entityType)
 | 
			
		||||
        {
 | 
			
		||||
            if (entityType == UtilConstants.DicArraySO)
 | 
			
		||||
            {
 | 
			
		||||
 
 | 
			
		||||
@@ -149,12 +149,12 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 日志开始事件
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public virtual Action<string, IReadOnlyList<SugarParameter>> LogEventStarting => this.Context.CurrentConnectionConfig.AopEvents?.OnLogExecuting;
 | 
			
		||||
        public virtual Action<string, IReadOnlyCollection<SugarParameter>> LogEventStarting => this.Context.CurrentConnectionConfig.AopEvents?.OnLogExecuting;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 日志完成事件
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public virtual Action<string, IReadOnlyList<SugarParameter>> LogEventCompleted => this.Context.CurrentConnectionConfig.AopEvents?.OnLogExecuted;
 | 
			
		||||
        public virtual Action<string, IReadOnlyCollection<SugarParameter>> LogEventCompleted => this.Context.CurrentConnectionConfig.AopEvents?.OnLogExecuted;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 检查连接执行前事件
 | 
			
		||||
@@ -169,17 +169,17 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 获取数据读取前事件
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public virtual Action<string, IReadOnlyList<SugarParameter>> OnGetDataReadering => this.Context.CurrentConnectionConfig.AopEvents?.OnGetDataReadering;
 | 
			
		||||
        public virtual Action<string, IReadOnlyCollection<SugarParameter>> OnGetDataReadering => this.Context.CurrentConnectionConfig.AopEvents?.OnGetDataReadering;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 获取数据读取后事件
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public virtual Action<string, IReadOnlyList<SugarParameter>, TimeSpan> OnGetDataReadered => this.Context.CurrentConnectionConfig.AopEvents?.OnGetDataReadered;
 | 
			
		||||
        public virtual Action<string, IReadOnlyCollection<SugarParameter>, TimeSpan> OnGetDataReadered => this.Context.CurrentConnectionConfig.AopEvents?.OnGetDataReadered;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 处理SQL执行前事件
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public virtual Func<string, IReadOnlyList<SugarParameter>, KeyValuePair<string, IReadOnlyList<SugarParameter>>> ProcessingEventStartingSQL => this.Context.CurrentConnectionConfig.AopEvents?.OnExecutingChangeSql;
 | 
			
		||||
        public virtual Func<string, IReadOnlyCollection<SugarParameter>, KeyValuePair<string, IReadOnlyCollection<SugarParameter>>> ProcessingEventStartingSQL => this.Context.CurrentConnectionConfig.AopEvents?.OnExecutingChangeSql;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// SQL格式化函数
 | 
			
		||||
@@ -374,7 +374,12 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
            {
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    await (Connection as DbConnection).OpenAsync().ConfigureAwait(false);
 | 
			
		||||
                    if (IsOpenAsync)
 | 
			
		||||
                        await (Connection as DbConnection).OpenAsync().ConfigureAwait(false);
 | 
			
		||||
                    else
 | 
			
		||||
#pragma warning disable CA1849
 | 
			
		||||
                        (Connection as DbConnection).Open();
 | 
			
		||||
#pragma warning restore CA1849
 | 
			
		||||
                }
 | 
			
		||||
                catch (Exception ex)
 | 
			
		||||
                {
 | 
			
		||||
@@ -531,7 +536,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 将SugarParameter数组转换为IDataParameter数组
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public abstract IDataParameter[] ToIDbDataParameter(params IReadOnlyList<SugarParameter> pars);
 | 
			
		||||
        public abstract IDataParameter[] ToIDbDataParameter(params IReadOnlyCollection<SugarParameter> pars);
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 设置命令到数据适配器
 | 
			
		||||
@@ -546,7 +551,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 获取数据库命令对象
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public abstract DbCommand GetCommand(string sql, IReadOnlyList<SugarParameter> pars);
 | 
			
		||||
        public abstract DbCommand GetCommand(string sql, IReadOnlyCollection<SugarParameter> pars);
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 数据库连接对象
 | 
			
		||||
@@ -609,10 +614,17 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
            var result = new DbResult<bool>();
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                await BeginTranAsync().ConfigureAwait(false);
 | 
			
		||||
                if (IsOpenAsync)
 | 
			
		||||
                    await BeginTranAsync().ConfigureAwait(false);
 | 
			
		||||
                else
 | 
			
		||||
#pragma warning disable CA1849
 | 
			
		||||
                    BeginTran();
 | 
			
		||||
                if (action != null)
 | 
			
		||||
                    await action().ConfigureAwait(false);
 | 
			
		||||
                await CommitTranAsync().ConfigureAwait(false);
 | 
			
		||||
                if (IsOpenAsync)
 | 
			
		||||
                    await CommitTranAsync().ConfigureAwait(false);
 | 
			
		||||
                else
 | 
			
		||||
                    CommitTran();
 | 
			
		||||
                result.Data = result.IsSuccess = true;
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
@@ -620,7 +632,11 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
                result.ErrorException = ex;
 | 
			
		||||
                result.ErrorMessage = ex.Message;
 | 
			
		||||
                result.IsSuccess = false;
 | 
			
		||||
                await RollbackTranAsync().ConfigureAwait(false);
 | 
			
		||||
                if (IsOpenAsync)
 | 
			
		||||
                    await RollbackTranAsync().ConfigureAwait(false);
 | 
			
		||||
                else
 | 
			
		||||
                    RollbackTran();
 | 
			
		||||
#pragma warning restore CA1849
 | 
			
		||||
                if (errorCallBack != null)
 | 
			
		||||
                {
 | 
			
		||||
                    errorCallBack(ex);
 | 
			
		||||
@@ -665,10 +681,17 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
            var result = new DbResult<T>();
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                await BeginTranAsync().ConfigureAwait(false);
 | 
			
		||||
                if (IsOpenAsync)
 | 
			
		||||
                    await BeginTranAsync().ConfigureAwait(false);
 | 
			
		||||
                else
 | 
			
		||||
#pragma warning disable CA1849
 | 
			
		||||
                    BeginTran();
 | 
			
		||||
                if (action != null)
 | 
			
		||||
                    result.Data = await action().ConfigureAwait(false);
 | 
			
		||||
                await CommitTranAsync().ConfigureAwait(false);
 | 
			
		||||
                if (IsOpenAsync)
 | 
			
		||||
                    await CommitTranAsync().ConfigureAwait(false);
 | 
			
		||||
                else
 | 
			
		||||
                    CommitTran();
 | 
			
		||||
                result.IsSuccess = true;
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
@@ -676,7 +699,11 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
                result.ErrorException = ex;
 | 
			
		||||
                result.ErrorMessage = ex.Message;
 | 
			
		||||
                result.IsSuccess = false;
 | 
			
		||||
                await RollbackTranAsync().ConfigureAwait(false);
 | 
			
		||||
                if (IsOpenAsync)
 | 
			
		||||
                    await RollbackTranAsync().ConfigureAwait(false);
 | 
			
		||||
                else
 | 
			
		||||
                    RollbackTran();
 | 
			
		||||
#pragma warning restore CA1849
 | 
			
		||||
                if (errorCallBack != null)
 | 
			
		||||
                {
 | 
			
		||||
                    errorCallBack(ex);
 | 
			
		||||
@@ -702,7 +729,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 执行包含GO语句的SQL命令
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public virtual int ExecuteCommandWithGo(string sql, params IReadOnlyList<SugarParameter> parameters)
 | 
			
		||||
        public virtual int ExecuteCommandWithGo(string sql, params IReadOnlyCollection<SugarParameter> parameters)
 | 
			
		||||
        {
 | 
			
		||||
            if (string.IsNullOrEmpty(sql))
 | 
			
		||||
                return 0;
 | 
			
		||||
@@ -735,7 +762,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 执行SQL命令
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public virtual int ExecuteCommand(string sql, params IReadOnlyList<SugarParameter> parameters)
 | 
			
		||||
        public virtual int ExecuteCommand(string sql, params IReadOnlyCollection<SugarParameter> parameters)
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
@@ -782,7 +809,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 获取数据读取器
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public virtual IDataReader GetDataReader(string sql, params IReadOnlyList<SugarParameter> parameters)
 | 
			
		||||
        public virtual IDataReader GetDataReader(string sql, params IReadOnlyCollection<SugarParameter> parameters)
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
@@ -830,7 +857,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 获取数据集
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public virtual DataSet GetDataSetAll(string sql, params IReadOnlyList<SugarParameter> parameters)
 | 
			
		||||
        public virtual DataSet GetDataSetAll(string sql, params IReadOnlyCollection<SugarParameter> parameters)
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
@@ -878,7 +905,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 获取单个值
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public virtual object GetScalar(string sql, params IReadOnlyList<SugarParameter> parameters)
 | 
			
		||||
        public virtual object GetScalar(string sql, params IReadOnlyCollection<SugarParameter> parameters)
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
@@ -922,7 +949,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 异步执行SQL命令
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public virtual async Task<int> ExecuteCommandAsync(string sql, params IReadOnlyList<SugarParameter> parameters)
 | 
			
		||||
        public virtual async Task<int> ExecuteCommandAsync(string sql, params IReadOnlyCollection<SugarParameter> parameters)
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
@@ -939,7 +966,9 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
                    ExecuteProcessingSQL(ref sql, ref parameters);
 | 
			
		||||
 | 
			
		||||
                ExecuteBefore(sql, parameters);
 | 
			
		||||
#pragma warning disable CA1849
 | 
			
		||||
                var sqlCommand = IsOpenAsync ? await GetCommandAsync(sql, parameters).ConfigureAwait(false) : GetCommand(sql, parameters);
 | 
			
		||||
#pragma warning restore CA1849
 | 
			
		||||
 | 
			
		||||
                int count;
 | 
			
		||||
                if (this.CancellationToken == null)
 | 
			
		||||
@@ -965,7 +994,8 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
            }
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                if (this.IsAutoClose()) this.Close();
 | 
			
		||||
                if (this.IsAutoClose())
 | 
			
		||||
                    await this.CloseAsync().ConfigureAwait(false);
 | 
			
		||||
                SetConnectionEnd(sql);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@@ -973,7 +1003,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 异步获取数据读取器
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public virtual async Task<IDataReader> GetDataReaderAsync(string sql, params IReadOnlyList<SugarParameter> parameters)
 | 
			
		||||
        public virtual async Task<IDataReader> GetDataReaderAsync(string sql, params IReadOnlyCollection<SugarParameter> parameters)
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
@@ -992,7 +1022,9 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
                    ExecuteProcessingSQL(ref sql, ref parameters);
 | 
			
		||||
 | 
			
		||||
                ExecuteBefore(sql, parameters);
 | 
			
		||||
#pragma warning disable CA1849
 | 
			
		||||
                var sqlCommand = IsOpenAsync ? await GetCommandAsync(sql, parameters).ConfigureAwait(false) : GetCommand(sql, parameters);
 | 
			
		||||
#pragma warning restore CA1849
 | 
			
		||||
 | 
			
		||||
                DbDataReader sqlDataReader;
 | 
			
		||||
                if (this.CancellationToken == null)
 | 
			
		||||
@@ -1027,7 +1059,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 异步获取单个值
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public virtual async Task<object> GetScalarAsync(string sql, params IReadOnlyList<SugarParameter> parameters)
 | 
			
		||||
        public virtual async Task<object> GetScalarAsync(string sql, params IReadOnlyCollection<SugarParameter> parameters)
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
@@ -1044,7 +1076,9 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
                    ExecuteProcessingSQL(ref sql, ref parameters);
 | 
			
		||||
 | 
			
		||||
                ExecuteBefore(sql, parameters);
 | 
			
		||||
#pragma warning disable CA1849
 | 
			
		||||
                var sqlCommand = IsOpenAsync ? await GetCommandAsync(sql, parameters).ConfigureAwait(false) : GetCommand(sql, parameters);
 | 
			
		||||
#pragma warning restore CA1849
 | 
			
		||||
 | 
			
		||||
                object scalar;
 | 
			
		||||
                if (CancellationToken == null)
 | 
			
		||||
@@ -1069,7 +1103,8 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
            }
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                if (this.IsAutoClose()) this.Close();
 | 
			
		||||
                if (this.IsAutoClose())
 | 
			
		||||
                    await this.CloseAsync().ConfigureAwait(false);
 | 
			
		||||
                SetConnectionEnd(sql);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@@ -1077,7 +1112,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 异步获取数据集(伪异步实现)
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public virtual Task<DataSet> GetDataSetAllAsync(string sql, params IReadOnlyList<SugarParameter> parameters)
 | 
			
		||||
        public virtual Task<DataSet> GetDataSetAllAsync(string sql, params IReadOnlyCollection<SugarParameter> parameters)
 | 
			
		||||
        {
 | 
			
		||||
            Async();
 | 
			
		||||
 | 
			
		||||
@@ -1106,7 +1141,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 获取字符串结果(使用参数数组)
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public virtual string GetString(string sql, params IReadOnlyList<SugarParameter> parameters)
 | 
			
		||||
        public virtual string GetString(string sql, params IReadOnlyCollection<SugarParameter> parameters)
 | 
			
		||||
        {
 | 
			
		||||
            return Convert.ToString(GetScalar(sql, parameters));
 | 
			
		||||
        }
 | 
			
		||||
@@ -1122,7 +1157,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 异步获取字符串结果(使用参数数组)
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public virtual async Task<string> GetStringAsync(string sql, params IReadOnlyList<SugarParameter> parameters)
 | 
			
		||||
        public virtual async Task<string> GetStringAsync(string sql, params IReadOnlyCollection<SugarParameter> parameters)
 | 
			
		||||
        {
 | 
			
		||||
            return Convert.ToString(await GetScalarAsync(sql, parameters).ConfigureAwait(false));
 | 
			
		||||
        }
 | 
			
		||||
@@ -1154,7 +1189,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 获取整型结果(使用参数数组)
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public virtual int GetInt(string sql, params IReadOnlyList<SugarParameter> parameters)
 | 
			
		||||
        public virtual int GetInt(string sql, params IReadOnlyCollection<SugarParameter> parameters)
 | 
			
		||||
        {
 | 
			
		||||
            return GetScalar(sql, parameters).ObjToInt();
 | 
			
		||||
        }
 | 
			
		||||
@@ -1170,7 +1205,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 异步获取整型结果(使用参数数组)
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public virtual async Task<int> GetIntAsync(string sql, params IReadOnlyList<SugarParameter> parameters)
 | 
			
		||||
        public virtual async Task<int> GetIntAsync(string sql, params IReadOnlyCollection<SugarParameter> parameters)
 | 
			
		||||
        {
 | 
			
		||||
            var list = await GetScalarAsync(sql, parameters).ConfigureAwait(false);
 | 
			
		||||
            return list.ObjToInt();
 | 
			
		||||
@@ -1187,7 +1222,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 获取双精度浮点数结果(使用参数数组)
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public virtual Double GetDouble(string sql, params IReadOnlyList<SugarParameter> parameters)
 | 
			
		||||
        public virtual Double GetDouble(string sql, params IReadOnlyCollection<SugarParameter> parameters)
 | 
			
		||||
        {
 | 
			
		||||
            return GetScalar(sql, parameters).ObjToMoney();
 | 
			
		||||
        }
 | 
			
		||||
@@ -1203,7 +1238,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 异步获取双精度浮点数结果(使用参数数组)
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public virtual async Task<Double> GetDoubleAsync(string sql, params IReadOnlyList<SugarParameter> parameters)
 | 
			
		||||
        public virtual async Task<Double> GetDoubleAsync(string sql, params IReadOnlyCollection<SugarParameter> parameters)
 | 
			
		||||
        {
 | 
			
		||||
            var result = await GetScalarAsync(sql, parameters).ConfigureAwait(false);
 | 
			
		||||
            return result.ObjToMoney();
 | 
			
		||||
@@ -1220,7 +1255,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 获取十进制数结果(使用参数数组)
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public virtual decimal GetDecimal(string sql, params IReadOnlyList<SugarParameter> parameters)
 | 
			
		||||
        public virtual decimal GetDecimal(string sql, params IReadOnlyCollection<SugarParameter> parameters)
 | 
			
		||||
        {
 | 
			
		||||
            return GetScalar(sql, parameters).ObjToDecimal();
 | 
			
		||||
        }
 | 
			
		||||
@@ -1236,7 +1271,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 异步获取十进制数结果(使用参数数组)
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public virtual async Task<decimal> GetDecimalAsync(string sql, params IReadOnlyList<SugarParameter> parameters)
 | 
			
		||||
        public virtual async Task<decimal> GetDecimalAsync(string sql, params IReadOnlyCollection<SugarParameter> parameters)
 | 
			
		||||
        {
 | 
			
		||||
            var result = await GetScalarAsync(sql, parameters).ConfigureAwait(false);
 | 
			
		||||
            return result.ObjToDecimal();
 | 
			
		||||
@@ -1253,7 +1288,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 获取日期时间结果(使用参数数组)
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public virtual DateTime GetDateTime(string sql, params IReadOnlyList<SugarParameter> parameters)
 | 
			
		||||
        public virtual DateTime GetDateTime(string sql, params IReadOnlyCollection<SugarParameter> parameters)
 | 
			
		||||
        {
 | 
			
		||||
            return GetScalar(sql, parameters).ObjToDate();
 | 
			
		||||
        }
 | 
			
		||||
@@ -1269,7 +1304,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 异步获取日期时间结果(使用参数数组)
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public virtual async Task<DateTime> GetDateTimeAsync(string sql, params IReadOnlyList<SugarParameter> parameters)
 | 
			
		||||
        public virtual async Task<DateTime> GetDateTimeAsync(string sql, params IReadOnlyCollection<SugarParameter> parameters)
 | 
			
		||||
        {
 | 
			
		||||
            var list = await GetScalarAsync(sql, parameters).ConfigureAwait(false);
 | 
			
		||||
            return list.ObjToDate();
 | 
			
		||||
@@ -1291,7 +1326,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 执行SQL查询并返回对象列表(使用参数数组)
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public virtual List<T> SqlQuery<T>(string sql, params IReadOnlyList<SugarParameter> parameters)
 | 
			
		||||
        public virtual List<T> SqlQuery<T>(string sql, params IReadOnlyCollection<SugarParameter> parameters)
 | 
			
		||||
        {
 | 
			
		||||
            var result = SqlQuery<T, object, object, object, object, object, object>(sql, parameters);
 | 
			
		||||
            return result.Item1;
 | 
			
		||||
@@ -1378,7 +1413,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
            if (parsmeterArray != null && parsmeterArray.Count != 0)
 | 
			
		||||
                builder.SqlQueryBuilder.Parameters.AddRange(parsmeterArray);
 | 
			
		||||
            string sqlString = builder.SqlQueryBuilder.ToSqlString();
 | 
			
		||||
            IReadOnlyList<SugarParameter> Parameters = builder.SqlQueryBuilder.Parameters;
 | 
			
		||||
            IReadOnlyCollection<SugarParameter> Parameters = builder.SqlQueryBuilder.Parameters;
 | 
			
		||||
            this.GetDataBefore(sqlString, Parameters);
 | 
			
		||||
            using (var dataReader = this.GetDataReader(sqlString, Parameters))
 | 
			
		||||
            {
 | 
			
		||||
@@ -1468,7 +1503,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 异步执行SQL查询并返回对象列表(使用参数数组)
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public virtual async Task<List<T>> SqlQueryAsync<T>(string sql, params IReadOnlyList<SugarParameter> parameters)
 | 
			
		||||
        public virtual async Task<List<T>> SqlQueryAsync<T>(string sql, params IReadOnlyCollection<SugarParameter> parameters)
 | 
			
		||||
        {
 | 
			
		||||
            var result = await SqlQueryAsync<T, object, object, object, object, object, object>(sql, parameters).ConfigureAwait(false);
 | 
			
		||||
            return result.Item1;
 | 
			
		||||
@@ -1531,7 +1566,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
            if (parsmeterArray != null && parsmeterArray.Count != 0)
 | 
			
		||||
                builder.SqlQueryBuilder.Parameters.AddRange(parsmeterArray);
 | 
			
		||||
            string sqlString = builder.SqlQueryBuilder.ToSqlString();
 | 
			
		||||
            IReadOnlyList<SugarParameter> Parameters = builder.SqlQueryBuilder.Parameters;
 | 
			
		||||
            IReadOnlyCollection<SugarParameter> Parameters = builder.SqlQueryBuilder.Parameters;
 | 
			
		||||
            this.GetDataBefore(sqlString, Parameters);
 | 
			
		||||
            using (var dataReader = await GetDataReaderAsync(sqlString, Parameters).ConfigureAwait(false))
 | 
			
		||||
            {
 | 
			
		||||
@@ -1609,7 +1644,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 执行SQL查询并返回单个对象(使用参数数组)
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public virtual T SqlQuerySingle<T>(string sql, params IReadOnlyList<SugarParameter> parameters)
 | 
			
		||||
        public virtual T SqlQuerySingle<T>(string sql, params IReadOnlyCollection<SugarParameter> parameters)
 | 
			
		||||
        {
 | 
			
		||||
            var result = SqlQuery<T>(sql, parameters);
 | 
			
		||||
            return result == null ? default(T) : result.FirstOrDefault();
 | 
			
		||||
@@ -1627,7 +1662,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 异步执行SQL查询并返回单个对象(使用参数数组)
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public virtual async Task<T> SqlQuerySingleAsync<T>(string sql, params IReadOnlyList<SugarParameter> parameters)
 | 
			
		||||
        public virtual async Task<T> SqlQuerySingleAsync<T>(string sql, params IReadOnlyCollection<SugarParameter> parameters)
 | 
			
		||||
        {
 | 
			
		||||
            var result = await SqlQueryAsync<T>(sql, parameters).ConfigureAwait(false);
 | 
			
		||||
            return result == null ? default(T) : result.FirstOrDefault();
 | 
			
		||||
@@ -1640,7 +1675,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 获取DataTable(使用参数数组)
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public virtual DataTable GetDataTable(string sql, params IReadOnlyList<SugarParameter> parameters)
 | 
			
		||||
        public virtual DataTable GetDataTable(string sql, params IReadOnlyCollection<SugarParameter> parameters)
 | 
			
		||||
        {
 | 
			
		||||
            var ds = GetDataSetAll(sql, parameters);
 | 
			
		||||
            if (ds.Tables.Count != 0 && ds.Tables.Count > 0) return ds.Tables[0];
 | 
			
		||||
@@ -1658,7 +1693,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 异步获取DataTable(使用参数数组)
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public virtual async Task<DataTable> GetDataTableAsync(string sql, params IReadOnlyList<SugarParameter> parameters)
 | 
			
		||||
        public virtual async Task<DataTable> GetDataTableAsync(string sql, params IReadOnlyCollection<SugarParameter> parameters)
 | 
			
		||||
        {
 | 
			
		||||
            var ds = await GetDataSetAllAsync(sql, parameters).ConfigureAwait(false);
 | 
			
		||||
            if (ds.Tables.Count != 0 && ds.Tables.Count > 0) return ds.Tables[0];
 | 
			
		||||
@@ -1769,7 +1804,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 异步获取命令对象(需要子类实现)
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public virtual async Task<DbCommand> GetCommandAsync(string sql, IReadOnlyList<SugarParameter> parameters)
 | 
			
		||||
        public virtual async Task<DbCommand> GetCommandAsync(string sql, IReadOnlyCollection<SugarParameter> parameters)
 | 
			
		||||
        {
 | 
			
		||||
            await Task.FromResult(0).ConfigureAwait(false);
 | 
			
		||||
            throw new NotImplementedException();
 | 
			
		||||
@@ -1786,7 +1821,12 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
            }
 | 
			
		||||
            if (this.Connection != null && this.Connection.State == ConnectionState.Open)
 | 
			
		||||
            {
 | 
			
		||||
                await (Connection as DbConnection).CloseAsync().ConfigureAwait(false);
 | 
			
		||||
                if (IsOpenAsync)
 | 
			
		||||
                    await (Connection as DbConnection).CloseAsync().ConfigureAwait(false);
 | 
			
		||||
                else
 | 
			
		||||
#pragma warning disable CA1849
 | 
			
		||||
                    (Connection as DbConnection).Close();
 | 
			
		||||
#pragma warning restore CA1849
 | 
			
		||||
            }
 | 
			
		||||
            if (this.IsMasterSlaveSeparation && this.SlaveConnections.HasValue())
 | 
			
		||||
            {
 | 
			
		||||
@@ -1794,7 +1834,12 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
                {
 | 
			
		||||
                    if (slaveConnection != null && slaveConnection.State == ConnectionState.Open)
 | 
			
		||||
                    {
 | 
			
		||||
                        await (slaveConnection as DbConnection).CloseAsync().ConfigureAwait(false);
 | 
			
		||||
                        if (IsOpenAsync)
 | 
			
		||||
                            await (Connection as DbConnection).CloseAsync().ConfigureAwait(false);
 | 
			
		||||
                        else
 | 
			
		||||
#pragma warning disable CA1849
 | 
			
		||||
                            (Connection as DbConnection).Close();
 | 
			
		||||
#pragma warning restore CA1849
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@@ -1803,7 +1848,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 异常处理
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        protected virtual void SugarCatch(Exception ex, string sql, IReadOnlyList<SugarParameter> parameters)
 | 
			
		||||
        protected virtual void SugarCatch(Exception ex, string sql, IReadOnlyCollection<SugarParameter> parameters)
 | 
			
		||||
        {
 | 
			
		||||
            if (sql?.Contains("{year}{month}{day}") == true)
 | 
			
		||||
            {
 | 
			
		||||
@@ -1848,7 +1893,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 处理执行前的SQL
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        protected void ExecuteProcessingSQL(ref string sql, ref IReadOnlyList<SugarParameter> parameters)
 | 
			
		||||
        protected void ExecuteProcessingSQL(ref string sql, ref IReadOnlyCollection<SugarParameter> parameters)
 | 
			
		||||
        {
 | 
			
		||||
            var result = this.ProcessingEventStartingSQL(sql, parameters);
 | 
			
		||||
            sql = result.Key;
 | 
			
		||||
@@ -1858,12 +1903,12 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 执行前的操作
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public virtual void ExecuteBefore(string sql, IReadOnlyList<SugarParameter> parameters)
 | 
			
		||||
        public virtual void ExecuteBefore(string sql, IReadOnlyCollection<SugarParameter> parameters)
 | 
			
		||||
        {
 | 
			
		||||
            this.BeforeTime = DateTime.Now;
 | 
			
		||||
            if (this.IsEnableLogEvent)
 | 
			
		||||
            {
 | 
			
		||||
                Action<string, IReadOnlyList<SugarParameter>> action = LogEventStarting;
 | 
			
		||||
                Action<string, IReadOnlyCollection<SugarParameter>> action = LogEventStarting;
 | 
			
		||||
                if (action != null)
 | 
			
		||||
                {
 | 
			
		||||
                    if (parameters == null || parameters.Count == 0)
 | 
			
		||||
@@ -1881,7 +1926,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 执行后的操作
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public virtual void ExecuteAfter(string sql, IReadOnlyList<SugarParameter> parameters)
 | 
			
		||||
        public virtual void ExecuteAfter(string sql, IReadOnlyCollection<SugarParameter> parameters)
 | 
			
		||||
        {
 | 
			
		||||
            this.AfterTime = DateTime.Now;
 | 
			
		||||
            var hasParameter = parameters.HasValue();
 | 
			
		||||
@@ -1900,7 +1945,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
            }
 | 
			
		||||
            if (this.IsEnableLogEvent)
 | 
			
		||||
            {
 | 
			
		||||
                Action<string, IReadOnlyList<SugarParameter>> action = LogEventCompleted;
 | 
			
		||||
                Action<string, IReadOnlyCollection<SugarParameter>> action = LogEventCompleted;
 | 
			
		||||
                if (action != null)
 | 
			
		||||
                {
 | 
			
		||||
                    if (parameters == null || parameters.Count == 0)
 | 
			
		||||
@@ -1928,12 +1973,12 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="sql">SQL语句</param>
 | 
			
		||||
        /// <param name="parameters">参数数组</param>
 | 
			
		||||
        public virtual void GetDataBefore(string sql, IReadOnlyList<SugarParameter> parameters)
 | 
			
		||||
        public virtual void GetDataBefore(string sql, IReadOnlyCollection<SugarParameter> parameters)
 | 
			
		||||
        {
 | 
			
		||||
            this.GetDataBeforeTime = DateTime.Now;
 | 
			
		||||
            if (this.IsEnableLogEvent)
 | 
			
		||||
            {
 | 
			
		||||
                Action<string, IReadOnlyList<SugarParameter>> action = OnGetDataReadering;
 | 
			
		||||
                Action<string, IReadOnlyCollection<SugarParameter>> action = OnGetDataReadering;
 | 
			
		||||
                if (action != null)
 | 
			
		||||
                {
 | 
			
		||||
                    if (parameters == null || parameters.Count == 0)
 | 
			
		||||
@@ -1953,12 +1998,12 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="sql">SQL语句</param>
 | 
			
		||||
        /// <param name="parameters">参数数组</param>
 | 
			
		||||
        public virtual void GetDataAfter(string sql, IReadOnlyList<SugarParameter> parameters)
 | 
			
		||||
        public virtual void GetDataAfter(string sql, IReadOnlyCollection<SugarParameter> parameters)
 | 
			
		||||
        {
 | 
			
		||||
            this.GetDataAfterTime = DateTime.Now;
 | 
			
		||||
            if (this.IsEnableLogEvent)
 | 
			
		||||
            {
 | 
			
		||||
                Action<string, IReadOnlyList<SugarParameter>, TimeSpan> action = OnGetDataReadered;
 | 
			
		||||
                Action<string, IReadOnlyCollection<SugarParameter>, TimeSpan> action = OnGetDataReadered;
 | 
			
		||||
                if (action != null)
 | 
			
		||||
                {
 | 
			
		||||
                    if (parameters == null || parameters.Count == 0)
 | 
			
		||||
@@ -1981,7 +2026,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <param name="parameters">参数对象</param>
 | 
			
		||||
        /// <param name="propertyInfo">属性信息数组</param>
 | 
			
		||||
        /// <returns>SugarParameter数组</returns>
 | 
			
		||||
        public virtual IReadOnlyList<SugarParameter> GetParameters(object parameters, PropertyInfo[] propertyInfo = null)
 | 
			
		||||
        public virtual IReadOnlyCollection<SugarParameter> GetParameters(object parameters, PropertyInfo[] propertyInfo = null)
 | 
			
		||||
        {
 | 
			
		||||
            if (parameters == null) return Array.Empty<SugarParameter>();
 | 
			
		||||
            return base.GetParameters(parameters, propertyInfo, this.SqlParameterKeyWord);
 | 
			
		||||
@@ -2065,7 +2110,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 检查是否需要格式化SQL
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private bool IsFormat(IReadOnlyList<SugarParameter> parameters)
 | 
			
		||||
        private bool IsFormat(IReadOnlyCollection<SugarParameter> parameters)
 | 
			
		||||
        {
 | 
			
		||||
            return FormatSql != null && parameters?.Count > 0;
 | 
			
		||||
        }
 | 
			
		||||
@@ -2105,7 +2150,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <param name="sql">SQL语句</param>
 | 
			
		||||
        /// <param name="parameters">参数数组</param>
 | 
			
		||||
        /// <param name="ex">异常对象</param>
 | 
			
		||||
        protected void ExecuteErrorEvent(string sql, IReadOnlyList<SugarParameter> parameters, Exception ex)
 | 
			
		||||
        protected void ExecuteErrorEvent(string sql, IReadOnlyCollection<SugarParameter> parameters, Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
            this.AfterTime = DateTime.Now;
 | 
			
		||||
            ErrorEvent(new SqlSugarException(this.Context, ex, sql, parameters));
 | 
			
		||||
@@ -2120,7 +2165,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="sql">SQL语句引用</param>
 | 
			
		||||
        /// <param name="parameters">参数数组</param>
 | 
			
		||||
        protected void InitParameters(ref string sql, IReadOnlyList<SugarParameter> parameters)
 | 
			
		||||
        protected void InitParameters(ref string sql, IReadOnlyCollection<SugarParameter> parameters)
 | 
			
		||||
        {
 | 
			
		||||
            this.SqlExecuteCount = 0;
 | 
			
		||||
            this.BeforeTime = DateTime.MinValue;
 | 
			
		||||
 
 | 
			
		||||
@@ -36,17 +36,17 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 设置SQL执行前日志事件处理程序
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public Action<string, IReadOnlyList<SugarParameter>> OnLogExecuting { set { this.Context.CurrentConnectionConfig.AopEvents.OnLogExecuting = value; } }
 | 
			
		||||
        public Action<string, IReadOnlyCollection<SugarParameter>> OnLogExecuting { set { this.Context.CurrentConnectionConfig.AopEvents.OnLogExecuting = value; } }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 设置SQL执行后日志事件处理程序
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public Action<string, IReadOnlyList<SugarParameter>> OnLogExecuted { set { this.Context.CurrentConnectionConfig.AopEvents.OnLogExecuted = value; } }
 | 
			
		||||
        public Action<string, IReadOnlyCollection<SugarParameter>> OnLogExecuted { set { this.Context.CurrentConnectionConfig.AopEvents.OnLogExecuted = value; } }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 设置执行SQL前修改SQL的事件处理程序
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public Func<string, IReadOnlyList<SugarParameter>, KeyValuePair<string, IReadOnlyList<SugarParameter>>> OnExecutingChangeSql { set { this.Context.CurrentConnectionConfig.AopEvents.OnExecutingChangeSql = value; } }
 | 
			
		||||
        public Func<string, IReadOnlyCollection<SugarParameter>, KeyValuePair<string, IReadOnlyCollection<SugarParameter>>> OnExecutingChangeSql { set { this.Context.CurrentConnectionConfig.AopEvents.OnExecutingChangeSql = value; } }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 设置数据执行前事件处理程序
 | 
			
		||||
@@ -76,11 +76,11 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 设置获取数据读取前事件处理程序
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public Action<string, IReadOnlyList<SugarParameter>> OnGetDataReadering { set { this.Context.CurrentConnectionConfig.AopEvents.OnGetDataReadering = value; } }
 | 
			
		||||
        public Action<string, IReadOnlyCollection<SugarParameter>> OnGetDataReadering { set { this.Context.CurrentConnectionConfig.AopEvents.OnGetDataReadering = value; } }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 设置获取数据读取后事件处理程序
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public Action<string, IReadOnlyList<SugarParameter>, TimeSpan> OnGetDataReadered { set { this.Context.CurrentConnectionConfig.AopEvents.OnGetDataReadered = value; } }
 | 
			
		||||
        public Action<string, IReadOnlyCollection<SugarParameter>, TimeSpan> OnGetDataReadered { set { this.Context.CurrentConnectionConfig.AopEvents.OnGetDataReadered = value; } }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -222,7 +222,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <param name="type">实体类型</param>
 | 
			
		||||
        /// <param name="newTableName">新表名</param>
 | 
			
		||||
        /// <returns>代码优先接口</returns>
 | 
			
		||||
        public ICodeFirst As(Type type, string newTableName)
 | 
			
		||||
        public ICodeFirst AS(Type type, string newTableName)
 | 
			
		||||
        {
 | 
			
		||||
            if (!MappingTables.TryAdd(type, newTableName))
 | 
			
		||||
            {
 | 
			
		||||
@@ -236,9 +236,9 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <typeparam name="T">实体类型</typeparam>
 | 
			
		||||
        /// <param name="newTableName">新表名</param>
 | 
			
		||||
        /// <returns>代码优先接口</returns>
 | 
			
		||||
        public ICodeFirst As<T>(string newTableName)
 | 
			
		||||
        public ICodeFirst AS<T>(string newTableName)
 | 
			
		||||
        {
 | 
			
		||||
            return As(typeof(T), newTableName);
 | 
			
		||||
            return AS(typeof(T), newTableName);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -192,7 +192,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
                            }
 | 
			
		||||
                            else if (UtilMethods.IsParameterConverter(item))
 | 
			
		||||
                            {
 | 
			
		||||
                                setValue = UtilMethods.QueryConverter(itemIndex, null, dataReader, entityInfo, item);
 | 
			
		||||
                                setValue = UtilMethods.QueryConverter(itemIndex, dataReader, entityInfo, item);
 | 
			
		||||
                            }
 | 
			
		||||
                            item.PropertyInfo.SetValue(parentObj, setValue);
 | 
			
		||||
                        }
 | 
			
		||||
@@ -210,8 +210,8 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        {
 | 
			
		||||
            var formats = this.QueryBuilder.QueryableFormats;
 | 
			
		||||
            var columns = this.QueryBuilder.Context.EntityMaintenance.GetEntityInfoWithAttr(typeof(T))
 | 
			
		||||
                .Columns.Where(it => formats.Any(y => y.PropertyName == it.PropertyName));
 | 
			
		||||
            if (columns.Any())
 | 
			
		||||
                .Columns.Where(it => formats.Any(y => y.PropertyName == it.PropertyName)).ToArray();
 | 
			
		||||
            if (columns.Length != 0)
 | 
			
		||||
            {
 | 
			
		||||
                foreach (var item in formats)
 | 
			
		||||
                {
 | 
			
		||||
 
 | 
			
		||||
@@ -195,6 +195,10 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        {
 | 
			
		||||
            dbTypeName = dbTypeName.ToLower();
 | 
			
		||||
            var propertyTypes = MappingTypes.Where(it => it.Key.Equals(dbTypeName, StringComparison.CurrentCultureIgnoreCase));
 | 
			
		||||
 | 
			
		||||
            var kv = propertyTypes.FirstOrDefault();
 | 
			
		||||
            var key = kv.Key;
 | 
			
		||||
            var type = kv.Value;
 | 
			
		||||
            if (dbTypeName == "int32")
 | 
			
		||||
            {
 | 
			
		||||
                return "int";
 | 
			
		||||
@@ -219,17 +223,17 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
            {
 | 
			
		||||
                return "bool";
 | 
			
		||||
            }
 | 
			
		||||
            else if (propertyTypes?.Any() != true)
 | 
			
		||||
            else if (key == null)
 | 
			
		||||
            {
 | 
			
		||||
                return "object";
 | 
			
		||||
            }
 | 
			
		||||
            else if (propertyTypes.First().Value == CSharpDataType.byteArray)
 | 
			
		||||
            else if (type == CSharpDataType.byteArray)
 | 
			
		||||
            {
 | 
			
		||||
                return "byte[]";
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                return propertyTypes.First().Value.ToString();
 | 
			
		||||
                return type.ToString();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -367,7 +371,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <returns>实体列表</returns>
 | 
			
		||||
        public virtual List<T> GetEntityListByType<T>(Type entityType, SqlSugarProvider context, IDataReader dataReader)
 | 
			
		||||
        {
 | 
			
		||||
            var method = typeof(DbBindProvider).GetMethod("GetEntityList", BindingFlags.Instance | BindingFlags.NonPublic);
 | 
			
		||||
            var method = typeof(DbBindProvider).GetMethod(nameof(GetEntityList), BindingFlags.Instance | BindingFlags.NonPublic);
 | 
			
		||||
            var genericMethod = method.MakeGenericMethod(entityType);
 | 
			
		||||
            var objectValue = genericMethod.Invoke(this, new object[] { context, dataReader });
 | 
			
		||||
            List<T> result = new List<T>();
 | 
			
		||||
@@ -388,7 +392,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <returns>实体列表</returns>
 | 
			
		||||
        public virtual async Task<List<T>> GetEntityListByTypeAsync<T>(Type entityType, SqlSugarProvider context, IDataReader dataReader)
 | 
			
		||||
        {
 | 
			
		||||
            var method = typeof(DbBindProvider).GetMethod("GetEntityListAsync", BindingFlags.Instance | BindingFlags.NonPublic);
 | 
			
		||||
            var method = typeof(DbBindProvider).GetMethod(nameof(GetEntityListAsync), BindingFlags.Instance | BindingFlags.NonPublic);
 | 
			
		||||
            var genericMethod = method.MakeGenericMethod(entityType);
 | 
			
		||||
            Task task = (Task)genericMethod.Invoke(this, new object[] { context, dataReader });
 | 
			
		||||
            return await GetTask<T>(task).ConfigureAwait(false);
 | 
			
		||||
 
 | 
			
		||||
@@ -34,175 +34,58 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// IsDBNull方法
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private static readonly MethodInfo isDBNullMethod = typeof(IDataRecord).GetMethod("IsDBNull", new Type[] { typeof(int) });
 | 
			
		||||
        private static readonly MethodInfo isDBNullMethod = typeof(IDataRecord).GetMethod(nameof(IDataRecord.IsDBNull), new Type[] { typeof(int) });
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// GetBoolean方法
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private static readonly MethodInfo getBoolean = typeof(IDataRecord).GetMethod("GetBoolean", new Type[] { typeof(int) });
 | 
			
		||||
        private static readonly MethodInfo getBoolean = typeof(IDataRecord).GetMethod(nameof(IDataRecord.GetBoolean), new Type[] { typeof(int) });
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// GetByte方法
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private static readonly MethodInfo getByte = typeof(IDataRecord).GetMethod("GetByte", new Type[] { typeof(int) });
 | 
			
		||||
        private static readonly MethodInfo getByte = typeof(IDataRecord).GetMethod(nameof(IDataRecord.GetByte), new Type[] { typeof(int) });
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// GetDateTime方法
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private static readonly MethodInfo getDateTime = typeof(IDataRecord).GetMethod("GetDateTime", new Type[] { typeof(int) });
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// GetDecimal方法
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private static readonly MethodInfo getDecimal = typeof(IDataRecord).GetMethod("GetDecimal", new Type[] { typeof(int) });
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// GetDouble方法
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private static readonly MethodInfo getDouble = typeof(IDataRecord).GetMethod("GetDouble", new Type[] { typeof(int) });
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// GetFloat方法
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private static readonly MethodInfo getFloat = typeof(IDataRecord).GetMethod("GetFloat", new Type[] { typeof(int) });
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// GetGuid方法
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private static readonly MethodInfo getGuid = typeof(IDataRecord).GetMethod("GetGuid", new Type[] { typeof(int) });
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// GetInt16方法
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private static readonly MethodInfo getInt16 = typeof(IDataRecord).GetMethod("GetInt16", new Type[] { typeof(int) });
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// GetInt32方法
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private static readonly MethodInfo getInt32 = typeof(IDataRecord).GetMethod("GetInt32", new Type[] { typeof(int) });
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// GetInt64方法
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private static readonly MethodInfo getInt64 = typeof(IDataRecord).GetMethod("GetInt64", new Type[] { typeof(int) });
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// GetString方法
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private static readonly MethodInfo getString = typeof(IDataRecord).GetMethod("GetString", new Type[] { typeof(int) });
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Getdatetimeoffset方法
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private static readonly MethodInfo getdatetimeoffset = typeof(IDataRecordExtensions).GetMethod("Getdatetimeoffset");
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// GetdatetimeoffsetDate方法
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private static readonly MethodInfo getdatetimeoffsetDate = typeof(IDataRecordExtensions).GetMethod("GetdatetimeoffsetDate");
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// GetStringGuid方法
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private static readonly MethodInfo getStringGuid = typeof(IDataRecordExtensions).GetMethod("GetStringGuid");
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// GetXelement方法
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private static readonly MethodInfo getXelement = typeof(IDataRecordExtensions).GetMethod("GetXelement");
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// GetConvertStringGuid方法
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private static readonly MethodInfo getConvertStringGuid = typeof(IDataRecordExtensions).GetMethod("GetConvertStringGuid");
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// GetEnum方法
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private static readonly MethodInfo getEnum = typeof(IDataRecordExtensions).GetMethod("GetEnum");
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// GetConvertString方法
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private static readonly MethodInfo getConvertString = typeof(IDataRecordExtensions).GetMethod("GetConvertString");
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// GetConvertFloat方法
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private static readonly MethodInfo getConvertFloat = typeof(IDataRecordExtensions).GetMethod("GetConvertFloat");
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// GetConvertBoolean方法
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private static readonly MethodInfo getConvertBoolean = typeof(IDataRecordExtensions).GetMethod("GetConvertBoolean");
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// GetConvertByte方法
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private static readonly MethodInfo getConvertByte = typeof(IDataRecordExtensions).GetMethod("GetConvertByte");
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// GetConvertChar方法
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private static readonly MethodInfo getConvertChar = typeof(IDataRecordExtensions).GetMethod("GetConvertChar");
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// GetConvertDateTime方法
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private static readonly MethodInfo getConvertDateTime = typeof(IDataRecordExtensions).GetMethod("GetConvertDateTime");
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// GetConvertTime方法
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private static readonly MethodInfo getConvertTime = typeof(IDataRecordExtensions).GetMethod("GetConvertTime");
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// GetTime方法
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private static readonly MethodInfo getTime = typeof(IDataRecordExtensions).GetMethod("GetTime");
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// GetConvertDecimal方法
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private static readonly MethodInfo getConvertDecimal = typeof(IDataRecordExtensions).GetMethod("GetConvertDecimal");
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// GetConvertDouble方法
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private static readonly MethodInfo getConvertDouble = typeof(IDataRecordExtensions).GetMethod("GetConvertDouble");
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// GetConvertDoubleToFloat方法
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private static readonly MethodInfo getConvertDoubleToFloat = typeof(IDataRecordExtensions).GetMethod("GetConvertDoubleToFloat");
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// GetConvertGuid方法
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private static readonly MethodInfo getConvertGuid = typeof(IDataRecordExtensions).GetMethod("GetConvertGuid");
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// GetConvertInt16方法
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private static readonly MethodInfo getConvertInt16 = typeof(IDataRecordExtensions).GetMethod("GetConvertInt16");
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// GetConvertInt32方法
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private static readonly MethodInfo getConvertInt32 = typeof(IDataRecordExtensions).GetMethod("GetConvertInt32");
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// GetConvetInt64方法
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private static readonly MethodInfo getConvertInt64 = typeof(IDataRecordExtensions).GetMethod("GetConvetInt64");
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// GetConvertEnum_Null方法
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private static readonly MethodInfo getConvertEnum_Null = typeof(IDataRecordExtensions).GetMethod("GetConvertEnum_Null");
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// GetConvertdatetimeoffset方法
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private static readonly MethodInfo getConvertdatetimeoffset = typeof(IDataRecordExtensions).GetMethod("GetConvertdatetimeoffset");
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// GetConvertdatetimeoffsetDate方法
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private static readonly MethodInfo getConvertdatetimeoffsetDate = typeof(IDataRecordExtensions).GetMethod("GetConvertdatetimeoffsetDate");
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// GetOtherNull方法
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private static readonly MethodInfo getOtherNull = typeof(IDataRecordExtensions).GetMethod("GetOtherNull");
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// GetOther方法
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private static readonly MethodInfo getOther = typeof(IDataRecordExtensions).GetMethod("GetOther");
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// GetJson方法
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private static readonly MethodInfo getJson = typeof(IDataRecordExtensions).GetMethod("GetJson");
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// GetArray方法
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private static readonly MethodInfo getArray = typeof(IDataRecordExtensions).GetMethod("GetArray");
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// GetEntity方法
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private static readonly MethodInfo getEntity = typeof(IDataRecordExtensions).GetMethod("GetEntity", new Type[] { typeof(SqlSugarProvider) });
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// GetMyIntNull方法
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private static readonly MethodInfo getMyIntNull = typeof(IDataRecordExtensions).GetMethod("GetMyIntNull");
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// GetMyInt方法
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private static readonly MethodInfo getMyInt = typeof(IDataRecordExtensions).GetMethod("GetMyInt");
 | 
			
		||||
        private static readonly MethodInfo getDateTime = typeof(IDataRecord).GetMethod(nameof(IDataRecord.GetDateTime), new Type[] { typeof(int) });
 | 
			
		||||
        private static readonly MethodInfo getDecimal = typeof(IDataRecord).GetMethod(nameof(IDataRecord.GetDecimal), new[] { typeof(int) });
 | 
			
		||||
        private static readonly MethodInfo getDouble = typeof(IDataRecord).GetMethod(nameof(IDataRecord.GetDouble), new[] { typeof(int) });
 | 
			
		||||
        private static readonly MethodInfo getFloat = typeof(IDataRecord).GetMethod(nameof(IDataRecord.GetFloat), new[] { typeof(int) });
 | 
			
		||||
        private static readonly MethodInfo getGuid = typeof(IDataRecord).GetMethod(nameof(IDataRecord.GetGuid), new[] { typeof(int) });
 | 
			
		||||
        private static readonly MethodInfo getInt16 = typeof(IDataRecord).GetMethod(nameof(IDataRecord.GetInt16), new[] { typeof(int) });
 | 
			
		||||
        private static readonly MethodInfo getInt32 = typeof(IDataRecord).GetMethod(nameof(IDataRecord.GetInt32), new[] { typeof(int) });
 | 
			
		||||
        private static readonly MethodInfo getInt64 = typeof(IDataRecord).GetMethod(nameof(IDataRecord.GetInt64), new[] { typeof(int) });
 | 
			
		||||
        private static readonly MethodInfo getString = typeof(IDataRecord).GetMethod(nameof(IDataRecord.GetString), new[] { typeof(int) });
 | 
			
		||||
        private static readonly MethodInfo getdatetimeoffset = typeof(IDataRecordExtensions).GetMethod(nameof(IDataRecordExtensions.GetDateTimeOffset));
 | 
			
		||||
        private static readonly MethodInfo getdatetimeoffsetDate = typeof(IDataRecordExtensions).GetMethod(nameof(IDataRecordExtensions.GetDateTimeOffsetDate));
 | 
			
		||||
        private static readonly MethodInfo getStringGuid = typeof(IDataRecordExtensions).GetMethod(nameof(IDataRecordExtensions.GetStringGuid));
 | 
			
		||||
        private static readonly MethodInfo getXelement = typeof(IDataRecordExtensions).GetMethod(nameof(IDataRecordExtensions.GetXelement));
 | 
			
		||||
        private static readonly MethodInfo getConvertStringGuid = typeof(IDataRecordExtensions).GetMethod(nameof(IDataRecordExtensions.GetConvertStringGuid));
 | 
			
		||||
        private static readonly MethodInfo getEnum = typeof(IDataRecordExtensions).GetMethod(nameof(IDataRecordExtensions.GetEnum));
 | 
			
		||||
        private static readonly MethodInfo getConvertString = typeof(IDataRecordExtensions).GetMethod(nameof(IDataRecordExtensions.GetConvertString));
 | 
			
		||||
        private static readonly MethodInfo getConvertFloat = typeof(IDataRecordExtensions).GetMethod(nameof(IDataRecordExtensions.GetConvertFloat));
 | 
			
		||||
        private static readonly MethodInfo getConvertBoolean = typeof(IDataRecordExtensions).GetMethod(nameof(IDataRecordExtensions.GetConvertBoolean));
 | 
			
		||||
        private static readonly MethodInfo getConvertByte = typeof(IDataRecordExtensions).GetMethod(nameof(IDataRecordExtensions.GetConvertByte));
 | 
			
		||||
        private static readonly MethodInfo getConvertChar = typeof(IDataRecordExtensions).GetMethod(nameof(IDataRecordExtensions.GetConvertChar));
 | 
			
		||||
        private static readonly MethodInfo getConvertDateTime = typeof(IDataRecordExtensions).GetMethod(nameof(IDataRecordExtensions.GetConvertDateTime));
 | 
			
		||||
        private static readonly MethodInfo getConvertTime = typeof(IDataRecordExtensions).GetMethod(nameof(IDataRecordExtensions.GetConvertTime));
 | 
			
		||||
        private static readonly MethodInfo getTime = typeof(IDataRecordExtensions).GetMethod(nameof(IDataRecordExtensions.GetTime));
 | 
			
		||||
        private static readonly MethodInfo getConvertDecimal = typeof(IDataRecordExtensions).GetMethod(nameof(IDataRecordExtensions.GetConvertDecimal));
 | 
			
		||||
        private static readonly MethodInfo getConvertDouble = typeof(IDataRecordExtensions).GetMethod(nameof(IDataRecordExtensions.GetConvertDouble));
 | 
			
		||||
        private static readonly MethodInfo getConvertDoubleToFloat = typeof(IDataRecordExtensions).GetMethod(nameof(IDataRecordExtensions.GetConvertDoubleToFloat));
 | 
			
		||||
        private static readonly MethodInfo getConvertGuid = typeof(IDataRecordExtensions).GetMethod(nameof(IDataRecordExtensions.GetConvertGuid));
 | 
			
		||||
        private static readonly MethodInfo getConvertInt16 = typeof(IDataRecordExtensions).GetMethod(nameof(IDataRecordExtensions.GetConvertInt16));
 | 
			
		||||
        private static readonly MethodInfo getConvertInt32 = typeof(IDataRecordExtensions).GetMethod(nameof(IDataRecordExtensions.GetConvertInt32));
 | 
			
		||||
        private static readonly MethodInfo getConvertInt64 = typeof(IDataRecordExtensions).GetMethod(nameof(IDataRecordExtensions.GetConvertInt64));
 | 
			
		||||
        private static readonly MethodInfo getConvertEnum_Null = typeof(IDataRecordExtensions).GetMethod(nameof(IDataRecordExtensions.GetConvertEnum_Null));
 | 
			
		||||
        private static readonly MethodInfo getConvertdatetimeoffset = typeof(IDataRecordExtensions).GetMethod(nameof(IDataRecordExtensions.GetConvertdatetimeoffset));
 | 
			
		||||
        private static readonly MethodInfo getConvertdatetimeoffsetDate = typeof(IDataRecordExtensions).GetMethod(nameof(IDataRecordExtensions.GetConvertdatetimeoffsetDate));
 | 
			
		||||
        private static readonly MethodInfo getOtherNull = typeof(IDataRecordExtensions).GetMethod(nameof(IDataRecordExtensions.GetOtherNull));
 | 
			
		||||
        private static readonly MethodInfo getOther = typeof(IDataRecordExtensions).GetMethod(nameof(IDataRecordExtensions.GetOther));
 | 
			
		||||
        private static readonly MethodInfo getJson = typeof(IDataRecordExtensions).GetMethod(nameof(IDataRecordExtensions.GetJson));
 | 
			
		||||
        private static readonly MethodInfo getArray = typeof(IDataRecordExtensions).GetMethod(nameof(IDataRecordExtensions.GetArray));
 | 
			
		||||
        private static readonly MethodInfo getEntity = typeof(IDataRecordExtensions).GetMethod(nameof(IDataRecordExtensions.GetEntity), new[] { typeof(SqlSugarProvider) });
 | 
			
		||||
        private static readonly MethodInfo getMyIntNull = typeof(IDataRecordExtensions).GetMethod(nameof(IDataRecordExtensions.GetMyIntNull));
 | 
			
		||||
        private static readonly MethodInfo getMyInt = typeof(IDataRecordExtensions).GetMethod(nameof(IDataRecordExtensions.GetMyInt));
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 加载委托
 | 
			
		||||
@@ -284,31 +167,32 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
                    }
 | 
			
		||||
                    if (!isGemo && columnInfo.PropertyInfo.PropertyType.IsClass() && columnInfo.PropertyInfo.PropertyType != UtilConstants.ByteArrayType && columnInfo.PropertyInfo.PropertyType != UtilConstants.ObjType)
 | 
			
		||||
                    {
 | 
			
		||||
                        if (this.ReaderKeys.Contains(fileName))
 | 
			
		||||
                        if (this.ReaderKeys.TryGetValue(fileName, out var v))
 | 
			
		||||
                        {
 | 
			
		||||
                            BindClass(generator, result, columnInfo, ReaderKeys.First(it => it.Equals(fileName, StringComparison.CurrentCultureIgnoreCase)));
 | 
			
		||||
                            BindClass(generator, result, columnInfo, v);
 | 
			
		||||
                        }
 | 
			
		||||
                        else if (this.ReaderKeys.Any(it => it.Equals(columnInfo.PropertyName, StringComparison.CurrentCultureIgnoreCase)))
 | 
			
		||||
                        else if (this.ReaderKeys.TryGetValue(columnInfo.PropertyName, out var v1))
 | 
			
		||||
                        {
 | 
			
		||||
                            BindClass(generator, result, columnInfo, ReaderKeys.First(it => it.Equals(columnInfo.PropertyName, StringComparison.CurrentCultureIgnoreCase)));
 | 
			
		||||
                            BindClass(generator, result, columnInfo, v1);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    else if (!isGemo && columnInfo.IsJson && columnInfo.PropertyInfo.PropertyType != UtilConstants.StringType)
 | 
			
		||||
                    {   //json is struct
 | 
			
		||||
                        if (this.ReaderKeys.Contains(fileName))
 | 
			
		||||
                        if (this.ReaderKeys.TryGetValue(fileName, out var v))
 | 
			
		||||
                        {
 | 
			
		||||
                            BindClass(generator, result, columnInfo, ReaderKeys.First(it => it.Equals(fileName, StringComparison.CurrentCultureIgnoreCase)));
 | 
			
		||||
                            BindClass(generator, result, columnInfo, v);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        if (this.ReaderKeys.Contains(fileName))
 | 
			
		||||
 | 
			
		||||
                        if (this.ReaderKeys.TryGetValue(fileName, out var v))
 | 
			
		||||
                        {
 | 
			
		||||
                            BindField(generator, result, columnInfo, ReaderKeys.First(it => it.Equals(fileName, StringComparison.CurrentCultureIgnoreCase)));
 | 
			
		||||
                            BindField(generator, result, columnInfo, v);
 | 
			
		||||
                        }
 | 
			
		||||
                        else if (this.ReaderKeys.Any(it => it.Equals(columnInfo.PropertyName, StringComparison.CurrentCultureIgnoreCase)))
 | 
			
		||||
                        else if (this.ReaderKeys.TryGetValue(columnInfo.PropertyName, out var v1))
 | 
			
		||||
                        {
 | 
			
		||||
                            BindField(generator, result, columnInfo, ReaderKeys.First(it => it.Equals(columnInfo.PropertyName, StringComparison.CurrentCultureIgnoreCase)));
 | 
			
		||||
                            BindField(generator, result, columnInfo, v1);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
@@ -338,7 +222,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
            generator.Emit(OpCodes.Callvirt, isDBNullMethod);
 | 
			
		||||
            generator.Emit(OpCodes.Brtrue, endIfLabel);
 | 
			
		||||
            generator.Emit(OpCodes.Ldloc, result);
 | 
			
		||||
            var method = (columnInfo.SqlParameterDbType as Type).GetMethod("QueryConverter");
 | 
			
		||||
            var method = (columnInfo.SqlParameterDbType as Type).GetMethod(nameof(ISugarDataConverter.QueryConverter));
 | 
			
		||||
            method = method.MakeGenericMethod(new Type[] { columnInfo.PropertyInfo.PropertyType });
 | 
			
		||||
            Type type = (columnInfo.SqlParameterDbType as Type);
 | 
			
		||||
            generator.Emit(OpCodes.Newobj, type.GetConstructor(Type.EmptyTypes));
 | 
			
		||||
@@ -386,7 +270,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
                    {
 | 
			
		||||
                        IDataRecordExtensions.DeserializeObjectFunc = insertBuilder.DeserializeObjectFunc;
 | 
			
		||||
                    }
 | 
			
		||||
                    jsonMethod = typeof(IDataRecordExtensions).GetMethod("GetDeserializeObject").MakeGenericMethod(columnInfo.PropertyInfo.PropertyType);
 | 
			
		||||
                    jsonMethod = typeof(IDataRecordExtensions).GetMethod(nameof(IDataRecordExtensions.GetDeserializeObject)).MakeGenericMethod(columnInfo.PropertyInfo.PropertyType);
 | 
			
		||||
                }
 | 
			
		||||
                generator.Emit(OpCodes.Call, jsonMethod);
 | 
			
		||||
                generator.Emit(OpCodes.Callvirt, columnInfo.PropertyInfo.GetSetMethod(true));
 | 
			
		||||
 
 | 
			
		||||
@@ -285,7 +285,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <param name="dr">数据记录器</param>
 | 
			
		||||
        /// <param name="i">字段索引</param>
 | 
			
		||||
        /// <returns>可空长整型</returns>
 | 
			
		||||
        public static long? GetConvetInt64(this IDataRecord dr, int i)
 | 
			
		||||
        public static long? GetConvertInt64(this IDataRecord dr, int i)
 | 
			
		||||
        {
 | 
			
		||||
            if (dr.IsDBNull(i))
 | 
			
		||||
            {
 | 
			
		||||
@@ -317,7 +317,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <param name="dr">数据记录器</param>
 | 
			
		||||
        /// <param name="i">字段索引</param>
 | 
			
		||||
        /// <returns>日期时间</returns>
 | 
			
		||||
        public static DateTime GetdatetimeoffsetDate(this IDataRecord dr, int i)
 | 
			
		||||
        public static DateTime GetDateTimeOffsetDate(this IDataRecord dr, int i)
 | 
			
		||||
        {
 | 
			
		||||
            if (dr.IsDBNull(i))
 | 
			
		||||
            {
 | 
			
		||||
@@ -351,7 +351,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <param name="dr">数据记录器</param>
 | 
			
		||||
        /// <param name="i">字段索引</param>
 | 
			
		||||
        /// <returns>DateTimeOffset</returns>
 | 
			
		||||
        public static DateTimeOffset Getdatetimeoffset(this IDataRecord dr, int i)
 | 
			
		||||
        public static DateTimeOffset GetDateTimeOffset(this IDataRecord dr, int i)
 | 
			
		||||
        {
 | 
			
		||||
            if (dr.IsDBNull(i))
 | 
			
		||||
            {
 | 
			
		||||
 
 | 
			
		||||
@@ -66,7 +66,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
            db.Aop.OnExecutingChangeSql = (sql, pars) =>
 | 
			
		||||
            {
 | 
			
		||||
                sql = getChangeSqlFunc(this.Context.CurrentConnectionConfig.DbType, sql);
 | 
			
		||||
                return new KeyValuePair<string, IReadOnlyList<SugarParameter>>(sql, pars);
 | 
			
		||||
                return new KeyValuePair<string, IReadOnlyCollection<SugarParameter>>(sql, pars);
 | 
			
		||||
            };
 | 
			
		||||
            var result = db.DbMaintenance.GetTableInfoList(false);
 | 
			
		||||
            return result;
 | 
			
		||||
@@ -100,7 +100,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
            db.Aop.OnExecutingChangeSql = (sql, pars) =>
 | 
			
		||||
            {
 | 
			
		||||
                sql = getChangeSqlFunc(this.Context.CurrentConnectionConfig.DbType, sql);
 | 
			
		||||
                return new KeyValuePair<string, IReadOnlyList<SugarParameter>>(sql, pars);
 | 
			
		||||
                return new KeyValuePair<string, IReadOnlyCollection<SugarParameter>>(sql, pars);
 | 
			
		||||
            };
 | 
			
		||||
            var result = db.DbMaintenance.GetColumnInfosByTableName(tableName, false);
 | 
			
		||||
            return result;
 | 
			
		||||
@@ -401,7 +401,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 添加复合主键
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public bool AddPrimaryKeys(string tableName, IReadOnlyList<string> columnNames)
 | 
			
		||||
        public bool AddPrimaryKeys(string tableName, IReadOnlyCollection<string> columnNames)
 | 
			
		||||
        {
 | 
			
		||||
            tableName = this.SqlBuilder.GetTranslationTableName(tableName);
 | 
			
		||||
            var columnName = string.Join(",", columnNames);
 | 
			
		||||
@@ -418,7 +418,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 添加复合主键(指定主键名)
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public bool AddPrimaryKeys(string tableName, IReadOnlyList<string> columnNames, string pkName)
 | 
			
		||||
        public bool AddPrimaryKeys(string tableName, IReadOnlyCollection<string> columnNames, string pkName)
 | 
			
		||||
        {
 | 
			
		||||
            tableName = this.SqlBuilder.GetTranslationTableName(tableName);
 | 
			
		||||
            var columnName = string.Join(",", columnNames);
 | 
			
		||||
@@ -469,7 +469,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
                        var sqlobj = this.Context.UpdateableT(dt)
 | 
			
		||||
                        .AS(tableName)
 | 
			
		||||
                        .Where($"{this.SqlBuilder.GetTranslationColumnName(columnInfo.DbColumnName)} is null ").ToSql();
 | 
			
		||||
                        sqlobj.Value[0].IsJson = true;
 | 
			
		||||
                        sqlobj.Value.First().IsJson = true;
 | 
			
		||||
                        this.Context.Ado.ExecuteCommand(sqlobj.Key, sqlobj.Value);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
@@ -480,7 +480,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
                        var sqlobj = this.Context.UpdateableT(dt)
 | 
			
		||||
                        .AS(tableName)
 | 
			
		||||
                        .Where($"{this.SqlBuilder.GetTranslationColumnName(columnInfo.DbColumnName)} is null ").ToSql();
 | 
			
		||||
                        sqlobj.Value[0].IsJson = true;
 | 
			
		||||
                        sqlobj.Value.First().IsJson = true;
 | 
			
		||||
                        this.Context.Ado.ExecuteCommand(sqlobj.Key, sqlobj.Value);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
@@ -838,7 +838,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 创建索引
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public virtual bool CreateIndex(string tableName, IReadOnlyList<string> columnNames, bool isUnique = false)
 | 
			
		||||
        public virtual bool CreateIndex(string tableName, IReadOnlyCollection<string> columnNames, bool isUnique = false)
 | 
			
		||||
        {
 | 
			
		||||
            string sql = string.Format(CreateIndexSql, this.SqlBuilder.GetTranslationTableName(tableName), string.Join(",", columnNames.Select(it => this.SqlBuilder.GetTranslationColumnName(it))), string.Join("_", columnNames) + this.Context.CurrentConnectionConfig.IndexSuffix, isUnique ? "UNIQUE" : "");
 | 
			
		||||
            sql = sql.Replace("_" + this.SqlBuilder.SqlTranslationLeft, "_");
 | 
			
		||||
@@ -851,7 +851,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 创建唯一索引
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public virtual bool CreateUniqueIndex(string tableName, IReadOnlyList<string> columnNames)
 | 
			
		||||
        public virtual bool CreateUniqueIndex(string tableName, IReadOnlyCollection<string> columnNames)
 | 
			
		||||
        {
 | 
			
		||||
            string sql = string.Format(CreateIndexSql, this.SqlBuilder.GetTranslationTableName(tableName), string.Join(",", columnNames.Select(it => this.SqlBuilder.GetTranslationColumnName(it))), string.Join("_", columnNames) + this.Context.CurrentConnectionConfig.IndexSuffix + "_Unique", "UNIQUE");
 | 
			
		||||
            sql = sql.Replace("_" + this.SqlBuilder.SqlTranslationLeft, "_");
 | 
			
		||||
@@ -864,7 +864,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 创建索引(指定索引名)
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public virtual bool CreateIndex(string tableName, IReadOnlyList<string> columnNames, string IndexName, bool isUnique = false)
 | 
			
		||||
        public virtual bool CreateIndex(string tableName, IReadOnlyCollection<string> columnNames, string IndexName, bool isUnique = false)
 | 
			
		||||
        {
 | 
			
		||||
            var include = "";
 | 
			
		||||
            if (IndexName.Contains("{include:", StringComparison.CurrentCultureIgnoreCase))
 | 
			
		||||
@@ -944,8 +944,8 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        public virtual void AddIndex(EntityInfo entityInfo)
 | 
			
		||||
        {
 | 
			
		||||
            var db = this.Context;
 | 
			
		||||
            var columns = entityInfo.Columns.Where(it => it.IsIgnore == false);
 | 
			
		||||
            var indexColumns = columns.Where(it => it.IndexGroupNameList.HasValue());
 | 
			
		||||
            var columns = entityInfo.Columns.Where(it => it.IsIgnore == false).ToArray();
 | 
			
		||||
            var indexColumns = columns.Where(it => it.IndexGroupNameList.HasValue()).ToArray();
 | 
			
		||||
            if (indexColumns.HasValue())
 | 
			
		||||
            {
 | 
			
		||||
                var groups = indexColumns.SelectMany(it => it.IndexGroupNameList).GroupBy(it => it).Select(it => it.Key);
 | 
			
		||||
@@ -960,7 +960,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var uIndexColumns = columns.Where(it => it.UIndexGroupNameList.HasValue());
 | 
			
		||||
            var uIndexColumns = columns.Where(it => it.UIndexGroupNameList.HasValue()).ToArray();
 | 
			
		||||
            if (uIndexColumns.HasValue())
 | 
			
		||||
            {
 | 
			
		||||
                var groups = uIndexColumns.SelectMany(it => it.UIndexGroupNameList).GroupBy(it => it).Select(it => it.Key);
 | 
			
		||||
 
 | 
			
		||||
@@ -28,7 +28,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        {
 | 
			
		||||
            if (Context == null) return 0;
 | 
			
		||||
            var inertable = MethodInfo.Invoke(Context, new object[] { objectValue });
 | 
			
		||||
            var result = inertable.GetType().GetMethod("ExecuteCommand").Invoke(inertable, Array.Empty<object>());
 | 
			
		||||
            var result = inertable.GetType().GetMethod(nameof(ExecuteCommand)).Invoke(inertable, Array.Empty<object>());
 | 
			
		||||
            return (int)result;
 | 
			
		||||
        }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
@@ -39,7 +39,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        {
 | 
			
		||||
            if (Context == null) return 0;
 | 
			
		||||
            var inertable = MethodInfo.Invoke(Context, new object[] { objectValue });
 | 
			
		||||
            var result = inertable.GetType().GetMyMethod("ExecuteCommandAsync", 0).Invoke(inertable, Array.Empty<object>());
 | 
			
		||||
            var result = inertable.GetType().GetMyMethod(nameof(ExecuteCommandAsync), 0).Invoke(inertable, Array.Empty<object>());
 | 
			
		||||
            return await ((Task<int>)result).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -51,7 +51,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        public CommonMethodInfo AS(string tableName)
 | 
			
		||||
        {
 | 
			
		||||
            var inertable = MethodInfo.Invoke(Context, new object[] { objectValue });
 | 
			
		||||
            var newMethod = inertable.GetType().GetMyMethod("AS", 1, typeof(string));
 | 
			
		||||
            var newMethod = inertable.GetType().GetMyMethod(nameof(QueryMethodInfo.AS), 1, typeof(string));
 | 
			
		||||
            var result = newMethod.Invoke(inertable, new object[] { tableName });
 | 
			
		||||
            return new CommonMethodInfo()
 | 
			
		||||
            {
 | 
			
		||||
@@ -70,7 +70,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
                return new CommonMethodInfo();
 | 
			
		||||
            }
 | 
			
		||||
            var inertable = MethodInfo.Invoke(Context, new object[] { objectValue });
 | 
			
		||||
            var newMethod = inertable.GetType().GetMyMethod("EnableDiffLogEvent", 1, typeof(object));
 | 
			
		||||
            var newMethod = inertable.GetType().GetMyMethod(nameof(EnableDiffLogEvent), 1, typeof(object));
 | 
			
		||||
            var result = newMethod.Invoke(inertable, new object[] { businessData });
 | 
			
		||||
            return new CommonMethodInfo()
 | 
			
		||||
            {
 | 
			
		||||
@@ -84,7 +84,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        public CommonMethodInfo SplitTable()
 | 
			
		||||
        {
 | 
			
		||||
            var inertable = MethodInfo.Invoke(Context, new object[] { objectValue });
 | 
			
		||||
            var newMethod = inertable.GetType().GetMyMethod("SplitTable", 0);
 | 
			
		||||
            var newMethod = inertable.GetType().GetMyMethod(nameof(SplitTable), 0);
 | 
			
		||||
            var result = newMethod.Invoke(inertable, Array.Empty<object>());
 | 
			
		||||
            return new CommonMethodInfo()
 | 
			
		||||
            {
 | 
			
		||||
 
 | 
			
		||||
@@ -63,7 +63,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        public async Task<bool> ExecuteCommandAsync()
 | 
			
		||||
        {
 | 
			
		||||
            if (Context == null) return false;
 | 
			
		||||
            var result = MethodInfos.GetType().GetMethod("ExecuteCommandAsync").Invoke(MethodInfos, Array.Empty<object>());
 | 
			
		||||
            var result = MethodInfos.GetType().GetMethod(nameof(ExecuteCommandAsync)).Invoke(MethodInfos, Array.Empty<object>());
 | 
			
		||||
            return await ((Task<bool>)result).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -74,7 +74,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        public bool ExecuteCommand()
 | 
			
		||||
        {
 | 
			
		||||
            if (Context == null) return false;
 | 
			
		||||
            var result = MethodInfos.GetType().GetMethod("ExecuteCommand").Invoke(MethodInfos, Array.Empty<object>());
 | 
			
		||||
            var result = MethodInfos.GetType().GetMethod(nameof(ExecuteCommand)).Invoke(MethodInfos, Array.Empty<object>());
 | 
			
		||||
            return (bool)result;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,7 @@
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 要删除的数据列表
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public IReadOnlyList<T> DataList { get; set; }
 | 
			
		||||
        public IReadOnlyCollection<T> DataList { get; set; }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// SqlSugar客户端实例
 | 
			
		||||
        /// </summary>
 | 
			
		||||
@@ -41,7 +41,7 @@
 | 
			
		||||
        /// <returns>受影响的行数</returns>
 | 
			
		||||
        public int ExecuteCommand()
 | 
			
		||||
        {
 | 
			
		||||
            if (DataList.Count == 1 && DataList[0] == null)
 | 
			
		||||
            if (DataList.Count == 1 && DataList.First() == null)
 | 
			
		||||
            {
 | 
			
		||||
                return 0;
 | 
			
		||||
            }
 | 
			
		||||
@@ -77,7 +77,7 @@
 | 
			
		||||
        /// <returns>受影响的行数</returns>
 | 
			
		||||
        public async Task<int> ExecuteCommandAsync()
 | 
			
		||||
        {
 | 
			
		||||
            if (DataList.Count == 1 && DataList[0] == null)
 | 
			
		||||
            if (DataList.Count == 1 && DataList.First() == null)
 | 
			
		||||
            {
 | 
			
		||||
                return 0;
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
@@ -55,7 +55,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 删除对象列表
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public IReadOnlyList<T> DeleteObjects { get; set; }
 | 
			
		||||
        public IReadOnlyCollection<T> DeleteObjects { get; set; }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 实体信息
 | 
			
		||||
        /// </summary>
 | 
			
		||||
@@ -82,7 +82,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        public int ExecuteCommand()
 | 
			
		||||
        {
 | 
			
		||||
            string sql;
 | 
			
		||||
            IReadOnlyList<SugarParameter> paramters;
 | 
			
		||||
            IReadOnlyCollection<SugarParameter> paramters;
 | 
			
		||||
            _ExecuteCommand(out sql, out paramters);
 | 
			
		||||
            var result = Db.ExecuteCommand(sql, paramters);
 | 
			
		||||
            After(sql);
 | 
			
		||||
@@ -112,7 +112,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        public async Task<int> ExecuteCommandAsync()
 | 
			
		||||
        {
 | 
			
		||||
            string sql;
 | 
			
		||||
            IReadOnlyList<SugarParameter> paramters;
 | 
			
		||||
            IReadOnlyCollection<SugarParameter> paramters;
 | 
			
		||||
            _ExecuteCommand(out sql, out paramters);
 | 
			
		||||
            var result = await Db.ExecuteCommandAsync(sql, paramters).ConfigureAwait(false);
 | 
			
		||||
            After(sql);
 | 
			
		||||
@@ -175,7 +175,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 根据对象列表设置删除条件
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public IDeleteable<T> Where(IReadOnlyList<T> deleteObjs)
 | 
			
		||||
        public IDeleteable<T> Where(IReadOnlyCollection<T> deleteObjs)
 | 
			
		||||
        {
 | 
			
		||||
            this.DeleteObjects = deleteObjs;
 | 
			
		||||
            if (deleteObjs == null || deleteObjs.Count == 0)
 | 
			
		||||
@@ -242,14 +242,15 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                StringBuilder whereInSql = new StringBuilder();
 | 
			
		||||
                for (int index = 0; index < deleteObjs.Count; index++)
 | 
			
		||||
                bool first = true;
 | 
			
		||||
                foreach (var deleteObj in deleteObjs)
 | 
			
		||||
                {
 | 
			
		||||
                    var deleteObj = deleteObjs[index];
 | 
			
		||||
                    StringBuilder orString = new StringBuilder();
 | 
			
		||||
                    if (index > 0)
 | 
			
		||||
                    if (!first)
 | 
			
		||||
                    {
 | 
			
		||||
                        orString.Append(DeleteBuilder.WhereInOrTemplate + UtilConstants.Space);
 | 
			
		||||
                    }
 | 
			
		||||
                    first = false;
 | 
			
		||||
                    int i = 0;
 | 
			
		||||
                    StringBuilder andString = new StringBuilder();
 | 
			
		||||
                    foreach (var primaryField in primaryFields)
 | 
			
		||||
@@ -421,7 +422,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 设置Where条件
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public IDeleteable<T> Where(string whereString, IReadOnlyList<SugarParameter> parameters)
 | 
			
		||||
        public IDeleteable<T> Where(string whereString, IReadOnlyCollection<SugarParameter> parameters)
 | 
			
		||||
        {
 | 
			
		||||
            DeleteBuilder.WhereInfos.Add(whereString);
 | 
			
		||||
            if (DeleteBuilder.Parameters == null)
 | 
			
		||||
@@ -642,7 +643,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// IN条件
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public IDeleteable<T> In<PkType>(IReadOnlyList<PkType> primaryKeyValues)
 | 
			
		||||
        public IDeleteable<T> In<PkType>(IReadOnlyCollection<PkType> primaryKeyValues)
 | 
			
		||||
        {
 | 
			
		||||
            if (primaryKeyValues == null || primaryKeyValues.Count == 0)
 | 
			
		||||
            {
 | 
			
		||||
@@ -702,7 +703,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// IN条件
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public IDeleteable<T> In<PkType>(Expression<Func<T, object>> inField, IReadOnlyList<PkType> primaryKeyValues)
 | 
			
		||||
        public IDeleteable<T> In<PkType>(Expression<Func<T, object>> inField, IReadOnlyCollection<PkType> primaryKeyValues)
 | 
			
		||||
        {
 | 
			
		||||
            var lamResult = DeleteBuilder.GetExpressionValue(inField, ResolveExpressType.FieldSingle);
 | 
			
		||||
            var fieldName = lamResult.GetResultString();
 | 
			
		||||
@@ -727,7 +728,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// IN条件
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public IDeleteable<T> In<PkType>(string inField, IReadOnlyList<PkType> primaryKeyValues)
 | 
			
		||||
        public IDeleteable<T> In<PkType>(string inField, IReadOnlyCollection<PkType> primaryKeyValues)
 | 
			
		||||
        {
 | 
			
		||||
            TempPrimaryKeys = new List<string>() { inField };
 | 
			
		||||
            var result = In(primaryKeyValues);
 | 
			
		||||
@@ -776,13 +777,13 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 获取SQL和参数
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public KeyValuePair<string, IReadOnlyList<SugarParameter>> ToSql()
 | 
			
		||||
        public KeyValuePair<string, IReadOnlyCollection<SugarParameter>> ToSql()
 | 
			
		||||
        {
 | 
			
		||||
            DeleteBuilder.EntityInfo = this.Context.EntityMaintenance.GetEntityInfo<T>();
 | 
			
		||||
            string sql = DeleteBuilder.ToSqlString();
 | 
			
		||||
            var paramters = DeleteBuilder.Parameters == null ? null : DeleteBuilder.Parameters;
 | 
			
		||||
            RestoreMapping();
 | 
			
		||||
            return new KeyValuePair<string, IReadOnlyList<SugarParameter>>(sql, paramters);
 | 
			
		||||
            return new KeyValuePair<string, IReadOnlyCollection<SugarParameter>>(sql, paramters);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
@@ -803,7 +804,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 执行删除命令
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private void _ExecuteCommand(out string sql, out IReadOnlyList<SugarParameter> paramters)
 | 
			
		||||
        private void _ExecuteCommand(out string sql, out IReadOnlyCollection<SugarParameter> paramters)
 | 
			
		||||
        {
 | 
			
		||||
            DeleteBuilder.EntityInfo = this.Context.EntityMaintenance.GetEntityInfo<T>();
 | 
			
		||||
            sql = DeleteBuilder.ToSqlString();
 | 
			
		||||
@@ -943,7 +944,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 数据变更AOP
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        protected virtual void DataChangesAop(IReadOnlyList<T> deleteObjs)
 | 
			
		||||
        protected virtual void DataChangesAop(IReadOnlyCollection<T> deleteObjs)
 | 
			
		||||
        {
 | 
			
		||||
            var dataEvent = this.Context.CurrentConnectionConfig.AopEvents?.DataChangesExecuted;
 | 
			
		||||
            if (dataEvent != null && deleteObjs != null)
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 待删除对象数组
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public IReadOnlyList<T> deleteObjects { get; set; }
 | 
			
		||||
        public IReadOnlyCollection<T> deleteObjects { get; set; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 执行删除命令
 | 
			
		||||
 
 | 
			
		||||
@@ -59,14 +59,14 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
            {
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    this.Context.Ado.BeginTran();
 | 
			
		||||
                    await this.Context.Ado.BeginTranAsync().ConfigureAwait(false);
 | 
			
		||||
                    var result = await _ExecuteCommandAsync().ConfigureAwait(false);
 | 
			
		||||
                    this.Context.Ado.CommitTran();
 | 
			
		||||
                    await this.Context.Ado.CommitTranAsync().ConfigureAwait(false);
 | 
			
		||||
                    return result;
 | 
			
		||||
                }
 | 
			
		||||
                catch (Exception)
 | 
			
		||||
                {
 | 
			
		||||
                    this.Context.Ado.RollbackTran();
 | 
			
		||||
                    await this.Context.Ado.RollbackTranAsync().ConfigureAwait(false);
 | 
			
		||||
                    throw;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@@ -115,7 +115,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <param name="keyValuePair">原始SQL键值对</param>
 | 
			
		||||
        /// <param name="asName">表别名</param>
 | 
			
		||||
        /// <returns>处理后的SQL键值对</returns>
 | 
			
		||||
        private KeyValuePair<string, List<SugarParameter>> GetSqlObj(KeyValuePair<string, IReadOnlyList<SugarParameter>> keyValuePair, string asName)
 | 
			
		||||
        private KeyValuePair<string, List<SugarParameter>> GetSqlObj(KeyValuePair<string, IReadOnlyCollection<SugarParameter>> keyValuePair, string asName)
 | 
			
		||||
        {
 | 
			
		||||
            List<SugarParameter> pars = new List<SugarParameter>();
 | 
			
		||||
            string sql = keyValuePair.Key;
 | 
			
		||||
 
 | 
			
		||||
@@ -17,7 +17,7 @@
 | 
			
		||||
        public int ExecuteReturnIdentity()
 | 
			
		||||
        {
 | 
			
		||||
            if (Context == null) return 0;
 | 
			
		||||
            var result = Context.GetType().GetMyMethod("ExecuteReturnIdentity", 0).Invoke(Context, Array.Empty<object>());
 | 
			
		||||
            var result = Context.GetType().GetMyMethod(nameof(ExecuteReturnIdentity), 0).Invoke(Context, Array.Empty<object>());
 | 
			
		||||
            return (int)result;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -28,7 +28,7 @@
 | 
			
		||||
        public async Task<int> ExecuteReturnIdentityAsync()
 | 
			
		||||
        {
 | 
			
		||||
            if (Context == null) return 0;
 | 
			
		||||
            var result = Context.GetType().GetMyMethod("ExecuteReturnIdentityAsync", 0).Invoke(Context, Array.Empty<object>());
 | 
			
		||||
            var result = Context.GetType().GetMyMethod(nameof(ExecuteReturnIdentityAsync), 0).Invoke(Context, Array.Empty<object>());
 | 
			
		||||
            return await ((Task<int>)result).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -39,7 +39,7 @@
 | 
			
		||||
        public int ExecuteCommand()
 | 
			
		||||
        {
 | 
			
		||||
            if (Context == null) return 0;
 | 
			
		||||
            var result = Context.GetType().GetMyMethod("ExecuteCommand", 0).Invoke(Context, Array.Empty<object>());
 | 
			
		||||
            var result = Context.GetType().GetMyMethod(nameof(ExecuteCommand), 0).Invoke(Context, Array.Empty<object>());
 | 
			
		||||
            return (int)result;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -50,7 +50,7 @@
 | 
			
		||||
        public async Task<int> ExecuteCommandAsync()
 | 
			
		||||
        {
 | 
			
		||||
            if (Context == null) return 0;
 | 
			
		||||
            var result = Context.GetType().GetMyMethod("ExecuteCommandAsync", 0).Invoke(Context, Array.Empty<object>());
 | 
			
		||||
            var result = Context.GetType().GetMyMethod(nameof(ExecuteCommandAsync), 0).Invoke(Context, Array.Empty<object>());
 | 
			
		||||
            return await ((Task<int>)result).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@@ -72,7 +72,7 @@
 | 
			
		||||
        public int ExecuteCommand()
 | 
			
		||||
        {
 | 
			
		||||
            if (Context == null) return 0;
 | 
			
		||||
            var result = Context.GetType().GetMyMethod("ExecuteCommand", 0).Invoke(Context, Array.Empty<object>());
 | 
			
		||||
            var result = Context.GetType().GetMyMethod(nameof(ExecuteCommand), 0).Invoke(Context, Array.Empty<object>());
 | 
			
		||||
            return (int)result;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -83,7 +83,7 @@
 | 
			
		||||
        public async Task<int> ExecuteCommandAsync()
 | 
			
		||||
        {
 | 
			
		||||
            if (Context == null) return 0;
 | 
			
		||||
            var result = Context.GetType().GetMyMethod("ExecuteCommandAsync", 0).Invoke(Context, Array.Empty<object>());
 | 
			
		||||
            var result = Context.GetType().GetMyMethod(nameof(ExecuteCommandAsync), 0).Invoke(Context, Array.Empty<object>());
 | 
			
		||||
            return await ((Task<int>)result).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@@ -105,7 +105,7 @@
 | 
			
		||||
        public int ExecuteCommand()
 | 
			
		||||
        {
 | 
			
		||||
            if (Context == null) return 0;
 | 
			
		||||
            var result = Context.GetType().GetMyMethod("ExecuteCommand", 0).Invoke(Context, Array.Empty<object>());
 | 
			
		||||
            var result = Context.GetType().GetMyMethod(nameof(ExecuteCommand), 0).Invoke(Context, Array.Empty<object>());
 | 
			
		||||
            return (int)result;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -129,7 +129,7 @@
 | 
			
		||||
        /// <returns>更新通用方法信息</returns>
 | 
			
		||||
        public UpdateCommonMethodInfo UpdateColumns(params string[] columns)
 | 
			
		||||
        {
 | 
			
		||||
            var result = Context.GetType().GetMyMethod("UpdateColumns", 1, typeof(string[])).Invoke(Context, new object[] { columns });
 | 
			
		||||
            var result = Context.GetType().GetMyMethod(nameof(UpdateColumns), 1, typeof(string[])).Invoke(Context, new object[] { columns });
 | 
			
		||||
            UpdateCommonMethodInfo updateCommonMethod = new UpdateCommonMethodInfo();
 | 
			
		||||
            updateCommonMethod.Context = result;
 | 
			
		||||
            return updateCommonMethod;
 | 
			
		||||
@@ -142,7 +142,7 @@
 | 
			
		||||
        public async Task<int> ExecuteCommandAsync()
 | 
			
		||||
        {
 | 
			
		||||
            if (Context == null) return 0;
 | 
			
		||||
            var result = Context.GetType().GetMyMethod("ExecuteCommandAsync", 0).Invoke(Context, Array.Empty<object>());
 | 
			
		||||
            var result = Context.GetType().GetMyMethod(nameof(ExecuteCommandAsync), 0).Invoke(Context, Array.Empty<object>());
 | 
			
		||||
            return await ((Task<int>)result).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -152,7 +152,7 @@
 | 
			
		||||
        /// <returns>更新通用方法信息</returns>
 | 
			
		||||
        public UpdateCommonMethodInfo SplitTable()
 | 
			
		||||
        {
 | 
			
		||||
            var newMethod = this.Context.GetType().GetMyMethod("SplitTable", 0);
 | 
			
		||||
            var newMethod = this.Context.GetType().GetMyMethod(nameof(SplitTable), 0);
 | 
			
		||||
            var result = newMethod.Invoke(Context, Array.Empty<object>());
 | 
			
		||||
            return new UpdateCommonMethodInfo()
 | 
			
		||||
            {
 | 
			
		||||
 
 | 
			
		||||
@@ -159,11 +159,11 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
            {
 | 
			
		||||
                Context = this._Context
 | 
			
		||||
            };
 | 
			
		||||
            if (method.Method.Name == "ToList")
 | 
			
		||||
            if (method.Method.Name == nameof(QueryMethodInfo.ToList))
 | 
			
		||||
            {
 | 
			
		||||
                // 不处理ToList方法
 | 
			
		||||
            }
 | 
			
		||||
            else if (method.Method.Name == "Where")
 | 
			
		||||
            else if (method.Method.Name == nameof(QueryMethodInfo.Where))
 | 
			
		||||
            {
 | 
			
		||||
                navigatManager.CheckHasRootShortName(method.Arguments[0], method.Arguments[1]);
 | 
			
		||||
                var exp = method.Arguments[1];
 | 
			
		||||
 
 | 
			
		||||
@@ -77,7 +77,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
            }
 | 
			
		||||
            if (NotAny(name))
 | 
			
		||||
            {
 | 
			
		||||
                DeleteMany(thisEntity, ids.ToList(), thisFkColumn.DbColumnName);
 | 
			
		||||
                DeleteMany(thisEntity, ids, thisFkColumn.DbColumnName);
 | 
			
		||||
                if (this._Options?.OneToManyEnableLogicDelete == true)
 | 
			
		||||
                {
 | 
			
		||||
                    var locgicColumn = thisEntity.Columns.FirstOrDefault(it => it.PropertyName.EqualCase("IsDeleted") || it.PropertyName.EqualCase("IsDelete"));
 | 
			
		||||
@@ -104,7 +104,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
                {
 | 
			
		||||
                    var list = this._Context.Queryable<TChild>()
 | 
			
		||||
                        .AS(thisEntity.DbTableName)
 | 
			
		||||
                        .In(thisFkColumn.DbColumnName, ids.ToList())
 | 
			
		||||
                        .In(thisFkColumn.DbColumnName, ids)
 | 
			
		||||
                        .ToList();
 | 
			
		||||
                    List<TChild> result = GetNoExistsId(list, children, thisPkColumn.PropertyName);
 | 
			
		||||
                    if (result.Count != 0)
 | 
			
		||||
@@ -173,7 +173,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
            }
 | 
			
		||||
            if (NotAny(name))
 | 
			
		||||
            {
 | 
			
		||||
                DeleteMany(thisEntity, ids.ToList(), thisFkColumn.DbColumnName);
 | 
			
		||||
                DeleteMany(thisEntity, ids, thisFkColumn.DbColumnName);
 | 
			
		||||
                if (this._Options?.OneToManyEnableLogicDelete == true)
 | 
			
		||||
                {
 | 
			
		||||
                    var locgicColumn = thisEntity.Columns.FirstOrDefault(it => it.PropertyName.EqualCase("IsDeleted") || it.PropertyName.EqualCase("IsDelete"));
 | 
			
		||||
@@ -203,13 +203,13 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
                        this._Context.Deleteable<object>()
 | 
			
		||||
                           .AS(thisEntity.DbTableName)
 | 
			
		||||
                           .EnableQueryFilter(thisEntity.Type)
 | 
			
		||||
                           .In(thisFkColumn.DbColumnName, ids.ToList()).ExecuteCommand();
 | 
			
		||||
                           .In(thisFkColumn.DbColumnName, ids).ExecuteCommand();
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        this._Context.Deleteable<object>()
 | 
			
		||||
                            .AS(thisEntity.DbTableName)
 | 
			
		||||
                            .In(thisFkColumn.DbColumnName, ids.ToList()).ExecuteCommand();
 | 
			
		||||
                            .In(thisFkColumn.DbColumnName, ids).ExecuteCommand();
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                _NavigateType = NavigateType.OneToMany;
 | 
			
		||||
@@ -261,7 +261,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <param name="thisEntity">当前实体信息</param>
 | 
			
		||||
        /// <param name="ids">ID列表</param>
 | 
			
		||||
        /// <param name="fkName">外键名称</param>
 | 
			
		||||
        private void DeleteMany(EntityInfo thisEntity, List<object> ids, string fkName)
 | 
			
		||||
        private void DeleteMany(EntityInfo thisEntity, IReadOnlyCollection<object> ids, string fkName)
 | 
			
		||||
        {
 | 
			
		||||
            if (_Options == null || _Options.OneToManyDeleteAll == false)
 | 
			
		||||
            {
 | 
			
		||||
 
 | 
			
		||||
@@ -113,7 +113,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
            }
 | 
			
		||||
            await Context.Utilities.PageEachAsync(datas, pageSize, async pageItems =>
 | 
			
		||||
            {
 | 
			
		||||
                var x = await Context.Storageable(pageItems).As(tableName).WhereColumns(whereColumns).ToStorageAsync().ConfigureAwait(false);
 | 
			
		||||
                var x = await Context.Storageable(pageItems).AS(tableName).WhereColumns(whereColumns).ToStorageAsync().ConfigureAwait(false);
 | 
			
		||||
                result += await x.BulkCopyAsync().ConfigureAwait(false);
 | 
			
		||||
                result += await x.BulkUpdateAsync(updateColumns).ConfigureAwait(false);
 | 
			
		||||
                return result;
 | 
			
		||||
 
 | 
			
		||||
@@ -72,7 +72,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                return await _BulkCopy(datas is IReadOnlyList<T> values ? values : datas.ToList()).ConfigureAwait(false);
 | 
			
		||||
                return await _BulkCopy(datas is IReadOnlyCollection<T> values ? values : datas.ToList()).ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        #endregion
 | 
			
		||||
@@ -129,7 +129,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                return await _BulkUpdate(datas is IReadOnlyList<T> values ? values : datas.ToList(), whereColumns, updateColumns).ConfigureAwait(false);
 | 
			
		||||
                return await _BulkUpdate(datas is IReadOnlyCollection<T> values ? values : datas.ToList(), whereColumns, updateColumns).ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -243,7 +243,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                return await _BulkMerge(datas is IReadOnlyList<T> values ? values : datas.ToList(), updateColumns, whereColumns).ConfigureAwait(false);
 | 
			
		||||
                return await _BulkMerge(datas is IReadOnlyCollection<T> values ? values : datas.ToList(), updateColumns, whereColumns).ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        /// <summary>批量合并实体列表</summary>
 | 
			
		||||
@@ -253,7 +253,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>执行批量合并操作</summary>
 | 
			
		||||
        private async Task<int> _BulkMerge(IReadOnlyList<T> datas, string[] updateColumns, string[] whereColumns)
 | 
			
		||||
        private async Task<int> _BulkMerge(IReadOnlyCollection<T> datas, string[] updateColumns, string[] whereColumns)
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
@@ -323,10 +323,10 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
            var value = this.context.DynamicBuilder().CreateObjectByType(type, dicList);
 | 
			
		||||
            newValue = UtilMethods.ConvertToObjectList(type, value);
 | 
			
		||||
            fastestMethod = this.context.GetType()
 | 
			
		||||
                                  .GetMethod("Fastest")
 | 
			
		||||
                                  .GetMethod(nameof(ISqlSugarClient.Fastest))
 | 
			
		||||
                                  .MakeGenericMethod(type)
 | 
			
		||||
                                  .Invoke(this.context, null);
 | 
			
		||||
            bulkCopyMethod = fastestMethod.GetType().GetMyMethod(isAsync ? "BulkMergeAsync" : "BulkMerge", 1);
 | 
			
		||||
            bulkCopyMethod = fastestMethod.GetType().GetMyMethod(isAsync ? nameof(BulkMergeAsync) : nameof(BulkMerge), 1);
 | 
			
		||||
        }
 | 
			
		||||
        /// <summary>准备批量合并操作</summary>
 | 
			
		||||
        private void _BulkMerge(DataTable dataTable, string[] whereColumns, string[] updateColumns, out object newValue, out object fastestMethod, out MethodInfo bulkCopyMethod, bool isAsync, bool isIdentity)
 | 
			
		||||
@@ -357,14 +357,14 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
            var value = this.context.DynamicBuilder().CreateObjectByType(type, dicList);
 | 
			
		||||
            newValue = UtilMethods.ConvertToObjectList(type, value);
 | 
			
		||||
            fastestMethod = this.context.GetType()
 | 
			
		||||
                                  .GetMethod("Fastest")
 | 
			
		||||
                                  .GetMethod(nameof(ISqlSugarClient.Fastest))
 | 
			
		||||
                                  .MakeGenericMethod(type)
 | 
			
		||||
                                  .Invoke(this.context, null);
 | 
			
		||||
            bulkCopyMethod = fastestMethod.GetType().GetMyMethod(isAsync ? "BulkMergeAsync" : "BulkMerge", 3, newValue.GetType(), typeof(string[]), typeof(string[]));
 | 
			
		||||
            bulkCopyMethod = fastestMethod.GetType().GetMyMethod(isAsync ? nameof(BulkMergeAsync) : nameof(BulkMerge), 3, newValue.GetType(), typeof(string[]), typeof(string[]));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>执行批量更新操作</summary>
 | 
			
		||||
        private async Task<int> _BulkUpdate(IReadOnlyList<T> datas, string[] whereColumns, string[] updateColumns)
 | 
			
		||||
        private async Task<int> _BulkUpdate(IReadOnlyCollection<T> datas, string[] whereColumns, string[] updateColumns)
 | 
			
		||||
        {
 | 
			
		||||
            var isAuto = this.context.CurrentConnectionConfig.IsAutoCloseConnection;
 | 
			
		||||
            var isAutoOk = false;
 | 
			
		||||
@@ -486,7 +486,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
            return result;
 | 
			
		||||
        }
 | 
			
		||||
        /// <summary>执行批量插入操作</summary>
 | 
			
		||||
        private async Task<int> _BulkCopy(IReadOnlyList<T> datas)
 | 
			
		||||
        private async Task<int> _BulkCopy(IReadOnlyCollection<T> datas)
 | 
			
		||||
        {
 | 
			
		||||
            Begin(datas, true);
 | 
			
		||||
            DataTable dt = ToDdateTable(datas);
 | 
			
		||||
@@ -519,7 +519,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
            var title = isAdd ? "BulkCopy" : "BulkUpdate";
 | 
			
		||||
            if (isMerge)
 | 
			
		||||
            {
 | 
			
		||||
                title = "BulkMerge";
 | 
			
		||||
                title = nameof(BulkMerge);
 | 
			
		||||
            }
 | 
			
		||||
            this.context.Ado.IsEnableLogEvent = isLog;
 | 
			
		||||
            if (this.context.CurrentConnectionConfig?.AopEvents?.OnLogExecuted != null)
 | 
			
		||||
@@ -534,7 +534,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
            var title = isAdd ? "BulkCopy" : "BulkUpdate";
 | 
			
		||||
            if (isMerge)
 | 
			
		||||
            {
 | 
			
		||||
                title = "BulkMerge";
 | 
			
		||||
                title = nameof(BulkMerge);
 | 
			
		||||
            }
 | 
			
		||||
            isLog = this.context.Ado.IsEnableLogEvent;
 | 
			
		||||
            this.context.Ado.IsEnableLogEvent = false;
 | 
			
		||||
 
 | 
			
		||||
@@ -111,10 +111,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
                    if (column.SqlParameterDbType != null && column.SqlParameterDbType is Type && UtilMethods.HasInterface((Type)column.SqlParameterDbType, typeof(ISugarDataConverter)))
 | 
			
		||||
                    {
 | 
			
		||||
                        var columnInfo = column;
 | 
			
		||||
                        var type = columnInfo.SqlParameterDbType as Type;
 | 
			
		||||
                        var ParameterConverter = type.GetMethod("ParameterConverter").MakeGenericMethod(columnInfo.PropertyInfo.PropertyType);
 | 
			
		||||
                        var obj = Activator.CreateInstance(type);
 | 
			
		||||
                        var p = ParameterConverter.Invoke(obj, new object[] { value, 100 }) as SugarParameter;
 | 
			
		||||
                        var p = UtilMethods.GetParameterConverter(0, value, columnInfo);
 | 
			
		||||
                        value = p.Value;
 | 
			
		||||
                    }
 | 
			
		||||
                    else if (isMySql && column.UnderType == UtilConstants.BoolType)
 | 
			
		||||
 
 | 
			
		||||
@@ -32,7 +32,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
            if (Context == null) return 0;
 | 
			
		||||
            var inertable = MethodInfo.Invoke(Context, new object[] { objectValue });
 | 
			
		||||
            inertable = GetPageInsertable(inertable);
 | 
			
		||||
            var result = inertable.GetType().GetMethod("ExecuteCommand").Invoke(inertable, Array.Empty<object>());
 | 
			
		||||
            var result = inertable.GetType().GetMethod(nameof(ExecuteCommand)).Invoke(inertable, Array.Empty<object>());
 | 
			
		||||
            return (int)result;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -53,7 +53,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
            if (Context == null) return 0;
 | 
			
		||||
            var inertable = MethodInfo.Invoke(Context, new object[] { objectValue });
 | 
			
		||||
            inertable = GetPageInsertable(inertable);
 | 
			
		||||
            var result = inertable.GetType().GetMyMethod("ExecuteCommandAsync", 0).Invoke(inertable, Array.Empty<object>());
 | 
			
		||||
            var result = inertable.GetType().GetMyMethod(nameof(ExecuteCommandAsync), 0).Invoke(inertable, Array.Empty<object>());
 | 
			
		||||
            return await ((Task<int>)result).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -64,14 +64,14 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        {
 | 
			
		||||
            if (Context == null) return 0;
 | 
			
		||||
            var inertable = MethodInfo.Invoke(Context, new object[] { objectValue });
 | 
			
		||||
            var result = inertable.GetType().GetMethod("ExecuteReturnIdentity").Invoke(inertable, Array.Empty<object>());
 | 
			
		||||
            var result = inertable.GetType().GetMethod(nameof(ExecuteReturnIdentity)).Invoke(inertable, Array.Empty<object>());
 | 
			
		||||
            return (int)result;
 | 
			
		||||
        }
 | 
			
		||||
        public long ExecuteReturnBigIdentity()
 | 
			
		||||
        {
 | 
			
		||||
            if (Context == null) return 0;
 | 
			
		||||
            var inertable = MethodInfo.Invoke(Context, new object[] { objectValue });
 | 
			
		||||
            var result = inertable.GetType().GetMethod("ExecuteReturnBigIdentity").Invoke(inertable, Array.Empty<object>());
 | 
			
		||||
            var result = inertable.GetType().GetMethod(nameof(ExecuteReturnBigIdentity)).Invoke(inertable, Array.Empty<object>());
 | 
			
		||||
            return (long)result;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -82,14 +82,14 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        {
 | 
			
		||||
            if (Context == null) return Task.FromResult(0);
 | 
			
		||||
            var inertable = MethodInfo.Invoke(Context, new object[] { objectValue });
 | 
			
		||||
            var result = inertable.GetType().GetMyMethod("ExecuteReturnIdentityAsync", 0).Invoke(inertable, Array.Empty<object>());
 | 
			
		||||
            var result = inertable.GetType().GetMyMethod(nameof(ExecuteReturnIdentityAsync), 0).Invoke(inertable, Array.Empty<object>());
 | 
			
		||||
            return Task.FromResult((int)result);
 | 
			
		||||
        }
 | 
			
		||||
        public Task<long> ExecuteReturnBigIdentityAsync()
 | 
			
		||||
        {
 | 
			
		||||
            if (Context == null) return Task.FromResult((long)0);
 | 
			
		||||
            var inertable = MethodInfo.Invoke(Context, new object[] { objectValue });
 | 
			
		||||
            var result = inertable.GetType().GetMyMethod("ExecuteReturnBigIdentityAsync", 0).Invoke(inertable, Array.Empty<object>());
 | 
			
		||||
            var result = inertable.GetType().GetMyMethod(nameof(ExecuteReturnBigIdentityAsync), 0).Invoke(inertable, Array.Empty<object>());
 | 
			
		||||
            return Task.FromResult((long)result);
 | 
			
		||||
        }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
@@ -98,7 +98,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        public CommonMethodInfo AS(string tableName)
 | 
			
		||||
        {
 | 
			
		||||
            var inertable = MethodInfo.Invoke(Context, new object[] { objectValue });
 | 
			
		||||
            var newMethod = inertable.GetType().GetMyMethod("AS", 1, typeof(string));
 | 
			
		||||
            var newMethod = inertable.GetType().GetMyMethod(nameof(QueryMethodInfo.AS), 1, typeof(string));
 | 
			
		||||
            var result = newMethod.Invoke(inertable, new object[] { tableName });
 | 
			
		||||
            return new CommonMethodInfo()
 | 
			
		||||
            {
 | 
			
		||||
@@ -112,7 +112,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        public CommonMethodInfo EnableDiffLogEvent(object businessData = null)
 | 
			
		||||
        {
 | 
			
		||||
            var inertable = MethodInfo.Invoke(Context, new object[] { objectValue });
 | 
			
		||||
            var newMethod = inertable.GetType().GetMyMethod("EnableDiffLogEvent", 1, typeof(object));
 | 
			
		||||
            var newMethod = inertable.GetType().GetMyMethod(nameof(EnableDiffLogEvent), 1, typeof(object));
 | 
			
		||||
            var result = newMethod.Invoke(inertable, new object[] { businessData });
 | 
			
		||||
            return new CommonMethodInfo()
 | 
			
		||||
            {
 | 
			
		||||
@@ -126,7 +126,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        public CommonMethodInfo IgnoreColumns(params string[] ignoreColumns)
 | 
			
		||||
        {
 | 
			
		||||
            var inertable = MethodInfo.Invoke(Context, new object[] { objectValue });
 | 
			
		||||
            var newMethod = inertable.GetType().GetMyMethod("IgnoreColumns", 1, typeof(string[]));
 | 
			
		||||
            var newMethod = inertable.GetType().GetMyMethod(nameof(IgnoreColumns), 1, typeof(string[]));
 | 
			
		||||
            var result = newMethod.Invoke(inertable, new object[] { ignoreColumns });
 | 
			
		||||
            return new CommonMethodInfo()
 | 
			
		||||
            {
 | 
			
		||||
@@ -140,7 +140,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        public CommonMethodInfo IgnoreColumns(bool ignoreNullColumn)
 | 
			
		||||
        {
 | 
			
		||||
            var inertable = MethodInfo.Invoke(Context, new object[] { objectValue });
 | 
			
		||||
            var newMethod = inertable.GetType().GetMyMethod("IgnoreColumns", 2, typeof(bool), typeof(bool));
 | 
			
		||||
            var newMethod = inertable.GetType().GetMyMethod(nameof(IgnoreColumns), 2, typeof(bool), typeof(bool));
 | 
			
		||||
            var result = newMethod.Invoke(inertable, new object[] { ignoreNullColumn, true });
 | 
			
		||||
            return new CommonMethodInfo()
 | 
			
		||||
            {
 | 
			
		||||
@@ -154,7 +154,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        public SplitMethodInfo SplitTable()
 | 
			
		||||
        {
 | 
			
		||||
            var inertable = MethodInfo.Invoke(Context, new object[] { objectValue });
 | 
			
		||||
            var newMethod = inertable.GetType().GetMyMethod("SplitTable", 0);
 | 
			
		||||
            var newMethod = inertable.GetType().GetMyMethod(nameof(SplitTable), 0);
 | 
			
		||||
            var result = newMethod.Invoke(inertable, Array.Empty<object>());
 | 
			
		||||
            return new SplitMethodInfo()
 | 
			
		||||
            {
 | 
			
		||||
@@ -169,7 +169,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        {
 | 
			
		||||
            if (Context == null) return 0;
 | 
			
		||||
            var inertable = MethodInfo.Invoke(Context, new object[] { objectValue });
 | 
			
		||||
            var result = inertable.GetType().GetMethod("ExecuteReturnSnowflakeId").Invoke(inertable, Array.Empty<object>());
 | 
			
		||||
            var result = inertable.GetType().GetMethod(nameof(ExecuteReturnSnowflakeId)).Invoke(inertable, Array.Empty<object>());
 | 
			
		||||
            return (long)result;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -180,7 +180,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        {
 | 
			
		||||
            if (Context == null) return 0;
 | 
			
		||||
            var inertable = MethodInfo.Invoke(Context, new object[] { objectValue });
 | 
			
		||||
            var result = inertable.GetType().GetMyMethod("ExecuteReturnSnowflakeIdAsync", 0).Invoke(inertable, Array.Empty<object>());
 | 
			
		||||
            var result = inertable.GetType().GetMyMethod(nameof(ExecuteReturnSnowflakeIdAsync), 0).Invoke(inertable, Array.Empty<object>());
 | 
			
		||||
            return await ((Task<long>)result).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -56,7 +56,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        public async Task<bool> ExecuteCommandAsync()
 | 
			
		||||
        {
 | 
			
		||||
            if (Context == null) return false;
 | 
			
		||||
            var result = MethodInfos.GetType().GetMethod("ExecuteCommandAsync").Invoke(MethodInfos, Array.Empty<object>());
 | 
			
		||||
            var result = MethodInfos.GetType().GetMethod(nameof(ExecuteCommandAsync)).Invoke(MethodInfos, Array.Empty<object>());
 | 
			
		||||
            return await ((Task<bool>)result).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -66,7 +66,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        public bool ExecuteCommand()
 | 
			
		||||
        {
 | 
			
		||||
            if (Context == null) return false;
 | 
			
		||||
            var result = MethodInfos.GetType().GetMethod("ExecuteCommand").Invoke(MethodInfos, Array.Empty<object>());
 | 
			
		||||
            var result = MethodInfos.GetType().GetMethod(nameof(ExecuteCommand)).Invoke(MethodInfos, Array.Empty<object>());
 | 
			
		||||
            return (bool)result;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -62,8 +62,8 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
                        {
 | 
			
		||||
                            item.Value = Guid.NewGuid();
 | 
			
		||||
                        }
 | 
			
		||||
                        if (InsertObjs[0].GetType().GetProperties().Any(it => it.Name == item.PropertyName))
 | 
			
		||||
                            InsertObjs[0].GetType().GetProperties().First(it => it.Name == item.PropertyName).SetValue(InsertObjs[0], item.Value, null);
 | 
			
		||||
                        if (InsertObjs.First().GetType().GetProperties().Any(it => it.Name == item.PropertyName))
 | 
			
		||||
                            InsertObjs.First().GetType().GetProperties().First(it => it.Name == item.PropertyName).SetValue(InsertObjs.First(), item.Value, null);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@@ -245,7 +245,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 数据变更AOP处理
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private void DataChangeAop(IReadOnlyList<T> items)
 | 
			
		||||
        private void DataChangeAop(IReadOnlyCollection<T> items)
 | 
			
		||||
        {
 | 
			
		||||
            var dataEvent = this.Context.CurrentConnectionConfig.AopEvents?.DataChangesExecuted;
 | 
			
		||||
            if (dataEvent != null)
 | 
			
		||||
@@ -625,7 +625,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
                foreach (var item in this.EntityInfo.Columns.Where(it => it.IsIgnore == false && GetPrimaryKeys().Any(pk => pk.Equals(it.DbColumnName, StringComparison.CurrentCultureIgnoreCase))))
 | 
			
		||||
                {
 | 
			
		||||
                    var fielddName = item.DbColumnName;
 | 
			
		||||
                    var fieldObject = this.EntityInfo.Columns.FirstOrDefault(it => it.PropertyName == item.PropertyName).PropertyInfo.GetValue(this.InsertObjs[^1], null);
 | 
			
		||||
                    var fieldObject = this.EntityInfo.Columns.FirstOrDefault(it => it.PropertyName == item.PropertyName).PropertyInfo.GetValue(this.InsertObjs.Last(), null);
 | 
			
		||||
                    var fieldValue = fieldObject.ObjToString();
 | 
			
		||||
                    if (fieldObject != null && fieldObject.GetType() != typeof(string) && this.Context.CurrentConnectionConfig.DbType == DbType.PostgreSQL)
 | 
			
		||||
                    {
 | 
			
		||||
@@ -674,7 +674,7 @@ namespace ThingsGateway.SqlSugar
 | 
			
		||||
                {
 | 
			
		||||
                    ColumnDescription = it.ColumnDescription,
 | 
			
		||||
                    ColumnName = it.DbColumnName,
 | 
			
		||||
                    Value = it.PropertyInfo.GetValue(this.InsertObjs[^1], null),
 | 
			
		||||
                    Value = it.PropertyInfo.GetValue(this.InsertObjs.Last(), null),
 | 
			
		||||
                    IsPrimaryKey = it.IsPrimarykey
 | 
			
		||||
                }).ToList();
 | 
			
		||||
                return new List<DiffLogTableInfo>() { diffTable };
 | 
			
		||||
 
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user