From da2f7073f9fd07f1f2a8c4c21d9aac8ef224b325 Mon Sep 17 00:00:00 2001 From: chenchun Date: Fri, 29 Nov 2024 15:25:16 +0800 Subject: [PATCH 1/3] =?UTF-8?q?style:=20=E4=BC=98=E5=8C=96abp-cli=E6=8F=90?= =?UTF-8?q?=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Yi.Abp.Net8/tool/Yi.Abp.Tool/Commands/CloneCommand.cs | 1 + Yi.Abp.Net8/tool/Yi.Abp.Tool/Commands/NewCommand.cs | 8 ++++++++ Yi.Abp.Net8/tool/Yi.Abp.Tool/Yi.Abp.Tool.csproj | 2 +- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/Yi.Abp.Net8/tool/Yi.Abp.Tool/Commands/CloneCommand.cs b/Yi.Abp.Net8/tool/Yi.Abp.Tool/Commands/CloneCommand.cs index ab3e20d8..00802bc9 100644 --- a/Yi.Abp.Net8/tool/Yi.Abp.Tool/Commands/CloneCommand.cs +++ b/Yi.Abp.Net8/tool/Yi.Abp.Tool/Commands/CloneCommand.cs @@ -20,6 +20,7 @@ namespace Yi.Abp.Tool.Commands { application.OnExecute(() => { + Console.WriteLine("正在克隆,请耐心等待"); StartCmd($"git clone {CloneAddress}"); return 0; }); diff --git a/Yi.Abp.Net8/tool/Yi.Abp.Tool/Commands/NewCommand.cs b/Yi.Abp.Net8/tool/Yi.Abp.Tool/Commands/NewCommand.cs index 68b5327b..95a7cc76 100644 --- a/Yi.Abp.Net8/tool/Yi.Abp.Tool/Commands/NewCommand.cs +++ b/Yi.Abp.Net8/tool/Yi.Abp.Tool/Commands/NewCommand.cs @@ -36,6 +36,9 @@ namespace Yi.Abp.Tool.Commands var soureOption = application.Option("-s|--soure", "模板来源,gitee模板库分支名称: 默认值`default`", CommandOptionType.SingleValue); + var dbmsOption = application.Option("-dbms|--dataBaseMs", "数据库类型,支持目前主流数据库", + CommandOptionType.SingleValue); + var moduleNameArgument = application.Argument("moduleName", "模块名", (_) => { }); //子命令,new list @@ -58,6 +61,11 @@ namespace Yi.Abp.Tool.Commands application.OnExecute(() => { + if (dbmsOption.HasValue()) + { + Console.WriteLine($"检测到使用数据库类型-{dbmsOption.Value()},请在生成后,只需在配置文件中,更改DbConnOptions:Url及DbType即可,支持目前主流数据库20+"); + } + var path = string.Empty; if (pathOption.HasValue()) { diff --git a/Yi.Abp.Net8/tool/Yi.Abp.Tool/Yi.Abp.Tool.csproj b/Yi.Abp.Net8/tool/Yi.Abp.Tool/Yi.Abp.Tool.csproj index 7c00e995..5f5300b6 100644 --- a/Yi.Abp.Net8/tool/Yi.Abp.Tool/Yi.Abp.Tool.csproj +++ b/Yi.Abp.Net8/tool/Yi.Abp.Tool/Yi.Abp.Tool.csproj @@ -5,7 +5,7 @@ net8.0 enable enable - 2.0.4 + 2.0.5 橙子老哥 yi-framework框架配套工具 https://ccnetcore.com From 1090907178b156fcc40a0d2e933a619c9333ed98 Mon Sep 17 00:00:00 2001 From: chenchun Date: Fri, 29 Nov 2024 18:01:54 +0800 Subject: [PATCH 2/3] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=E5=8A=A8?= =?UTF-8?q?=E6=80=81api=E5=90=AF=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SwaggerAddExtensions.cs | 131 +++++++++--------- .../Services/AccountService.cs | 4 +- .../Dtos/UserRoleMenuDto.cs | 4 +- .../Managers/AccountManager.cs | 4 +- Yi.Abp.Net8/src/Yi.Abp.Web/YiAbpWebModule.cs | 47 ++++--- 5 files changed, 99 insertions(+), 91 deletions(-) diff --git a/Yi.Abp.Net8/framework/Yi.Framework.AspNetCore/Microsoft/Extensions/DependencyInjection/SwaggerAddExtensions.cs b/Yi.Abp.Net8/framework/Yi.Framework.AspNetCore/Microsoft/Extensions/DependencyInjection/SwaggerAddExtensions.cs index 0476e169..7f446586 100644 --- a/Yi.Abp.Net8/framework/Yi.Framework.AspNetCore/Microsoft/Extensions/DependencyInjection/SwaggerAddExtensions.cs +++ b/Yi.Abp.Net8/framework/Yi.Framework.AspNetCore/Microsoft/Extensions/DependencyInjection/SwaggerAddExtensions.cs @@ -9,84 +9,89 @@ using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Models; using Swashbuckle.AspNetCore.SwaggerGen; using Volo.Abp.AspNetCore.Mvc; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Options; namespace Yi.Framework.AspNetCore.Microsoft.Extensions.DependencyInjection { public static class SwaggerAddExtensions { - public static IServiceCollection AddYiSwaggerGen(this IServiceCollection services, Action? action=null) + public static IServiceCollection AddYiSwaggerGen(this IServiceCollection services, + Action? action = null) { - - var serviceProvider = services.BuildServiceProvider(); - var mvcOptions = serviceProvider.GetRequiredService>(); - - var mvcSettings = mvcOptions.Value.ConventionalControllers.ConventionalControllerSettings.DistinctBy(x => x.RemoteServiceName); + var mvcOptions = services.GetPreConfigureActions().Configure(); + + var mvcSettings = + mvcOptions.ConventionalControllers.ConventionalControllerSettings.DistinctBy(x => x.RemoteServiceName); services.AddAbpSwaggerGen( - options => - { - if (action is not null) + options => { - action.Invoke(options); - } - - // 配置分组,还需要去重,支持重写,如果外部传入后,将以外部为准 - foreach (var setting in mvcSettings.OrderBy(x => x.RemoteServiceName)) - { - if (!options.SwaggerGeneratorOptions.SwaggerDocs.ContainsKey(setting.RemoteServiceName)) + if (action is not null) { - options.SwaggerDoc(setting.RemoteServiceName, new OpenApiInfo { Title = setting.RemoteServiceName, Version = "v1" }); + action.Invoke(options); } - } - // 根据分组名称过滤 API 文档 - options.DocInclusionPredicate((docName, apiDesc) => - { - if (apiDesc.ActionDescriptor is ControllerActionDescriptor controllerActionDescriptor) + // 配置分组,还需要去重,支持重写,如果外部传入后,将以外部为准 + foreach (var setting in mvcSettings.OrderBy(x => x.RemoteServiceName)) { - var settingOrNull = mvcSettings.Where(x => x.Assembly == controllerActionDescriptor.ControllerTypeInfo.Assembly).FirstOrDefault(); - if (settingOrNull is not null) + if (!options.SwaggerGeneratorOptions.SwaggerDocs.ContainsKey(setting.RemoteServiceName)) { - return docName == settingOrNull.RemoteServiceName; + options.SwaggerDoc(setting.RemoteServiceName, + new OpenApiInfo { Title = setting.RemoteServiceName, Version = "v1" }); } } - return false; - }); - options.CustomSchemaIds(type => type.FullName); - var basePath = Path.GetDirectoryName(typeof(Program).Assembly.Location); - if (basePath is not null) - { - foreach (var item in Directory.GetFiles(basePath, "*.xml")) + // 根据分组名称过滤 API 文档 + options.DocInclusionPredicate((docName, apiDesc) => { - options.IncludeXmlComments(item, true); + if (apiDesc.ActionDescriptor is ControllerActionDescriptor controllerActionDescriptor) + { + var settingOrNull = mvcSettings + .Where(x => x.Assembly == controllerActionDescriptor.ControllerTypeInfo.Assembly) + .FirstOrDefault(); + if (settingOrNull is not null) + { + return docName == settingOrNull.RemoteServiceName; + } + } + + return false; + }); + + options.CustomSchemaIds(type => type.FullName); + var basePath = Path.GetDirectoryName(typeof(Program).Assembly.Location); + if (basePath is not null) + { + foreach (var item in Directory.GetFiles(basePath, "*.xml")) + { + options.IncludeXmlComments(item, true); + } } + + options.AddSecurityDefinition("JwtBearer", new OpenApiSecurityScheme() + { + Description = "直接输入Token即可", + Name = "Authorization", + In = ParameterLocation.Header, + Type = SecuritySchemeType.Http, + Scheme = "bearer" + }); + var scheme = new OpenApiSecurityScheme() + { + Reference = new OpenApiReference() { Type = ReferenceType.SecurityScheme, Id = "JwtBearer" } + }; + options.AddSecurityRequirement(new OpenApiSecurityRequirement() + { + [scheme] = new string[0] + }); + + options.OperationFilter(); + options.SchemaFilter(); } + ); - options.AddSecurityDefinition("JwtBearer", new OpenApiSecurityScheme() - { - Description = "直接输入Token即可", - Name = "Authorization", - In = ParameterLocation.Header, - Type = SecuritySchemeType.Http, - Scheme = "bearer" - }); - var scheme = new OpenApiSecurityScheme() - { - Reference = new OpenApiReference() { Type = ReferenceType.SecurityScheme, Id = "JwtBearer" } - }; - options.AddSecurityRequirement(new OpenApiSecurityRequirement() - { - [scheme] = new string[0] - }); - - options.OperationFilter(); - options.SchemaFilter(); - } - ); - - return services; } @@ -103,7 +108,6 @@ namespace Yi.Framework.AspNetCore.Microsoft.Extensions.DependencyInjection /// /// /// - public void Apply(OpenApiSchema model, SchemaFilterContext context) { if (context.Type.IsEnum) @@ -112,7 +116,7 @@ namespace Yi.Framework.AspNetCore.Microsoft.Extensions.DependencyInjection model.Type = "string"; model.Format = null; - + StringBuilder stringBuilder = new StringBuilder(); Enum.GetNames(context.Type) .ToList() @@ -121,9 +125,10 @@ namespace Yi.Framework.AspNetCore.Microsoft.Extensions.DependencyInjection Enum e = (Enum)Enum.Parse(context.Type, name); var descrptionOrNull = GetEnumDescription(e); model.Enum.Add(new OpenApiString(name)); - stringBuilder.Append($"【枚举:{name}{(descrptionOrNull is null ? string.Empty : $"({descrptionOrNull})")}={Convert.ToInt64(Enum.Parse(context.Type, name))}】
"); + stringBuilder.Append( + $"【枚举:{name}{(descrptionOrNull is null ? string.Empty : $"({descrptionOrNull})")}={Convert.ToInt64(Enum.Parse(context.Type, name))}】
"); }); - model.Description= stringBuilder.ToString(); + model.Description = stringBuilder.ToString(); } } @@ -133,13 +138,13 @@ namespace Yi.Framework.AspNetCore.Microsoft.Extensions.DependencyInjection var attributes = (DescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false); return attributes.Length > 0 ? attributes[0].Description : null; } - } public class AddRequiredHeaderParameter : IOperationFilter { public static string HeaderKey { get; set; } = "__tenant"; + public void Apply(OpenApiOperation operation, OperationFilterContext context) { if (operation.Parameters == null) @@ -150,8 +155,8 @@ namespace Yi.Framework.AspNetCore.Microsoft.Extensions.DependencyInjection In = ParameterLocation.Header, Required = false, AllowEmptyValue = true, - Description="租户id或者租户名称(可空为默认租户)" + Description = "租户id或者租户名称(可空为默认租户)" }); } } -} +} \ No newline at end of file diff --git a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application/Services/AccountService.cs b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application/Services/AccountService.cs index 388cf078..4fb3b4a3 100644 --- a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application/Services/AccountService.cs +++ b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application/Services/AccountService.cs @@ -355,13 +355,13 @@ namespace Yi.Framework.Rbac.Application.Services { //将后端菜单转换成前端路由,组件级别需要过滤 output = - ObjectMapper.Map, List>(menus).Vue3RuoYiRouterBuild(); + ObjectMapper.Map, List>(menus.Where(x=>x.MenuSource==MenuSourceEnum.Ruoyi).ToList()).Vue3RuoYiRouterBuild(); } else if (routerType == "pure") { //将后端菜单转换成前端路由,组件级别需要过滤 output = - ObjectMapper.Map, List>(menus).Vue3PureRouterBuild(); + ObjectMapper.Map, List>(menus.Where(x=>x.MenuSource==MenuSourceEnum.Pure).ToList()).Vue3PureRouterBuild(); } return output; diff --git a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain.Shared/Dtos/UserRoleMenuDto.cs b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain.Shared/Dtos/UserRoleMenuDto.cs index 199b98e9..e647bab5 100644 --- a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain.Shared/Dtos/UserRoleMenuDto.cs +++ b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain.Shared/Dtos/UserRoleMenuDto.cs @@ -9,8 +9,8 @@ namespace Yi.Framework.Rbac.Domain.Shared.Dtos public HashSet Roles { get; set; } = new(); public HashSet Menus { get; set; } = new(); - public List RoleCodes { get; set; } = new(); - public List PermissionCodes { get; set; } = new(); + public HashSet RoleCodes { get; set; } = new(); + public HashSet PermissionCodes { get; set; } = new(); } public class UserDto diff --git a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Managers/AccountManager.cs b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Managers/AccountManager.cs index 7051f71c..746222f0 100644 --- a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Managers/AccountManager.cs +++ b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Managers/AccountManager.cs @@ -217,8 +217,8 @@ namespace Yi.Framework.Rbac.Domain.Managers } else { - dto.PermissionCodes?.ForEach(per => AddToClaim(claims, TokenTypeConst.Permission, per)); - dto.RoleCodes?.ForEach(role => AddToClaim(claims, AbpClaimTypes.Role, role)); + dto.PermissionCodes?.ToList()?.ForEach(per => AddToClaim(claims, TokenTypeConst.Permission, per)); + dto.RoleCodes?.ToList()?.ForEach(role => AddToClaim(claims, AbpClaimTypes.Role, role)); } return claims; diff --git a/Yi.Abp.Net8/src/Yi.Abp.Web/YiAbpWebModule.cs b/Yi.Abp.Net8/src/Yi.Abp.Web/YiAbpWebModule.cs index 50211fa2..bcf35ec9 100644 --- a/Yi.Abp.Net8/src/Yi.Abp.Web/YiAbpWebModule.cs +++ b/Yi.Abp.Net8/src/Yi.Abp.Web/YiAbpWebModule.cs @@ -66,6 +66,30 @@ namespace Yi.Abp.Web { private const string DefaultCorsPolicyName = "Default"; + public override void PreConfigureServices(ServiceConfigurationContext context) + { + //动态Api-改进在pre中配置,启动更快 + PreConfigure(options => + { + options.ConventionalControllers.Create(typeof(YiAbpApplicationModule).Assembly, + options => options.RemoteServiceName = "default"); + options.ConventionalControllers.Create(typeof(YiFrameworkRbacApplicationModule).Assembly, + options => options.RemoteServiceName = "rbac"); + options.ConventionalControllers.Create(typeof(YiFrameworkBbsApplicationModule).Assembly, + options => options.RemoteServiceName = "bbs"); + options.ConventionalControllers.Create(typeof(YiFrameworkChatHubApplicationModule).Assembly, + options => options.RemoteServiceName = "chat-hub"); + options.ConventionalControllers.Create( + typeof(YiFrameworkTenantManagementApplicationModule).Assembly, + options => options.RemoteServiceName = "tenant-management"); + options.ConventionalControllers.Create(typeof(YiFrameworkCodeGenApplicationModule).Assembly, + options => options.RemoteServiceName = "code-gen"); + + //统一前缀 + options.ConventionalControllers.ConventionalControllerSettings.ForEach(x => x.RootPath = "api/app"); + }); + } + public override Task ConfigureServicesAsync(ServiceConfigurationContext context) { var configuration = context.Services.GetConfiguration(); @@ -91,28 +115,7 @@ namespace Yi.Abp.Web //配置错误处理显示详情 Configure(options => { options.SendExceptionsDetailsToClients = true; }); - - //动态Api - Configure(options => - { - options.ConventionalControllers.Create(typeof(YiAbpApplicationModule).Assembly, - options => options.RemoteServiceName = "default"); - options.ConventionalControllers.Create(typeof(YiFrameworkRbacApplicationModule).Assembly, - options => options.RemoteServiceName = "rbac"); - options.ConventionalControllers.Create(typeof(YiFrameworkBbsApplicationModule).Assembly, - options => options.RemoteServiceName = "bbs"); - options.ConventionalControllers.Create(typeof(YiFrameworkChatHubApplicationModule).Assembly, - options => options.RemoteServiceName = "chat-hub"); - options.ConventionalControllers.Create( - typeof(YiFrameworkTenantManagementApplicationModule).Assembly, - options => options.RemoteServiceName = "tenant-management"); - options.ConventionalControllers.Create(typeof(YiFrameworkCodeGenApplicationModule).Assembly, - options => options.RemoteServiceName = "code-gen"); - - //统一前缀 - options.ConventionalControllers.ConventionalControllerSettings.ForEach(x => x.RootPath = "api/app"); - }); - + //【NewtonsoftJson严重问题!!!!!逆天】设置api格式,留给后人铭记 // service.AddControllers().AddNewtonsoftJson(options => // { From 356938d6d393cd2b6b704bbf85ec92378b70e537 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A9=99=E5=AD=90?= <454313500@qq.com> Date: Sat, 30 Nov 2024 23:45:19 +0800 Subject: [PATCH 3/3] =?UTF-8?q?pref:=20=E4=BC=98=E5=8C=96db=E5=B7=A5?= =?UTF-8?q?=E4=BD=9C=E5=8D=95=E5=85=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../UnitOfWorkSqlsugarDbContextProvider.cs | 20 ++++++++----------- .../Services/TestService.cs | 6 ++++-- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/Yi.Abp.Net8/framework/Yi.Framework.SqlSugarCore/Uow/UnitOfWorkSqlsugarDbContextProvider.cs b/Yi.Abp.Net8/framework/Yi.Framework.SqlSugarCore/Uow/UnitOfWorkSqlsugarDbContextProvider.cs index d67b24ee..34a48521 100644 --- a/Yi.Abp.Net8/framework/Yi.Framework.SqlSugarCore/Uow/UnitOfWorkSqlsugarDbContextProvider.cs +++ b/Yi.Abp.Net8/framework/Yi.Framework.SqlSugarCore/Uow/UnitOfWorkSqlsugarDbContextProvider.cs @@ -35,8 +35,7 @@ namespace Yi.Framework.SqlSugarCore.Uow CurrentTenant = currentTenant; Logger = NullLogger>.Instance; } - - //private static object _databaseApiLock = new object(); + public virtual async Task GetDbContextAsync() { @@ -48,19 +47,16 @@ namespace Yi.Framework.SqlSugarCore.Uow var unitOfWork = UnitOfWorkManager.Current; - if (unitOfWork == null /*|| unitOfWork.Options.IsTransactional == false*/) + if (unitOfWork == null ) { - var dbContext = (TDbContext)ServiceProvider.GetRequiredService(); - //提高体验,取消工作单元强制性 - //throw new AbpException("A DbContext can only be created inside a unit of work!"); + //var dbContext = (TDbContext)ServiceProvider.GetRequiredService(); //如果不启用工作单元,创建一个新的db,不开启事务即可 - return dbContext; + //return dbContext; + + //2024-11-30,改回强制性使用工作单元,否则容易造成歧义 + throw new AbpException("DbContext 只能在工作单元内工作,当前DbContext没有工作单元,如需创建新线程并发操作,请手动创建工作单元"); + } - - - - - //尝试当前工作单元获取db var databaseApi = unitOfWork.FindDatabaseApi(dbContextKey); diff --git a/Yi.Abp.Net8/src/Yi.Abp.Application/Services/TestService.cs b/Yi.Abp.Net8/src/Yi.Abp.Application/Services/TestService.cs index cde02589..6c563991 100644 --- a/Yi.Abp.Net8/src/Yi.Abp.Application/Services/TestService.cs +++ b/Yi.Abp.Net8/src/Yi.Abp.Application/Services/TestService.cs @@ -67,7 +67,8 @@ namespace Yi.Abp.Application.Services public async Task GetUowAsync() { //魔改 - // 用户体验优先,万金油模式,支持高并发。支持单、多线程并发安全,支持多线程工作单元,支持多线程无工作单元,支持。。。 + // 用户体验优先,万金油模式,支持高并发。支持单、多线程并发安全,支持多线程工作单元,支持。。。 + // 不支持多线程无工作单元,应由工作单元统一管理(来自abp工作单元设计) // 请注意,如果requiresNew: true只有在没有工作单元内使用,嵌套子工作单元,默认值false即可 // 自动在各个情况处理db客户端最优解之一 int i = 3; @@ -78,7 +79,8 @@ namespace Yi.Abp.Application.Services { tasks.Add(Task.Run(async () => { - await sqlSugarRepository.InsertAsync(new BannerAggregateRoot { Name = "插入2" }); + //以下操作是错误的,不允许在新线程中,直接操作db,所有db操作应放在工作单元内,应由工作单元统一管理-来自abp工作单元设计 + //await sqlSugarRepository.InsertAsync(new BannerAggregateRoot { Name = "插入2" }); using (var uow = UnitOfWorkManager.Begin(requiresNew: true, isTransactional: true)) { await sqlSugarRepository.InsertAsync(new BannerAggregateRoot { Name = "插入1" });