using System.Collections.Generic; using System.Data; using System.IO; using System.Reflection; using YD_Event.Core.Const; using YD_Event.Core.Entities; using YD_Event.Core.Enum; using YD_Event.Core.Options; using Mapster; using Newtonsoft.Json; using Yitter.IdGenerator; using Microsoft.Data.SqlClient; namespace SqlSugar; public static class SqlSugarExtensions { /// /// 添加 SqlSugar 拓展(适用于单个数据库) /// /// /// 数据库连接对象 /// /// public static IServiceCollection AddSqlSugar(this IServiceCollection services, ConnectionConfigExt config, Action buildAction = default) { return services.AddSqlSugar(new List() { config }, buildAction); } /// /// 添加 SqlSugar 拓展(适用于多数据库) /// /// /// 数据库连接对象集合 /// /// public static IServiceCollection AddSqlSugar(this IServiceCollection services, List configs, Action buildAction = default) { SqlSugarScope sqlSugarScope = new SqlSugarScope(configs.Adapt>(), buildAction ?? Aop); configs.ForEach(x => { Init(sqlSugarScope, x); }); services.AddSingleton(sqlSugarScope);//使用单例注入 services.AddSingleton(sqlSugarScope); services.AddUnitOfWork();//事务 services.AddScoped(typeof(ISqlSugarRepository<>), typeof(SqlSugarRepository<>));//注入泛型仓储 return services; } /// /// 初始化数据库 /// /// /// static void Init(SqlSugarScope client, ConnectionConfigExt config) { if (!config.EnableInitDb) { return; } SqlSugarScopeProvider provider = client.GetConnectionScope(config.ConfigId); //创建数据库 provider.DbMaintenance.CreateDatabase(); IEnumerable types = App.EffectiveTypes.Where(x => !x.IsInterface && x.IsClass && !x.IsAbstract && typeof(IEntity).IsAssignableFrom(x)); provider.CodeFirst.InitTables(types.ToArray()); //初始化数据 InitData(client); } /// /// 添加 SqlSugar 服务 /// /// /// public static IServiceCollection AddSqlSugar(this IServiceCollection services) { var options = App.GetOptions(); if (string.Equals(Environment.GetEnvironmentVariable("YD_EVENT_ALLOW_UNENCRYPTED_SQL"), "1", StringComparison.Ordinal)) { options.Connections.ForEach(connection => { if (connection.DbType != DbType.SqlServer) return; var builder = new SqlConnectionStringBuilder(connection.ConnectionString) { Encrypt = false, TrustServerCertificate = true }; connection.ConnectionString = builder.ConnectionString; }); } ICacheService ormCache = new SqlSugarCache(); options.Connections.ForEach(x => { x.MoreSettings = new ConnMoreSettings() { //所有 增、删 、改 会自动调用.RemoveDataCache() IsAutoRemoveDataCache = true }; //配置缓存 x.ConfigureExternalServices = new ConfigureExternalServices() { DataInfoCacheService = ormCache, EntityService = ((prop, column) => { //如果实体不是主键,并且是可空类型,表列设置为可空(支持string?和string) if (column.IsPrimarykey == false && new NullabilityInfoContext() .Create(prop).WriteState is NullabilityState.Nullable) { column.IsNullable = true; } }) }; }); return AddSqlSugar(services, options.Connections, Aop); } /// /// 拦截器 /// private static readonly Action Aop = (db) => { db.Aop.DataExecuting = (_, entityInfo) => { try { switch (entityInfo.OperationType) { //执行insert时 case DataFilterType.InsertByObject: //自动设置主键 if (entityInfo.EntityColumnInfo.IsPrimarykey && entityInfo.EntityValue is Entity { Id: 0 } entity) { entity.Id = YitIdHelper.NextId(); } // 创建审计字段只在调用方未赋值时补齐,保留数据迁移等场景的显式历史值。 if (entityInfo.PropertyName == nameof(ICreatedTime.CreatedTime) && entityInfo.EntityValue is ICreatedTime { CreatedTime: var createdAt } && createdAt == DateTime.MinValue) { entityInfo.SetValue(DateTime.Now); } if (entityInfo.PropertyName == nameof(ICreatedUserId.CreatedUserId) && entityInfo.EntityValue is ICreatedUserId { CreatedUserId: 0 } && TryGetCurrentUserId(out var createdUserId)) { entityInfo.SetValue(createdUserId); } break; case DataFilterType.UpdateByObject: // 修改时间每次更新都刷新;有登录上下文时,修改人统一取当前操作者。 if (entityInfo.PropertyName == nameof(IUpdatedTime.UpdatedTime) && entityInfo.EntityValue is IUpdatedTime) { entityInfo.SetValue(DateTime.Now); } if (entityInfo.PropertyName == nameof(IUpdatedUserId.UpdatedUserId) && entityInfo.EntityValue is IUpdatedUserId updatedUser) { var claimValue = App.User?.FindFirst(AuthClaimsConst.AuthIdKey)?.Value; var updatedUserId = ResolveUpdatedUserId(claimValue, updatedUser.UpdatedUserId); if (updatedUserId.HasValue) { // 存在有效登录用户时始终覆盖显式值,确保记录最后一次实际操作人。 entityInfo.SetValue(updatedUserId.Value); } } break; case DataFilterType.DeleteByObject: break; } } catch (TargetInvocationException ex) { Console.WriteLine($"[Error] TargetInvocationException in DataExecuting: {ex.InnerException?.ToString() ?? ex.Message}"); throw ex.InnerException ?? ex; } catch (Exception ex) { Console.WriteLine($"[Error] Exception in DataExecuting: {ex.ToString()}"); throw; } }; // 文档地址:https://www.donet5.com/Home/Doc?typeId=1204 db.Aop.OnLogExecuting = (sql, parameters) => { var originColor = Console.ForegroundColor; if (sql.StartsWith("SELECT", StringComparison.OrdinalIgnoreCase)) Console.ForegroundColor = ConsoleColor.Green; if (sql.StartsWith("UPDATE", StringComparison.OrdinalIgnoreCase) || sql.StartsWith("INSERT", StringComparison.OrdinalIgnoreCase)) Console.ForegroundColor = ConsoleColor.Yellow; if (sql.StartsWith("DELETE", StringComparison.OrdinalIgnoreCase)) Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("【" + DateTime.Now + "——执行SQL】\r\n" + UtilMethods.GetSqlString(db.CurrentConnectionConfig.DbType, sql, parameters) + "\r\n"); Console.ForegroundColor = originColor; //App.PrintToMiniProfiler("SqlSugar", "Info", sql + "\r\n" + db.Utilities.SerializeObject(parameters.ToDictionary(it => it.ParameterName, it => it.Value))); }; db.Aop.OnError = ex => { if (ex.Parametres == null) return; var originColor = Console.ForegroundColor; Console.ForegroundColor = ConsoleColor.DarkRed; var pars = db.Utilities.SerializeObject(((SugarParameter[])ex.Parametres).ToDictionary(it => it.ParameterName, it => it.Value)); Console.WriteLine("【" + DateTime.Now + "——错误SQL】\r\n" + UtilMethods.GetSqlString(db.CurrentConnectionConfig.DbType, ex.Sql, (SugarParameter[])ex.Parametres) + "\r\n"); Console.ForegroundColor = originColor; // App.PrintToMiniProfiler("SqlSugar", "Error", $"{ex.Message}{Environment.NewLine}{ex.Sql}{pars}{Environment.NewLine}"); }; //配置逻辑删除过滤器(查询数据时过滤掉已被标记删除的数据) db.QueryFilter.AddTableFilter(it => it.DeleteMark == false); }; private static bool TryGetCurrentUserId(out long userId) { var claimValue = App.User?.FindFirst(AuthClaimsConst.AuthIdKey)?.Value; return long.TryParse(claimValue, out userId) && userId > 0; } /// /// 有有效登录用户时以当前用户为准;无用户上下文时保留后台任务显式传入的操作者。 /// internal static long? ResolveUpdatedUserId(string? currentUserClaim, long? originalUserId) { return long.TryParse(currentUserClaim, out var currentUserId) && currentUserId > 0 ? currentUserId : originalUserId; } /// /// 初始化基础数据 /// private static void InitData(SqlSugarScope client) { string path = Path.Combine(AppContext.BaseDirectory, "InitData"); var dir = new DirectoryInfo(path); var files = dir.GetFiles("*.txt"); foreach (var file in files) { using var reader = file.OpenText(); string s = reader.ReadToEnd(); var table = JsonConvert.DeserializeObject(s); if (table.Rows.Count == 0) { continue; } table.TableName = file.Name.Replace(".txt", ""); client.Storageable(table).WhereColumns("Id").ToStorage().AsInsertable.ExecuteCommand(); } } }