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();
}
}
}