diff --git a/Admin.NET/Admin.NET.Core/Attribute/IdempotentAttribute.cs b/Admin.NET/Admin.NET.Core/Attribute/IdempotentAttribute.cs
index 1c8cfe9c..59ea9463 100644
--- a/Admin.NET/Admin.NET.Core/Attribute/IdempotentAttribute.cs
+++ b/Admin.NET/Admin.NET.Core/Attribute/IdempotentAttribute.cs
@@ -14,99 +14,41 @@ namespace Admin.NET.Core;
///
[SuppressSniffer]
[AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = true)]
-public class IdempotentAttribute : Attribute, IAsyncActionFilter
+public class IdempotentAttribute(int intervalTime = 5, bool throwBah = true, string message = "您的操作过于频繁,请稍后再试!") : Attribute, IAsyncActionFilter
{
- ///
- /// 请求间隔时间/秒
- ///
- public int IntervalTime { get; set; } = 5;
-
- ///
- /// 错误提示内容
- ///
- public string Message { get; set; } = "你操作频率过快,请稍后重试!";
-
- ///
- /// 缓存前缀: Key+请求路由+用户Id+请求参数
- ///
- public string CacheKey { get; set; } = CacheConst.KeyIdempotent;
-
- ///
- /// 是否直接抛出异常:Ture是,False返回上次请求结果
- ///
- public bool ThrowBah { get; set; }
-
- ///
- /// 锁前缀
- ///
- public string LockPrefix { get; set; } = "lock_";
-
- public IdempotentAttribute()
- {
- }
+ private static readonly Lazy SysCacheService = new(() => App.GetService());
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
var httpContext = context.HttpContext;
- var path = httpContext.Request.Path.Value.ToString();
- var userId = httpContext.User?.FindFirstValue(ClaimConst.UserId);
- var cacheExpireTime = TimeSpan.FromSeconds(IntervalTime);
-
+ var path = httpContext.Request.Path.Value;
+ var userId = httpContext.User.FindFirstValue(ClaimConst.UserId);
var parameters = JsonConvert.SerializeObject(context.ActionArguments, Formatting.None, new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Include,
DefaultValueHandling = DefaultValueHandling.Include
});
- var cacheKey = CacheKey + MD5Encryption.Encrypt($"{path}{userId}{parameters}");
- var sysCacheService = httpContext.RequestServices.GetService();
- try
+ // 分布式锁
+ var md5Key = MD5Encryption.Encrypt($"{path}{userId}{parameters}");
+ using var distributedLock = SysCacheService.Value.BeginCacheLock(CacheConst.KeyIdempotent + md5Key);
+ if (distributedLock == null)
{
- // 分布式锁
- using var distributedLock = sysCacheService.BeginCacheLock($"{LockPrefix}{cacheKey}") ?? throw Oops.Oh(Message);
-
- var cacheValue = sysCacheService.Get(cacheKey);
- if (cacheValue != null)
- {
- if (ThrowBah) throw Oops.Oh(Message);
- context.Result = new ObjectResult(cacheValue.Value);
- return;
- }
- else
- {
- var resultContext = await next();
- // 缓存请求结果 null 值不缓存
- if (resultContext.Result is ObjectResult { Value: { } } objectResult)
- {
- var typeName = objectResult.Value.GetType().Name;
- var responseData = new ResponseData
- {
- Type = typeName,
- Value = objectResult.Value
- };
- sysCacheService.Set(cacheKey, responseData, cacheExpireTime);
- }
- }
+ if (throwBah) throw Oops.Oh(message);
+ return;
}
- catch (Exception ex)
+
+ // 判断是否存在重复请求
+ var cacheKey = CacheConst.KeyIdempotent + "cache:" + md5Key;
+ var isExist = SysCacheService.Value.ExistKey(cacheKey);
+ if (isExist)
{
- throw Oops.Oh($"{Message}-{ex}");
+ if (throwBah) throw Oops.Oh(message);
+ return;
}
- }
- ///
- /// 请求结果数据
- ///
- private class ResponseData
- {
- ///
- /// 结果类型
- ///
- public string Type { get; set; }
-
- ///
- /// 请求结果
- ///
- public dynamic Value { get; set; }
+ // 标记请求
+ SysCacheService.Value.Set(cacheKey, 1, TimeSpan.FromSeconds(intervalTime));
+ await next();
}
}
\ No newline at end of file
diff --git a/Admin.NET/Admin.NET.Core/CodeGen/CodeGenStrategyFactory.cs b/Admin.NET/Admin.NET.Core/CodeGen/CodeGenStrategyFactory.cs
index 65ed8fb7..ace47a07 100644
--- a/Admin.NET/Admin.NET.Core/CodeGen/CodeGenStrategyFactory.cs
+++ b/Admin.NET/Admin.NET.Core/CodeGen/CodeGenStrategyFactory.cs
@@ -4,7 +4,7 @@
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
-namespace Admin.NET.Core.CodeGen;
+namespace Admin.NET.Core;
///
/// 代码生成策略工厂
diff --git a/Admin.NET/Admin.NET.Core/CodeGen/Engines/CustomTemplateEngine.cs b/Admin.NET/Admin.NET.Core/CodeGen/Engines/CustomTemplateEngine.cs
index 48db5539..d651dd5e 100644
--- a/Admin.NET/Admin.NET.Core/CodeGen/Engines/CustomTemplateEngine.cs
+++ b/Admin.NET/Admin.NET.Core/CodeGen/Engines/CustomTemplateEngine.cs
@@ -4,7 +4,7 @@
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
-namespace Admin.NET.Core.CodeGen;
+namespace Admin.NET.Core;
///
/// 自定义模板引擎
diff --git a/Admin.NET/Admin.NET.Core/CodeGen/Engines/TableEntityEngine.cs b/Admin.NET/Admin.NET.Core/CodeGen/Engines/TableEntityEngine.cs
index 49f3aad3..d9beb81b 100644
--- a/Admin.NET/Admin.NET.Core/CodeGen/Engines/TableEntityEngine.cs
+++ b/Admin.NET/Admin.NET.Core/CodeGen/Engines/TableEntityEngine.cs
@@ -4,7 +4,7 @@
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
-namespace Admin.NET.Core.CodeGen;
+namespace Admin.NET.Core;
public class TableEntityEngine : ViewEngineModel
{
diff --git a/Admin.NET/Admin.NET.Core/CodeGen/Engines/TableSeedDataEngine.cs b/Admin.NET/Admin.NET.Core/CodeGen/Engines/TableSeedDataEngine.cs
index 9bb8b43d..14c60d3b 100644
--- a/Admin.NET/Admin.NET.Core/CodeGen/Engines/TableSeedDataEngine.cs
+++ b/Admin.NET/Admin.NET.Core/CodeGen/Engines/TableSeedDataEngine.cs
@@ -4,7 +4,7 @@
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
-namespace Admin.NET.Core.CodeGen;
+namespace Admin.NET.Core;
public class TableSeedDataEngine : ViewEngineModel
{
diff --git a/Admin.NET/Admin.NET.Core/CodeGen/Models/CodeGenColumnConfig.cs b/Admin.NET/Admin.NET.Core/CodeGen/Models/CodeGenColumnConfig.cs
index 23e23016..e7d94253 100644
--- a/Admin.NET/Admin.NET.Core/CodeGen/Models/CodeGenColumnConfig.cs
+++ b/Admin.NET/Admin.NET.Core/CodeGen/Models/CodeGenColumnConfig.cs
@@ -4,7 +4,7 @@
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
-namespace Admin.NET.Core.CodeGen;
+namespace Admin.NET.Core;
///
/// 代码生成详细配置参数
diff --git a/Admin.NET/Admin.NET.Core/CodeGen/Models/TemplateContextOutput.cs b/Admin.NET/Admin.NET.Core/CodeGen/Models/TemplateContextOutput.cs
index 2f5dd52a..1ec9e74f 100644
--- a/Admin.NET/Admin.NET.Core/CodeGen/Models/TemplateContextOutput.cs
+++ b/Admin.NET/Admin.NET.Core/CodeGen/Models/TemplateContextOutput.cs
@@ -4,7 +4,7 @@
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
-namespace Admin.NET.Core.CodeGen;
+namespace Admin.NET.Core;
///
/// 模板输出上下文
diff --git a/Admin.NET/Admin.NET.Core/CodeGen/Strategies/Base/CodeGenEntityStrategyBase.cs b/Admin.NET/Admin.NET.Core/CodeGen/Strategies/Base/CodeGenEntityStrategyBase.cs
index 6859fd81..80f11bfe 100644
--- a/Admin.NET/Admin.NET.Core/CodeGen/Strategies/Base/CodeGenEntityStrategyBase.cs
+++ b/Admin.NET/Admin.NET.Core/CodeGen/Strategies/Base/CodeGenEntityStrategyBase.cs
@@ -4,7 +4,7 @@
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
-namespace Admin.NET.Core.CodeGen;
+namespace Admin.NET.Core;
///
/// 种子数据策略基类(处理TableSeedDataEngine类型)
diff --git a/Admin.NET/Admin.NET.Core/CodeGen/Strategies/Base/CodeGenStrategy.cs b/Admin.NET/Admin.NET.Core/CodeGen/Strategies/Base/CodeGenStrategy.cs
index fc159d04..9b13efda 100644
--- a/Admin.NET/Admin.NET.Core/CodeGen/Strategies/Base/CodeGenStrategy.cs
+++ b/Admin.NET/Admin.NET.Core/CodeGen/Strategies/Base/CodeGenStrategy.cs
@@ -4,7 +4,7 @@
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
-namespace Admin.NET.Core.CodeGen;
+namespace Admin.NET.Core;
///
/// 基础策略接口
diff --git a/Admin.NET/Admin.NET.Core/CodeGen/Strategies/Base/CodeGenTableStrategyBase.cs b/Admin.NET/Admin.NET.Core/CodeGen/Strategies/Base/CodeGenTableStrategyBase.cs
index 699e2a67..c5465124 100644
--- a/Admin.NET/Admin.NET.Core/CodeGen/Strategies/Base/CodeGenTableStrategyBase.cs
+++ b/Admin.NET/Admin.NET.Core/CodeGen/Strategies/Base/CodeGenTableStrategyBase.cs
@@ -4,7 +4,7 @@
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
-namespace Admin.NET.Core.CodeGen;
+namespace Admin.NET.Core;
///
/// 表策略基类(处理SysCodeGen类型)
diff --git a/Admin.NET/Admin.NET.Core/CodeGen/Strategies/Entity/TableEntityCodeGenStrategy.cs b/Admin.NET/Admin.NET.Core/CodeGen/Strategies/Entity/TableEntityCodeGenStrategy.cs
index 9eb7fd79..6894e7de 100644
--- a/Admin.NET/Admin.NET.Core/CodeGen/Strategies/Entity/TableEntityCodeGenStrategy.cs
+++ b/Admin.NET/Admin.NET.Core/CodeGen/Strategies/Entity/TableEntityCodeGenStrategy.cs
@@ -4,7 +4,7 @@
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
-namespace Admin.NET.Core.CodeGen;
+namespace Admin.NET.Core;
///
/// 表实体代码生成策略类
diff --git a/Admin.NET/Admin.NET.Core/CodeGen/Strategies/Entity/TableSeedDataCodeGenStrategy.cs b/Admin.NET/Admin.NET.Core/CodeGen/Strategies/Entity/TableSeedDataCodeGenStrategy.cs
index 776f91f7..dba38ccc 100644
--- a/Admin.NET/Admin.NET.Core/CodeGen/Strategies/Entity/TableSeedDataCodeGenStrategy.cs
+++ b/Admin.NET/Admin.NET.Core/CodeGen/Strategies/Entity/TableSeedDataCodeGenStrategy.cs
@@ -4,7 +4,7 @@
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
-namespace Admin.NET.Core.CodeGen;
+namespace Admin.NET.Core;
///
/// 表种子数据代码生成策略类
diff --git a/Admin.NET/Admin.NET.Core/CodeGen/Strategies/MasterSlaveTablesCodeGenStrategy.cs b/Admin.NET/Admin.NET.Core/CodeGen/Strategies/MasterSlaveTablesCodeGenStrategy.cs
index b4462957..c71dd5d0 100644
--- a/Admin.NET/Admin.NET.Core/CodeGen/Strategies/MasterSlaveTablesCodeGenStrategy.cs
+++ b/Admin.NET/Admin.NET.Core/CodeGen/Strategies/MasterSlaveTablesCodeGenStrategy.cs
@@ -4,7 +4,7 @@
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
-namespace Admin.NET.Core.CodeGen;
+namespace Admin.NET.Core;
///
/// 主从表代码生成策略类
diff --git a/Admin.NET/Admin.NET.Core/CodeGen/Strategies/SingleTableCodeGenStrategy.cs b/Admin.NET/Admin.NET.Core/CodeGen/Strategies/SingleTableCodeGenStrategy.cs
index 7ca7947a..e6050fae 100644
--- a/Admin.NET/Admin.NET.Core/CodeGen/Strategies/SingleTableCodeGenStrategy.cs
+++ b/Admin.NET/Admin.NET.Core/CodeGen/Strategies/SingleTableCodeGenStrategy.cs
@@ -4,7 +4,7 @@
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
-namespace Admin.NET.Core.CodeGen;
+namespace Admin.NET.Core;
///
/// 单表代码生成策略类
diff --git a/Admin.NET/Admin.NET.Core/CodeGen/Strategies/TableRelationshipCodeGenStrategy.cs b/Admin.NET/Admin.NET.Core/CodeGen/Strategies/TableRelationshipCodeGenStrategy.cs
index b115a8ee..0f0556dc 100644
--- a/Admin.NET/Admin.NET.Core/CodeGen/Strategies/TableRelationshipCodeGenStrategy.cs
+++ b/Admin.NET/Admin.NET.Core/CodeGen/Strategies/TableRelationshipCodeGenStrategy.cs
@@ -4,7 +4,7 @@
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
-namespace Admin.NET.Core.CodeGen;
+namespace Admin.NET.Core;
///
/// 关系对照代码生成策略类
diff --git a/Admin.NET/Admin.NET.Core/CodeGen/Strategies/TreeMasterSlaveTablesCodeGenStrategy.cs b/Admin.NET/Admin.NET.Core/CodeGen/Strategies/TreeMasterSlaveTablesCodeGenStrategy.cs
index 28e02f26..5a87d517 100644
--- a/Admin.NET/Admin.NET.Core/CodeGen/Strategies/TreeMasterSlaveTablesCodeGenStrategy.cs
+++ b/Admin.NET/Admin.NET.Core/CodeGen/Strategies/TreeMasterSlaveTablesCodeGenStrategy.cs
@@ -4,7 +4,7 @@
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
-namespace Admin.NET.Core.CodeGen;
+namespace Admin.NET.Core;
///
/// 主从明细带树组件代码生成策略类
diff --git a/Admin.NET/Admin.NET.Core/CodeGen/Strategies/TreeSingleTableCodeGenTableStrategy.cs b/Admin.NET/Admin.NET.Core/CodeGen/Strategies/TreeSingleTableCodeGenTableStrategy.cs
index 812f06e8..96045ef6 100644
--- a/Admin.NET/Admin.NET.Core/CodeGen/Strategies/TreeSingleTableCodeGenTableStrategy.cs
+++ b/Admin.NET/Admin.NET.Core/CodeGen/Strategies/TreeSingleTableCodeGenTableStrategy.cs
@@ -4,7 +4,7 @@
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
-namespace Admin.NET.Core.CodeGen;
+namespace Admin.NET.Core;
///
/// 单表带树组件代码生成策略类
diff --git a/Admin.NET/Admin.NET.Core/CodeGen/Strategies/TreeTableRelationshipCodeGenStrategy.cs b/Admin.NET/Admin.NET.Core/CodeGen/Strategies/TreeTableRelationshipCodeGenStrategy.cs
index 562ffd70..b4441507 100644
--- a/Admin.NET/Admin.NET.Core/CodeGen/Strategies/TreeTableRelationshipCodeGenStrategy.cs
+++ b/Admin.NET/Admin.NET.Core/CodeGen/Strategies/TreeTableRelationshipCodeGenStrategy.cs
@@ -4,7 +4,7 @@
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
-namespace Admin.NET.Core.CodeGen;
+namespace Admin.NET.Core;
///
/// 关系对照带树组件代码生成策略类
diff --git a/Admin.NET/Admin.NET.Core/Const/CacheConst.cs b/Admin.NET/Admin.NET.Core/Const/CacheConst.cs
index 673ce30e..cb41bc70 100644
--- a/Admin.NET/Admin.NET.Core/Const/CacheConst.cs
+++ b/Admin.NET/Admin.NET.Core/Const/CacheConst.cs
@@ -112,9 +112,9 @@ public class CacheConst
public const string KeyDict = "sys_dict:";
///
- /// 重复请求(幂等)字典缓存
+ /// 重复请求(幂等)缓存
///
- public const string KeyIdempotent = "sys_idempotent:";
+ public const string KeyIdempotent = "sys_idempotent_lock:";
///
/// Excel临时文件缓存
diff --git a/Admin.NET/Admin.NET.Core/Service/CodeGen/SysCodeGenColumnService.cs b/Admin.NET/Admin.NET.Core/Service/CodeGen/SysCodeGenColumnService.cs
index 41825976..2d019837 100644
--- a/Admin.NET/Admin.NET.Core/Service/CodeGen/SysCodeGenColumnService.cs
+++ b/Admin.NET/Admin.NET.Core/Service/CodeGen/SysCodeGenColumnService.cs
@@ -4,7 +4,6 @@
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
-using Admin.NET.Core.CodeGen;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
diff --git a/Admin.NET/Admin.NET.Core/Service/CodeGen/SysCodeGenService.cs b/Admin.NET/Admin.NET.Core/Service/CodeGen/SysCodeGenService.cs
index 34a5c020..9b8f9366 100644
--- a/Admin.NET/Admin.NET.Core/Service/CodeGen/SysCodeGenService.cs
+++ b/Admin.NET/Admin.NET.Core/Service/CodeGen/SysCodeGenService.cs
@@ -4,7 +4,6 @@
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
-using Admin.NET.Core.CodeGen;
using System.IO.Compression;
namespace Admin.NET.Core;
diff --git a/Admin.NET/Admin.NET.Core/Service/DataBase/SysDatabaseService.cs b/Admin.NET/Admin.NET.Core/Service/DataBase/SysDatabaseService.cs
index 0f1027bb..fb41d18c 100644
--- a/Admin.NET/Admin.NET.Core/Service/DataBase/SysDatabaseService.cs
+++ b/Admin.NET/Admin.NET.Core/Service/DataBase/SysDatabaseService.cs
@@ -18,16 +18,19 @@ public class SysDatabaseService : IDynamicApiController, ITransient
private readonly ISqlSugarClient _db;
private readonly IViewEngine _viewEngine;
private readonly CodeGenOptions _codeGenOptions;
+ private readonly CodeGenStrategyFactory _codeGenStrategyFactory;
public SysDatabaseService(UserManager userManager,
ISqlSugarClient db,
IViewEngine viewEngine,
- IOptions codeGenOptions)
+ IOptions codeGenOptions,
+ CodeGenStrategyFactory codeGenStrategyFactory)
{
_userManager = userManager;
_db = db;
_viewEngine = viewEngine;
_codeGenOptions = codeGenOptions.Value;
+ _codeGenStrategyFactory = codeGenStrategyFactory;
}
///
@@ -363,33 +366,10 @@ public class SysDatabaseService : IDynamicApiController, ITransient
///
[ApiDescriptionSettings(Name = "CreateEntity"), HttpPost]
[DisplayName("创建实体")]
- public void CreateEntity(CreateEntityInput input)
+ public async Task CreateEntity(CreateEntityInput input)
{
- var tResult = GenerateEntity(input);
- var targetPath = GetEntityTargetPath(input);
- File.WriteAllText(targetPath, tResult, Encoding.UTF8);
- }
-
- ///
- /// 创建实体文件内容
- ///
- ///
- ///
- ///
- ///
- ///
- [DisplayName("创建实体文件内容")]
- public string GenerateEntity(string ConfigId, string TableName, string Position, string BaseClassName)
- {
- var input = new CreateEntityInput
- {
- TableName = TableName,
- EntityName = TableName.ToFirstLetterUpperCase(),
- ConfigId = ConfigId,
- Position = string.IsNullOrWhiteSpace(Position) ? "Admin.NET.Application" : Position,
- BaseClassName = string.IsNullOrWhiteSpace(BaseClassName) ? "EntityBaseId" : BaseClassName
- };
- return GenerateEntity(input);
+ var template = await GenerateEntity(input);
+ await File.WriteAllTextAsync(template.OutPath, template.Context, Encoding.UTF8);
}
///
@@ -397,53 +377,12 @@ public class SysDatabaseService : IDynamicApiController, ITransient
///
///
///
+ [ApiDescriptionSettings(Name = "GenerateEntity"), HttpPost]
[DisplayName("创建实体文件内容")]
- public string GenerateEntity(CreateEntityInput input)
+ public async Task GenerateEntity(CreateEntityInput input)
{
- var config = App.GetOptions().ConnectionConfigs.FirstOrDefault(u => u.ConfigId.ToString() == input.ConfigId);
- input.Position = string.IsNullOrWhiteSpace(input.Position) ? "Admin.NET.Application" : input.Position;
- input.EntityName = string.IsNullOrWhiteSpace(input.EntityName)
- ? (config.DbSettings.EnableUnderLine ? CodeGenHelper.CamelColumnName(input.TableName, null) : input.TableName)
- : input.EntityName;
- string[] dbColumnNames = [];
- // Entity.cs.vm中是允许创建没有基类的实体的,所以这里也要做出相同的判断
- if (!string.IsNullOrWhiteSpace(input.BaseClassName))
- {
- _codeGenOptions.EntityBaseColumn.TryGetValue(input.BaseClassName, out dbColumnNames);
- if (dbColumnNames is null || dbColumnNames is { Length: 0 })
- throw Oops.Oh("基类配置文件不存在此类型");
- }
-
- var db = _db.AsTenant().GetConnectionScope(input.ConfigId);
- var dbColumnInfos = db.DbMaintenance.GetColumnInfosByTableName(input.TableName, false);
- dbColumnInfos.ForEach(u =>
- {
- // 禁止字段全是大写的
- if (u.DbColumnName.ToUpper() == u.DbColumnName)
- throw new Exception($"字段命名规范错误:{u.DbColumnName} 字段全是大写字母,请用大驼峰式命名规范!");
-
- u.PropertyName = config.DbSettings.EnableUnderLine ? CodeGenHelper.CamelColumnName(u.DbColumnName, dbColumnNames) : u.DbColumnName; // 转下划线后的列名需要再转回来
- u.DataType = CodeGenHelper.ConvertDataType(u, config.DbType);
- });
- if (_codeGenOptions.BaseEntityNames.Contains(input.BaseClassName, StringComparer.OrdinalIgnoreCase))
- dbColumnInfos = dbColumnInfos.Where(u => !dbColumnNames.Contains(u.PropertyName, StringComparer.OrdinalIgnoreCase)).ToList();
-
- var dbTableInfo = db.DbMaintenance.GetTableInfoList(false).FirstOrDefault(u => u.Name == input.TableName || u.Name == input.TableName.ToLower()) ?? throw Oops.Oh(ErrorCodeEnum.db1001);
- var templatePath = GetEntityTemplatePath();
- var tContent = File.ReadAllText(templatePath);
- var tResult = _viewEngine.RunCompileFromCached(tContent, new
- {
- NameSpace = $"{input.Position}.Entity",
- TableName = input.TableName,
- EntityName = input.EntityName,
- BaseClassName = string.IsNullOrWhiteSpace(input.BaseClassName) ? "" : $": {input.BaseClassName}",
- ConfigId = input.ConfigId,
- Description = string.IsNullOrWhiteSpace(dbTableInfo.Description) ? input.EntityName + "业务表" : dbTableInfo.Description,
- TableFields = dbColumnInfos,
- AuthorName = "Admin.NET",
- Email = "Admin.NET@qq.com"
- });
- return tResult;
+ var strategy = _codeGenStrategyFactory.GetStrategy(CodeGenSceneEnum.TableEntity);
+ return (await strategy.GenerateCode(input))?.FirstOrDefault();
}
///
@@ -454,191 +393,9 @@ public class SysDatabaseService : IDynamicApiController, ITransient
[DisplayName("创建种子数据")]
public async Task CreateSeedData(CreateSeedDataInput input)
{
- var config = App.GetOptions().ConnectionConfigs.FirstOrDefault(u => u.ConfigId.ToString() == input.ConfigId);
- input.Position = string.IsNullOrWhiteSpace(input.Position) ? "Admin.NET.Core" : input.Position;
-
- var templatePath = GetSeedDataTemplatePath();
- var db = _db.AsTenant().GetConnectionScope(input.ConfigId);
- var tableInfo = db.DbMaintenance.GetTableInfoList(false).First(u => u.Name == input.TableName); // 表名
- List dbColumnInfos = db.DbMaintenance.GetColumnInfosByTableName(input.TableName, false); // 所有字段
- IEnumerable entityInfos = await GetEntityInfos();
- Type entityType = null;
- foreach (var item in entityInfos)
- {
- if (tableInfo.Name.ToLower() != (config.DbSettings.EnableUnderLine ? UtilMethods.ToUnderLine(item.DbTableName) : item.DbTableName).ToLower()) continue;
- entityType = item.Type;
- break;
- }
-
- if (entityType == null) throw Oops.Oh(ErrorCodeEnum.db1003);
-
- input.EntityName = entityType.Name;
- input.SeedDataName = entityType.Name + "SeedData";
- if (!string.IsNullOrWhiteSpace(input.Suffix)) input.SeedDataName += input.Suffix;
-
- // 查询所有数据
- var query = db.QueryableByObject(entityType);
- // 如果 entityType.Name=="SysDictType"或"SysDictData"或"SysDictDataTenant" 加入查询条件 u.IsEnum!=1
- if (entityType.Name == "SysDictType" || entityType.Name == "SysDictData" || entityType.Name == "SysDictDataTenant")
- {
- if (config.DbSettings.EnableUnderLine)
- query = query.Where("is_enum != 1");
- else
- query = query.Where("IsEnum != 1");
- }
-
- // 优先用创建时间排序
- DbColumnInfo orderField = dbColumnInfos.FirstOrDefault(u => u.DbColumnName.ToLower() == "create_time" || u.DbColumnName.ToLower() == "createtime");
- if (orderField != null) query = query.OrderBy(orderField.DbColumnName);
- // 优先用创建时间排序,再使用第一个主键排序
- if (dbColumnInfos.Any(u => u.IsPrimarykey))
- query = query.OrderBy(dbColumnInfos.First(u => u.IsPrimarykey).DbColumnName);
- var records = ((IEnumerable)await query.ToListAsync()).ToDynamicList();
-
- // 过滤已存在的数据
- if (input.FilterExistingData && records.Count != 0)
- {
- // 获取实体类型-所有种数据数据类型
- var entityTypes = App.EffectiveTypes.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass && u.IsDefined(typeof(SugarTable), false) && u.FullName.EndsWith("." + input.EntityName))
- .Where(u => !u.GetCustomAttributes().Any()).ToList();
- if (entityTypes.Count == 1) // 只有一个实体匹配才能过滤
- {
- // 获取实体的主键对应的属性名称
- var pkInfo = entityTypes[0].GetProperties().FirstOrDefault(u => u.GetCustomAttribute()?.IsPrimaryKey == true);
- if (pkInfo != null)
- {
- var seedDataTypes = SeedDataHelper.GetSeedDataTypeList(entityTypes[0]);
- // 可能会重名的种子数据不作为过滤项
- string doNotFilterFullName1 = $"{input.Position}.SeedData.{input.SeedDataName}";
- string doNotFilterFullName2 = $"{input.Position}.{input.SeedDataName}"; // Core中的命名空间没有SeedData
-
- PropertyInfo idPropertySeedData = records[0].GetType().GetProperty("Id");
-
- for (int i = seedDataTypes.Count - 1; i >= 0; i--)
- {
- string fullName = seedDataTypes[i].FullName;
- if ((fullName == doNotFilterFullName1) || (fullName == doNotFilterFullName2)) continue;
-
- // 删除重复数据
- var instance = Activator.CreateInstance(seedDataTypes[i]);
- var hasDataMethod = seedDataTypes[i].GetMethod("HasData");
- var seedData = ((IEnumerable)hasDataMethod?.Invoke(instance, null))?.Cast