feat: 🎉 test log sql operate log

This commit is contained in:
anjoy8 2023-08-23 16:13:42 +08:00
parent a375998699
commit 8372a3a0d4
7 changed files with 169 additions and 111 deletions

View File

@ -1393,9 +1393,21 @@
</member>
<member name="T:Blog.Core.Api.Controllers.Systems.DynamicCodeFirstController">
<summary>
缓存管理
动态建表 CURD
</summary>
</member>
<member name="M:Blog.Core.Api.Controllers.Systems.DynamicCodeFirstController.GetDynamicType">
<summary>
动态type
</summary>
<returns></returns>
</member>
<member name="M:Blog.Core.Api.Controllers.Systems.DynamicCodeFirstController.GetDynamicType2">
<summary>
动态type 继承BaseEntity
</summary>
<returns></returns>
</member>
<member name="M:Blog.Core.Api.Controllers.Systems.DynamicCodeFirstController.TestCreateTable">
<summary>
测试建表

View File

@ -57,6 +57,9 @@
"TranAOP": {
"Enabled": true
},
"UserAuditAOP": {
"Enabled": false
},
"SqlAOP": {
"Enabled": true,
"LogToFile": {

View File

@ -11,7 +11,7 @@ namespace Blog.Core.Common.DB.Aop;
public static class SqlSugarAop
{
public static void OnLogExecuting(ISqlSugarClient sqlSugarScopeProvider, string sql, SugarParameter[] p, ConnectionConfig config)
public static void OnLogExecuting(ISqlSugarClient sqlSugarScopeProvider, string user, string table, string operate, string sql, SugarParameter[] p, ConnectionConfig config)
{
try
{
@ -25,8 +25,8 @@ public static class SqlSugarAop
{
using (LogContextExtension.Create.SqlAopPushProperty(sqlSugarScopeProvider))
{
Log.Information("------------------ \r\n ConnId:[{ConnId}]【SQL语句】: \r\n {Sql}",
config.ConfigId, UtilMethods.GetNativeSql( sql, p));
Log.Information("------------------ \r\n User:[{User}] Table:[{Table}] Operate:[{Operate}] ConnId:[{ConnId}]【SQL语句】: \r\n {Sql}",
user, table, operate, config.ConfigId, UtilMethods.GetNativeSql(sql, p));
}
}
}

View File

@ -48,7 +48,7 @@ namespace Blog.Core.Common.HttpContextUser
public bool IsAuthenticated()
{
return _accessor.HttpContext.User.Identity.IsAuthenticated;
return _accessor.HttpContext?.User?.Identity?.IsAuthenticated ?? false;
}

View File

@ -79,6 +79,15 @@ namespace Blog.Core.Extensions
{
ConsoleHelper.WriteSuccessLine($"Transaction AOP: True");
}
// 审计AOP
if (!AppSettings.app(new string[] { "AppSettings", "UserAuditAOP", "Enabled" }).ObjToBool())
{
Console.WriteLine($"UserAudit AOP: False");
}
else
{
ConsoleHelper.WriteSuccessLine($"UserAudit AOP: True");
}
// 数据库Sql执行AOP
if (!AppSettings.app(new string[] { "AppSettings", "SqlAOP", "OutToLogFile", "Enabled" }).ObjToBool())
@ -251,6 +260,7 @@ namespace Blog.Core.Extensions
new string[] { "缓存AOP", AppSettings.app("AppSettings", "CachingAOP", "Enabled") },
new string[] { "服务日志AOP", AppSettings.app("AppSettings", "LogAOP", "Enabled") },
new string[] { "事务AOP", AppSettings.app("AppSettings", "TranAOP", "Enabled") },
new string[] { "服务审计AOP", AppSettings.app("AppSettings", "UserAuditAOP", "Enabled") },
new string[] { "Sql执行AOP", AppSettings.app("AppSettings", "SqlAOP", "Enabled") },
new string[] { "Sql执行AOP控制台输出", AppSettings.app("AppSettings", "SqlAOP", "LogToConsole", "Enabled") },
};

View File

@ -57,6 +57,12 @@ namespace Blog.Core.Extensions
cacheType.Add(typeof(BlogLogAOP));
}
if (AppSettings.app(new string[] { "AppSettings", "UserAuditAOP", "Enabled" }).ObjToBool())
{
builder.RegisterType<BlogUserAuditAOP>();
cacheType.Add(typeof(BlogUserAuditAOP));
}
builder.RegisterGeneric(typeof(BaseRepository<>)).As(typeof(IBaseRepository<>)).InstancePerDependency(); //注册仓储
builder.RegisterGeneric(typeof(BaseServices<>)).As(typeof(IBaseServices<>)).InstancePerDependency(); //注册服务

View File

@ -11,126 +11,153 @@ using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Blog.Core.Common.Caches;
using Blog.Core.Common.Core;
using Blog.Core.Common.HttpContextUser;
using static Grpc.Core.ChannelOption;
using System.Text.RegularExpressions;
namespace Blog.Core.Extensions
{
/// <summary>
/// SqlSugar 启动服务
/// </summary>
public static class SqlsugarSetup
{
private static readonly MemoryCache Cache = new MemoryCache(new MemoryCacheOptions());
/// <summary>
/// SqlSugar 启动服务
/// </summary>
public static class SqlsugarSetup
{
private static readonly MemoryCache Cache = new MemoryCache(new MemoryCacheOptions());
public static void AddSqlsugarSetup(this IServiceCollection services)
{
if (services == null) throw new ArgumentNullException(nameof(services));
public static void AddSqlsugarSetup(this IServiceCollection services)
{
if (services == null) throw new ArgumentNullException(nameof(services));
// 默认添加主数据库连接
MainDb.CurrentDbConnId = AppSettings.app(new string[] {"MainDB"});
// 默认添加主数据库连接
MainDb.CurrentDbConnId = AppSettings.app(new string[] { "MainDB" });
BaseDBConfig.MutiConnectionString.slaveDbs.ForEach(s =>
{
BaseDBConfig.AllSlaveConfigs.Add(new SlaveConnectionConfig()
{
HitRate = s.HitRate,
ConnectionString = s.Connection
});
});
BaseDBConfig.MutiConnectionString.slaveDbs.ForEach(s =>
{
BaseDBConfig.AllSlaveConfigs.Add(new SlaveConnectionConfig()
{
HitRate = s.HitRate,
ConnectionString = s.Connection
});
});
BaseDBConfig.MutiConnectionString.allDbs.ForEach(m =>
{
var config = new ConnectionConfig()
{
ConfigId = m.ConnId.ObjToString().ToLower(),
ConnectionString = m.Connection,
DbType = (DbType) m.DbType,
IsAutoCloseConnection = true,
// Check out more information: https://github.com/anjoy8/Blog.Core/issues/122
//IsShardSameThread = false,
MoreSettings = new ConnMoreSettings()
{
//IsWithNoLockQuery = true,
IsAutoRemoveDataCache = true,
SqlServerCodeFirstNvarchar = true,
},
// 从库
SlaveConnectionConfigs = BaseDBConfig.AllSlaveConfigs,
// 自定义特性
ConfigureExternalServices = new ConfigureExternalServices()
{
DataInfoCacheService = new SqlSugarCacheService(),
EntityService = (property, column) =>
{
if (column.IsPrimarykey && property.PropertyType == typeof(int))
{
column.IsIdentity = true;
}
}
},
InitKeyType = InitKeyType.Attribute
};
if (SqlSugarConst.LogConfigId.ToLower().Equals(m.ConnId.ToLower()))
{
BaseDBConfig.LogConfig = config;
}
else
{
BaseDBConfig.ValidConfig.Add(config);
}
BaseDBConfig.MutiConnectionString.allDbs.ForEach(m =>
{
var config = new ConnectionConfig()
{
ConfigId = m.ConnId.ObjToString().ToLower(),
ConnectionString = m.Connection,
DbType = (DbType)m.DbType,
IsAutoCloseConnection = true,
// Check out more information: https://github.com/anjoy8/Blog.Core/issues/122
//IsShardSameThread = false,
MoreSettings = new ConnMoreSettings()
{
//IsWithNoLockQuery = true,
IsAutoRemoveDataCache = true,
SqlServerCodeFirstNvarchar = true,
},
// 从库
SlaveConnectionConfigs = BaseDBConfig.AllSlaveConfigs,
// 自定义特性
ConfigureExternalServices = new ConfigureExternalServices()
{
DataInfoCacheService = new SqlSugarCacheService(),
EntityService = (property, column) =>
{
if (column.IsPrimarykey && property.PropertyType == typeof(int))
{
column.IsIdentity = true;
}
}
},
InitKeyType = InitKeyType.Attribute
};
if (SqlSugarConst.LogConfigId.ToLower().Equals(m.ConnId.ToLower()))
{
BaseDBConfig.LogConfig = config;
}
else
{
BaseDBConfig.ValidConfig.Add(config);
}
BaseDBConfig.AllConfigs.Add(config);
});
BaseDBConfig.AllConfigs.Add(config);
});
if (BaseDBConfig.LogConfig is null)
{
throw new ApplicationException("未配置Log库连接");
}
// SqlSugarScope是线程安全可使用单例注入
// 参考https://www.donet5.com/Home/Doc?typeId=1181
services.AddSingleton<ISqlSugarClient>(o =>
{
return new SqlSugarScope(BaseDBConfig.AllConfigs, db =>
{
BaseDBConfig.ValidConfig.ForEach(config =>
{
var dbProvider = db.GetConnectionScope((string) config.ConfigId);
if (BaseDBConfig.LogConfig is null)
{
throw new ApplicationException("未配置Log库连接");
}
// 打印SQL语句
dbProvider.Aop.OnLogExecuting = (s, parameters) =>
SqlSugarAop.OnLogExecuting(dbProvider, s, parameters, config);
// SqlSugarScope是线程安全可使用单例注入
// 参考https://www.donet5.com/Home/Doc?typeId=1181
services.AddSingleton<ISqlSugarClient>(o =>
{
return new SqlSugarScope(BaseDBConfig.AllConfigs, db =>
{
BaseDBConfig.ValidConfig.ForEach(config =>
{
var dbProvider = db.GetConnectionScope((string)config.ConfigId);
// 数据审计
dbProvider.Aop.DataExecuting = SqlSugarAop.DataExecuting;
// 打印SQL语句
dbProvider.Aop.OnLogExecuting = (s, parameters) =>
{
var user = InternalApp.RootServices.GetService<IUser>();
SqlSugarAop.OnLogExecuting(dbProvider, user?.Name.ObjToString(), ExtractTableName(s), Enum.GetName(typeof(SugarActionType), dbProvider.SugarActionType), s, parameters, config);
};
// 配置实体假删除过滤器
RepositorySetting.SetDeletedEntityFilter(dbProvider);
// 配置实体数据权限
RepositorySetting.SetTenantEntityFilter(dbProvider);
});
});
});
}
// 数据审计
dbProvider.Aop.DataExecuting = SqlSugarAop.DataExecuting;
private static string GetWholeSql(SugarParameter[] paramArr, string sql)
{
foreach (var param in paramArr)
{
sql.Replace(param.ParameterName, param.Value.ObjToString());
}
// 配置实体假删除过滤器
RepositorySetting.SetDeletedEntityFilter(dbProvider);
// 配置实体数据权限
RepositorySetting.SetTenantEntityFilter(dbProvider);
});
});
});
}
return sql;
}
private static string GetWholeSql(SugarParameter[] paramArr, string sql)
{
foreach (var param in paramArr)
{
sql.Replace(param.ParameterName, param.Value.ObjToString());
}
private static string GetParas(SugarParameter[] pars)
{
string key = "【SQL参数】";
foreach (var param in pars)
{
key += $"{param.ParameterName}:{param.Value}\n";
}
return sql;
}
return key;
}
}
private static string GetParas(SugarParameter[] pars)
{
string key = "【SQL参数】";
foreach (var param in pars)
{
key += $"{param.ParameterName}:{param.Value}\n";
}
return key;
}
private static string ExtractTableName(string sql)
{
// 匹配 SQL 语句中的表名的正则表达式
//string regexPattern = @"\s*(?:UPDATE|DELETE\s+FROM|SELECT\s+\*\s+FROM)\s+(\w+)";
string regexPattern = @"(?i)(?:FROM|UPDATE|DELETE\s+FROM)\s+`(.+?)`";
Regex regex = new Regex(regexPattern, RegexOptions.IgnoreCase);
Match match = regex.Match(sql);
if (match.Success)
{
// 提取匹配到的表名
return match.Groups[1].Value;
}
else
{
// 如果没有匹配到表名,则返回空字符串或者抛出异常等处理
return string.Empty;
}
}
}
}