using System.Reflection; using System.Text; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using NPin.Framework.SqlSugarCore.Abstractions; using SqlSugar; using Volo.Abp.Auditing; using Volo.Abp.Data; using Volo.Abp.DependencyInjection; using Volo.Abp.Domain.Entities; using Volo.Abp.Domain.Entities.Events; using Volo.Abp.Guids; using Volo.Abp.MultiTenancy; using Volo.Abp.Users; namespace NPin.Framework.SqlSugarCore; public class SqlSugarDbContext : ISqlSugarDbContext { private IAbpLazyServiceProvider LazyServiceProvider { get; } public ISqlSugarClient SqlSugarClient { get; private set; } public DbConnOptions Options => LazyServiceProvider.LazyGetRequiredService>().Value; private AbpDbConnectionOptions _connectionOptions => LazyServiceProvider.LazyGetRequiredService>().Value; public ICurrentUser CurrentUser => LazyServiceProvider.GetRequiredService(); public ICurrentTenant CurrentTenant => LazyServiceProvider.LazyGetRequiredService(); public IDataFilter DataFilter => LazyServiceProvider.LazyGetRequiredService(); private IGuidGenerator GuidGenerator => LazyServiceProvider.LazyGetRequiredService(); protected ILoggerFactory Logger => LazyServiceProvider.LazyGetRequiredService(); protected virtual bool IsMultiTenantFilterEnabled => DataFilter?.IsEnabled() ?? false; protected virtual bool IsSoftDeleteFilterEnabled => DataFilter?.IsEnabled() ?? false; public IEntityChangeEventHelper EntityChangeEventHelper => LazyServiceProvider.LazyGetService(NullEntityChangeEventHelper.Instance); public void SetSqlSugarClient(ISqlSugarClient sqlSugarClient) { SqlSugarClient = sqlSugarClient; } public SqlSugarDbContext(IAbpLazyServiceProvider lazyServiceProvider) { LazyServiceProvider = lazyServiceProvider; var connectionCreator = LazyServiceProvider.LazyGetRequiredService(); connectionCreator.OnSqlSugarClientConfig = OnSqlSugarClientConfig; connectionCreator.EntityService = EntityService; connectionCreator.EntityNameService = EntityNameService; connectionCreator.DataExecuting = DataExecuting; connectionCreator.DataExecuted = DataExecuted; connectionCreator.OnLogExecuting = OnLogExecuting; connectionCreator.OnLogExecuted = OnLogExecuted; var connStr = GetCurrentConnectionString(); SqlSugarClient = new SqlSugarClient(connectionCreator.Build(action: opt => { opt.ConnectionString = connStr; })); connectionCreator.SetDbAop(SqlSugarClient); } /// /// db切换多库支持 /// /// protected virtual string GetCurrentConnectionString() { var defaultUrl = Options.Url ?? _connectionOptions.GetConnectionStringOrNull(ConnectionStrings.DefaultConnectionStringName); // 如果未开启多租户,返回db url 或者 默认连接字符串 if (!Options.EnabledSaasMultiTenancy) { return defaultUrl; } // 开启多租户 var connectionStringResolver = LazyServiceProvider.LazyGetRequiredService(); var connectionString = connectionStringResolver.ResolveAsync().Result; // 没有检测到使用多租户功能,默认使用默认库即可 if (string.IsNullOrWhiteSpace(connectionString)) { Volo.Abp.Check.NotNull(Options.Url, "租户默认库Default未找到"); connectionString = defaultUrl; } return connectionString!; } /// /// 上下文对象扩展 /// /// protected virtual void OnSqlSugarClientConfig(ISqlSugarClient sqlSugarClient) { //需自定义扩展 if (IsSoftDeleteFilterEnabled) { sqlSugarClient.QueryFilter.AddTableFilter(u => u.IsDeleted == false); } if (IsMultiTenantFilterEnabled) { sqlSugarClient.QueryFilter.AddTableFilter(u => u.TenantId == CurrentTenant.Id); } // 自定义其它Filter CustomDataFilter(sqlSugarClient); } protected virtual void CustomDataFilter(ISqlSugarClient sqlSugarClient) { } protected virtual void DataExecuted(object oldValue, DataAfterModel entityInfo) { } protected virtual void DataExecuting(object? oldValue, DataFilterModel entityInfo) { // 审计日志 switch (entityInfo.OperationType) { case DataFilterType.UpdateByObject: if (entityInfo.PropertyName.Equals(nameof(IAuditedObject.LastModificationTime))) { if (!DateTime.MinValue.Equals(oldValue)) { entityInfo.SetValue(DateTime.Now); } } if (entityInfo.PropertyName.Equals(nameof(IAuditedObject.LastModifierId))) { if (CurrentUser.Id != null) { entityInfo.SetValue(CurrentUser.Id); } } break; case DataFilterType.InsertByObject: if (entityInfo.PropertyName.Equals(nameof(IEntity.Id))) { //主键为空或者为默认最小值 if (Guid.Empty.Equals(oldValue)) { entityInfo.SetValue(GuidGenerator.Create()); } } if (entityInfo.PropertyName.Equals(nameof(IAuditedObject.CreationTime))) { //为空或者为默认最小值 if (oldValue is null || DateTime.MinValue.Equals(oldValue)) { entityInfo.SetValue(DateTime.Now); } } if (entityInfo.PropertyName.Equals(nameof(IAuditedObject.CreatorId))) { if (CurrentUser.Id != null) { entityInfo.SetValue(CurrentUser.Id); } } //插入时,需要租户id,先预留 if (entityInfo.PropertyName.Equals(nameof(IMultiTenant.TenantId))) { if (CurrentTenant is not null) { entityInfo.SetValue(CurrentTenant.Id); } } break; } //领域事件 switch (entityInfo.OperationType) { case DataFilterType.InsertByObject: if (entityInfo.PropertyName == nameof(IEntity.Id)) { EntityChangeEventHelper.PublishEntityCreatedEvent(entityInfo.EntityValue); } break; case DataFilterType.UpdateByObject: if (entityInfo.PropertyName == nameof(IEntity.Id)) { //软删除,发布的是删除事件 if (entityInfo.EntityValue is ISoftDelete softDelete) { if (softDelete.IsDeleted) { EntityChangeEventHelper.PublishEntityDeletedEvent(entityInfo.EntityValue); } } else { EntityChangeEventHelper.PublishEntityUpdatedEvent(entityInfo.EntityValue); } } break; case DataFilterType.DeleteByObject: if (entityInfo.PropertyName == nameof(IEntity.Id)) { EntityChangeEventHelper.PublishEntityDeletedEvent(entityInfo.EntityValue); } break; } } protected virtual void OnLogExecuting(string sql, SugarParameter[] pars) { } protected virtual void OnLogExecuted(string sql, SugarParameter[] pars) { if (Options.EnabledSqlLog) { var log = Logger.CreateLogger(); var sb = new StringBuilder(); sb.AppendLine(); sb.AppendLine("==========NPin-SQL=========="); sb.AppendLine(UtilMethods.GetNativeSql(sql, pars)); sb.AppendLine($"Count: {SqlSugarClient.Ado.SqlExecuteCount}"); sb.AppendLine($"耗时 {SqlSugarClient.Ado.SqlExecutionTime.TotalMilliseconds} 毫秒"); log.LogDebug(sb.ToString()); } } /// /// 实体配置 /// 自动 Nullable /// 自动主键 /// 自动Ignore关联配置(导航) /// 开启下划线 /// /// /// protected virtual void EntityService(PropertyInfo property, EntityColumnInfo column) { // 自动 Nullable if (new NullabilityInfoContext().Create(property).WriteState is NullabilityState.Nullable) { column.IsNullable = true; } if (property.Name == "ConcurrencyStamp") { column.IsIgnore = true; } if (property.PropertyType == typeof(ExtraPropertyDictionary)) { column.IsIgnore = true; } if (property.Name == nameof(Entity.Id)) { column.IsPrimarykey = true; } column.DbColumnName = UtilMethods.ToUnderLine(column.DbColumnName); } /// /// EntityName 配置 /// 开启下划线 /// /// /// protected virtual void EntityNameService(Type type, EntityInfo entity) { // 开启下划线 entity.DbTableName = UtilMethods.ToUnderLine(entity.DbTableName); } public void Backup() { string directoryName = "database_backup"; string fileName = $"{SqlSugarClient.Ado.Connection.Database}_" + DateTime.Now.ToString("yyyyMMdd_HHmmss"); if (!Directory.Exists(directoryName)) { Directory.CreateDirectory(directoryName); } switch (Options.DbType) { case DbType.MySql: // mysql 只支持.net core SqlSugarClient.DbMaintenance.BackupDataBase(SqlSugarClient.Ado.Connection.Database, $"{Path.Combine(directoryName, fileName)}.sql"); break; case DbType.Sqlite: // sqlite 只支持.net core SqlSugarClient.DbMaintenance.BackupDataBase(null, $"{fileName}.db"); break; case DbType.SqlServer: // 第一个参数库名 SqlSugarClient.DbMaintenance.BackupDataBase(SqlSugarClient.Ado.Connection.Database, $"{Path.Combine(directoryName, fileName)}.bak"); break; default: throw new NotImplementedException("其他数据库备份未实现"); } } }