chore: 构建稳定版本

This commit is contained in:
陈淳
2023-12-11 09:55:12 +08:00
parent 098d4bc85f
commit 769a6a9c63
756 changed files with 10431 additions and 19867 deletions

View File

@@ -0,0 +1,47 @@
using SqlSugar;
namespace Yi.Framework.SqlSugarCore
{
public class DbConnOptions
{
/// <summary>
/// 连接字符串,必填
/// </summary>
public string? Url { get; set; }
/// <summary>
/// 数据库类型
/// </summary>
public DbType? DbType { get; set; }
/// <summary>
/// 开启种子数据
/// </summary>
public bool EnabledDbSeed { get; set; } = false;
/// <summary>
/// 开启读写分离
/// </summary>
public bool EnabledReadWrite { get; set; } = false;
/// <summary>
/// 开启codefirst
/// </summary>
public bool EnabledCodeFirst { get; set; } = false;
/// <summary>
/// 开启sql日志
/// </summary>
public bool EnabledSqlLog { get; set; } = true;
/// <summary>
/// 实体程序集
/// </summary>
public List<string>? EntityAssembly { get; set; }
/// <summary>
/// 读写分离
/// </summary>
public List<string>? ReadUrl { get; set; }
}
}

View File

@@ -0,0 +1,362 @@
using System.Linq.Expressions;
using SqlSugar;
using Volo.Abp.Domain.Entities;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Linq;
using Yi.Framework.SqlSugarCore.Abstractions;
namespace Yi.Framework.SqlSugarCore.Repositories
{
public class SqlSugarRepository<TEntity> : ISqlSugarRepository<TEntity>, IRepository<TEntity> where TEntity : class, IEntity, new()
{
public ISqlSugarClient _Db => GetDbContextAsync().Result;
public ISugarQueryable<TEntity> _DbQueryable => GetDbContextAsync().Result.Queryable<TEntity>();
private ISugarDbContextProvider<ISqlSugarDbContext> _sugarDbContextProvider;
public IAsyncQueryableExecuter AsyncExecuter { get; }
public SqlSugarRepository(ISugarDbContextProvider<ISqlSugarDbContext> sugarDbContextProvider)
{
_sugarDbContextProvider = sugarDbContextProvider;
}
/// <summary>
/// 获取DB
/// </summary>
/// <returns></returns>
public virtual async Task<ISqlSugarClient> GetDbContextAsync()
{
var db = (await _sugarDbContextProvider.GetDbContextAsync()).SqlSugarClient;
await Console.Out.WriteLineAsync("获取的id" + db.ContextID);
return db;
}
/// <summary>
/// 获取简单Db
/// </summary>
/// <returns></returns>
public virtual async Task<SimpleClient<TEntity>> GetDbSimpleClientAsync()
{
var db = await GetDbContextAsync();
return new SimpleClient<TEntity>(db);
}
#region Abp模块
public async Task<TEntity?> FindAsync(Expression<Func<TEntity, bool>> predicate, bool includeDetails = true, CancellationToken cancellationToken = default)
{
return await GetFirstAsync(predicate);
}
public async Task<TEntity> GetAsync(Expression<Func<TEntity, bool>> predicate, bool includeDetails = true, CancellationToken cancellationToken = default)
{
return await GetFirstAsync(predicate);
}
public async Task DeleteAsync(Expression<Func<TEntity, bool>> predicate, bool autoSave = false, CancellationToken cancellationToken = default)
{
await DeleteAsync(predicate);
}
public async Task DeleteDirectAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default)
{
await DeleteAsync(predicate);
}
public IQueryable<TEntity> WithDetails()
{
throw new NotImplementedException();
}
public IQueryable<TEntity> WithDetails(params Expression<Func<TEntity, object>>[] propertySelectors)
{
throw new NotImplementedException();
}
public Task<IQueryable<TEntity>> WithDetailsAsync()
{
throw new NotImplementedException();
}
public Task<IQueryable<TEntity>> WithDetailsAsync(params Expression<Func<TEntity, object>>[] propertySelectors)
{
throw new NotImplementedException();
}
public Task<IQueryable<TEntity>> GetQueryableAsync()
{
throw new NotImplementedException();
}
public async Task<List<TEntity>> GetListAsync(Expression<Func<TEntity, bool>> predicate, bool includeDetails = false, CancellationToken cancellationToken = default)
{
return await GetListAsync(predicate);
}
public async Task<TEntity> InsertAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default)
{
return await InsertReturnEntityAsync(entity);
}
public async Task InsertManyAsync(IEnumerable<TEntity> entities, bool autoSave = false, CancellationToken cancellationToken = default)
{
await InsertRangeAsync(entities.ToList());
}
public async Task<TEntity> UpdateAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default)
{
await UpdateAsync(entity);
return entity;
}
public async Task UpdateManyAsync(IEnumerable<TEntity> entities, bool autoSave = false, CancellationToken cancellationToken = default)
{
await UpdateRangeAsync(entities.ToList());
}
public async Task DeleteAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default)
{
await DeleteAsync(entity);
}
public async Task DeleteManyAsync(IEnumerable<TEntity> entities, bool autoSave = false, CancellationToken cancellationToken = default)
{
await DeleteAsync(entities.ToList());
}
public async Task<List<TEntity>> GetListAsync(bool includeDetails = false, CancellationToken cancellationToken = default)
{
return await GetListAsync();
}
public async Task<long> GetCountAsync(CancellationToken cancellationToken = default)
{
return await this.CountAsync();
}
public async Task<List<TEntity>> GetPagedListAsync(int skipCount, int maxResultCount, string sorting, bool includeDetails = false, CancellationToken cancellationToken = default)
{
return await GetPageListAsync(_ => true, skipCount, maxResultCount);
}
#endregion
#region DB快捷操作
public async Task<IDeleteable<TEntity>> AsDeleteable()
{
return (await GetDbSimpleClientAsync()).AsDeleteable();
}
public async Task<IInsertable<TEntity>> AsInsertable(List<TEntity> insertObjs)
{
return (await GetDbSimpleClientAsync()).AsInsertable(insertObjs);
}
public async Task<IInsertable<TEntity>> AsInsertable(TEntity insertObj)
{
return (await GetDbSimpleClientAsync()).AsInsertable(insertObj);
}
public async Task<IInsertable<TEntity>> AsInsertable(TEntity[] insertObjs)
{
return (await GetDbSimpleClientAsync()).AsInsertable(insertObjs);
}
public async Task<ISugarQueryable<TEntity>> AsQueryable()
{
return (await GetDbSimpleClientAsync()).AsQueryable();
}
public async Task<ISqlSugarClient> AsSugarClient()
{
return (await GetDbSimpleClientAsync()).AsSugarClient();
}
public async Task<ITenant> AsTenant()
{
return (await GetDbSimpleClientAsync()).AsTenant();
}
public async Task<IUpdateable<TEntity>> AsUpdateable(List<TEntity> updateObjs)
{
return (await GetDbSimpleClientAsync()).AsUpdateable(updateObjs);
}
public async Task<IUpdateable<TEntity>> AsUpdateable(TEntity updateObj)
{
return (await GetDbSimpleClientAsync()).AsUpdateable(updateObj);
}
public async Task<IUpdateable<TEntity>> AsUpdateable()
{
return (await GetDbSimpleClientAsync()).AsUpdateable();
}
public async Task<IUpdateable<TEntity>> AsUpdateable(TEntity[] updateObjs)
{
return (await GetDbSimpleClientAsync()).AsUpdateable(updateObjs);
}
#endregion
#region SimpleClient模块
public async Task<int> CountAsync(Expression<Func<TEntity, bool>> whereExpression)
{
return await (await GetDbSimpleClientAsync()).CountAsync(whereExpression);
}
public async Task<bool> DeleteAsync(TEntity deleteObj)
{
return await (await GetDbSimpleClientAsync()).DeleteAsync(deleteObj);
}
public async Task<bool> DeleteAsync(List<TEntity> deleteObjs)
{
return await (await GetDbSimpleClientAsync()).DeleteAsync(deleteObjs);
}
public async Task<bool> DeleteAsync(Expression<Func<TEntity, bool>> whereExpression)
{
return await (await GetDbSimpleClientAsync()).DeleteAsync(whereExpression);
}
public async Task<bool> DeleteByIdAsync(dynamic id)
{
return await (await GetDbSimpleClientAsync()).DeleteByIdAsync(id);
}
public async Task<bool> DeleteByIdsAsync(dynamic[] ids)
{
return await (await GetDbSimpleClientAsync()).DeleteByIdAsync(ids);
}
public async Task<TEntity> GetByIdAsync(dynamic id)
{
return await (await GetDbSimpleClientAsync()).GetByIdAsync(id);
}
public async Task<TEntity> GetFirstAsync(Expression<Func<TEntity, bool>> whereExpression)
{
return await (await GetDbSimpleClientAsync()).GetFirstAsync(whereExpression);
}
public async Task<List<TEntity>> GetListAsync()
{
return await (await GetDbSimpleClientAsync()).GetListAsync();
}
public async Task<List<TEntity>> GetListAsync(Expression<Func<TEntity, bool>> whereExpression)
{
return await (await GetDbSimpleClientAsync()).GetListAsync(whereExpression);
}
public async Task<List<TEntity>> GetPageListAsync(Expression<Func<TEntity, bool>> whereExpression, int pageNum, int pageSize)
{
return await (await GetDbSimpleClientAsync()).GetPageListAsync(whereExpression, new PageModel() { PageIndex = pageNum, PageSize = pageSize });
}
public async Task<List<TEntity>> GetPageListAsync(Expression<Func<TEntity, bool>> whereExpression, int pageNum, int pageSize, Expression<Func<TEntity, object>>? orderByExpression = null, OrderByType orderByType = OrderByType.Asc)
{
return await (await GetDbSimpleClientAsync()).GetPageListAsync(whereExpression, new PageModel { PageIndex = pageNum, PageSize = pageSize }, orderByExpression, orderByType);
}
public async Task<TEntity> GetSingleAsync(Expression<Func<TEntity, bool>> whereExpression)
{
return await (await GetDbSimpleClientAsync()).GetSingleAsync(whereExpression);
}
public async Task<bool> InsertAsync(TEntity insertObj)
{
return await (await GetDbSimpleClientAsync()).InsertAsync(insertObj);
}
public async Task<bool> InsertOrUpdateAsync(TEntity data)
{
return await (await GetDbSimpleClientAsync()).InsertOrUpdateAsync(data);
}
public async Task<bool> InsertOrUpdateAsync(List<TEntity> datas)
{
return await (await GetDbSimpleClientAsync()).InsertOrUpdateAsync(datas);
}
public async Task<bool> InsertRangeAsync(List<TEntity> insertObjs)
{
return await (await GetDbSimpleClientAsync()).InsertRangeAsync(insertObjs);
}
public async Task<long> InsertReturnBigIdentityAsync(TEntity insertObj)
{
return await (await GetDbSimpleClientAsync()).InsertReturnBigIdentityAsync(insertObj);
}
public async Task<TEntity> InsertReturnEntityAsync(TEntity insertObj)
{
return await (await GetDbSimpleClientAsync()).InsertReturnEntityAsync(insertObj);
}
public async Task<int> InsertReturnIdentityAsync(TEntity insertObj)
{
return await (await GetDbSimpleClientAsync()).InsertReturnIdentityAsync(insertObj);
}
public async Task<long> InsertReturnSnowflakeIdAsync(TEntity insertObj)
{
return await (await GetDbSimpleClientAsync()).InsertReturnSnowflakeIdAsync(insertObj);
}
public async Task<bool> IsAnyAsync(Expression<Func<TEntity, bool>> whereExpression)
{
return await (await GetDbSimpleClientAsync()).IsAnyAsync(whereExpression);
}
public async Task<bool> UpdateAsync(TEntity updateObj)
{
return await (await GetDbSimpleClientAsync()).UpdateAsync(updateObj);
}
public async Task<bool> UpdateAsync(Expression<Func<TEntity, TEntity>> columns, Expression<Func<TEntity, bool>> whereExpression)
{
return await (await GetDbSimpleClientAsync()).UpdateAsync(columns, whereExpression);
}
public async Task<bool> UpdateRangeAsync(List<TEntity> updateObjs)
{
return await (await GetDbSimpleClientAsync()).UpdateRangeAsync(updateObjs);
}
#endregion
}
public class SqlSugarRepository<TEntity, TKey> : SqlSugarRepository<TEntity>, ISqlSugarRepository<TEntity,TKey>, IRepository<TEntity, TKey> where TEntity : class, IEntity<TKey>, new()
{
public SqlSugarRepository(ISugarDbContextProvider<ISqlSugarDbContext> sugarDbContextProvider) : base(sugarDbContextProvider)
{
}
public async Task DeleteAsync(TKey id, bool autoSave = false, CancellationToken cancellationToken = default)
{
await DeleteByIdAsync(id);
}
public async Task DeleteManyAsync(IEnumerable<TKey> ids, bool autoSave = false, CancellationToken cancellationToken = default)
{
await DeleteByIdsAsync(ids.Select(x => (object)x).ToArray());
}
public async Task<TEntity?> FindAsync(TKey id, bool includeDetails = true, CancellationToken cancellationToken = default)
{
return await GetByIdAsync(id);
}
public async Task<TEntity> GetAsync(TKey id, bool includeDetails = true, CancellationToken cancellationToken = default)
{
return await GetByIdAsync(id);
}
}
}

View File

@@ -0,0 +1,239 @@
using System.Reflection;
using System.Text;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using SqlSugar;
using Volo.Abp;
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;
using Yi.Framework.SqlSugarCore.Abstractions;
namespace Yi.Framework.SqlSugarCore
{
public class SqlSugarDbContext : ISqlSugarDbContext
{
/// <summary>
/// SqlSugar 客户端
/// </summary>
public ISqlSugarClient SqlSugarClient { get; }
public ICurrentUser CurrentUser => LazyServiceProvider.GetRequiredService<ICurrentUser>();
private IAbpLazyServiceProvider LazyServiceProvider { get; }
private IGuidGenerator GuidGenerator => LazyServiceProvider.LazyGetRequiredService<IGuidGenerator>();
protected ILoggerFactory Logger => LazyServiceProvider.LazyGetRequiredService<ILoggerFactory>();
private ICurrentTenant CurrentTenant => LazyServiceProvider.LazyGetRequiredService<ICurrentTenant>();
public IDataFilter DataFilter => LazyServiceProvider.LazyGetRequiredService<IDataFilter>();
protected virtual bool IsMultiTenantFilterEnabled => DataFilter?.IsEnabled<IMultiTenant>() ?? false;
protected virtual bool IsSoftDeleteFilterEnabled => DataFilter?.IsEnabled<ISoftDelete>() ?? false;
public IEntityChangeEventHelper EntityChangeEventHelper => LazyServiceProvider.LazyGetService<IEntityChangeEventHelper>(NullEntityChangeEventHelper.Instance);
protected DbConnOptions Options => LazyServiceProvider.LazyGetRequiredService<IOptions<DbConnOptions>>().Value;
public SqlSugarDbContext(IAbpLazyServiceProvider lazyServiceProvider)
{
LazyServiceProvider = lazyServiceProvider;
var dbConnOptions = Options;
#region options
if (dbConnOptions.DbType is null)
{
throw new ArgumentException("DbType配置为空");
}
var slavaConFig = new List<SlaveConnectionConfig>();
if (dbConnOptions.EnabledReadWrite)
{
if (dbConnOptions.ReadUrl is null)
{
throw new ArgumentException("读写分离为空");
}
var readCon = dbConnOptions.ReadUrl;
readCon.ForEach(s =>
{
//如果是动态saas分库这里的连接串都不能写死需要动态添加这里只配置共享库的连接
slavaConFig.Add(new SlaveConnectionConfig() { ConnectionString = s });
});
}
#endregion
SqlSugarClient = new SqlSugarClient(new ConnectionConfig()
{
//准备添加分表分库
DbType = dbConnOptions.DbType ?? DbType.Sqlite,
ConnectionString = dbConnOptions.Url,
IsAutoCloseConnection = true,
SlaveConnectionConfigs = slavaConFig,
//设置codefirst非空值判断
ConfigureExternalServices = new ConfigureExternalServices
{
EntityService = (c, p) =>
{
if (new NullabilityInfoContext()
.Create(c).WriteState is NullabilityState.Nullable)
{
p.IsNullable = true;
}
}
}
},
db =>
{
db.Aop.DataExecuting = DataExecuting;
db.Aop.DataExecuted = DataExecuted;
db.Aop.OnLogExecuting = OnLogExecuting;
db.Aop.OnLogExecuted = OnLogExecuted;
//扩展
OnSqlSugarClientConfig(db);
});
}
/// <summary>
/// 上下文对象扩展
/// </summary>
/// <param name="sqlSugarClient"></param>
protected virtual void OnSqlSugarClientConfig(ISqlSugarClient sqlSugarClient)
{
//需自定义扩展
if (IsSoftDeleteFilterEnabled)
{
sqlSugarClient.QueryFilter.AddTableFilter<ISoftDelete>(u => u.IsDeleted == false);
}
if (IsMultiTenantFilterEnabled)
{
sqlSugarClient.QueryFilter.AddTableFilter<IMultiTenant>(u => u.TenantId == GuidGenerator.Create());
}
CustomDataFilter();
}
protected virtual void CustomDataFilter()
{
}
protected virtual void DataExecuted(object oldValue, DataAfterModel entityInfo)
{
}
/// <summary>
/// 数据
/// </summary>
/// <param name="oldValue"></param>
/// <param name="entityInfo"></param>
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 != null)
{
entityInfo.SetValue(CurrentUser.Id);
}
}
break;
case DataFilterType.InsertByObject:
if (entityInfo.PropertyName.Equals(nameof(IEntity<Guid>.Id)))
{
//主键为空或者为默认最小值
if (Guid.Empty.Equals(oldValue))
{
entityInfo.SetValue(GuidGenerator.Create());
}
}
if (entityInfo.PropertyName.Equals(nameof(IAuditedObject.CreationTime)))
{
//为空或者为默认最小值
if (oldValue is null || DateTime.MinValue.Equals((DateTime)oldValue))
{
entityInfo.SetValue(DateTime.Now);
}
}
if (entityInfo.PropertyName.Equals(nameof(IAuditedObject.CreatorId)))
{
if (CurrentUser != 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<object>.Id))
{
EntityChangeEventHelper.PublishEntityCreatedEvent(entityInfo.EntityValue);
}
break;
case DataFilterType.UpdateByObject:
if (entityInfo.PropertyName == nameof(IEntity<object>.Id))
{
EntityChangeEventHelper.PublishEntityUpdatedEvent(entityInfo.EntityValue);
}
break;
case DataFilterType.DeleteByObject:
if (entityInfo.PropertyName == nameof(IEntity<object>.Id))
{
EntityChangeEventHelper.PublishEntityDeletedEvent(entityInfo.EntityValue);
}
break;
}
}
/// <summary>
/// 日志
/// </summary>
/// <param name="sql"></param>
/// <param name="pars"></param>
protected virtual void OnLogExecuting(string sql , SugarParameter[] pars)
{
if (Options.EnabledSqlLog)
{
Logger.CreateLogger<SqlSugarDbContext>().LogDebug(UtilMethods.GetSqlString(DbType.SqlServer, sql, pars));
}
}
/// <summary>
/// 日志
/// </summary>
/// <param name="sql"></param>
/// <param name="pars"></param>
protected virtual void OnLogExecuted(string sql, SugarParameter[] pars)
{
}
}
}

View File

@@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Auditing;
using Volo.Abp.DependencyInjection;
namespace Yi.Framework.SqlSugarCore
{
public class SqlSugarLogAuditingStore : IAuditingStore, ISingletonDependency
{
public Task SaveAsync(AuditLogInfo auditInfo)
{
Console.WriteLine(auditInfo.ExecutionTime);
return Task.CompletedTask;
}
}
}

View File

@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Yi.Framework.SqlSugarCore.Abstractions;
namespace Yi.Framework.SqlSugarCore
{
public static class SqlsugarCoreExtensions
{
public static IServiceCollection AddYiDbContext<DbContext>(this IServiceCollection service) where DbContext : class, ISqlSugarDbContext
{
service.Replace(new ServiceDescriptor(typeof(ISqlSugarDbContext), typeof(DbContext), ServiceLifetime.Scoped));
return service;
}
public static IServiceCollection AddYiDbContext<DbContext>(this IServiceCollection service,Action<DbConnOptions> options) where DbContext : class, ISqlSugarDbContext
{
service.Configure<DbConnOptions>(ops => {
options.Invoke(ops);
});
service.AddYiDbContext<DbContext>();
return service;
}
}
}

View File

@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Uow;
using Yi.Framework.SqlSugarCore.Abstractions;
namespace Yi.Framework.SqlSugarCore.Uow
{
public class SqlSugarDatabaseApi : IDatabaseApi
{
public ISqlSugarDbContext DbContext { get; }
public SqlSugarDatabaseApi(ISqlSugarDbContext dbContext)
{
DbContext = dbContext;
}
}
}

View File

@@ -0,0 +1,38 @@
using Volo.Abp.Uow;
using Yi.Framework.SqlSugarCore.Abstractions;
namespace Yi.Framework.SqlSugarCore.Uow
{
public class SqlSugarTransactionApi : ITransactionApi, ISupportsRollback
{
private ISqlSugarDbContext _sqlsugarDbContext;
public SqlSugarTransactionApi(ISqlSugarDbContext sqlsugarDbContext)
{
_sqlsugarDbContext = sqlsugarDbContext;
}
public async Task CommitAsync(CancellationToken cancellationToken = default)
{
await Console.Out.WriteLineAsync("事务提交");
Console.WriteLine(_sqlsugarDbContext.SqlSugarClient.ContextID + "---------------");
await _sqlsugarDbContext.SqlSugarClient.Ado.CommitTranAsync();
}
public void Dispose()
{
Console.WriteLine("Dispose");
}
public async Task RollbackAsync(CancellationToken cancellationToken = default)
{
await Console.Out.WriteLineAsync("事务回滚");
Console.WriteLine(_sqlsugarDbContext.SqlSugarClient.ContextID);
await _sqlsugarDbContext.SqlSugarClient.Ado.RollbackTranAsync();
}
}
}

View File

@@ -0,0 +1,134 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Logging;
using Volo.Abp.Data;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Threading;
using Volo.Abp.Uow;
using Volo.Abp;
using Microsoft.Extensions.DependencyInjection;
using SqlSugar;
using Yi.Framework.SqlSugarCore.Abstractions;
namespace Yi.Framework.SqlSugarCore.Uow
{
public class UnitOfWorkSqlsugarDbContextProvider<TDbContext> : ISugarDbContextProvider<TDbContext> where TDbContext : ISqlSugarDbContext
{
public ILogger<UnitOfWorkSqlsugarDbContextProvider<TDbContext>> Logger { get; set; }
protected readonly IUnitOfWorkManager UnitOfWorkManager;
protected readonly IConnectionStringResolver ConnectionStringResolver;
protected readonly ICancellationTokenProvider CancellationTokenProvider;
protected readonly ICurrentTenant CurrentTenant;
public UnitOfWorkSqlsugarDbContextProvider(
IUnitOfWorkManager unitOfWorkManager,
IConnectionStringResolver connectionStringResolver,
ICancellationTokenProvider cancellationTokenProvider,
ICurrentTenant currentTenant
)
{
UnitOfWorkManager = unitOfWorkManager;
ConnectionStringResolver = connectionStringResolver;
CancellationTokenProvider = cancellationTokenProvider;
CurrentTenant = currentTenant;
Logger = NullLogger<UnitOfWorkSqlsugarDbContextProvider<TDbContext>>.Instance;
}
public virtual async Task<TDbContext> GetDbContextAsync()
{
var unitOfWork = UnitOfWorkManager.Current;
if (unitOfWork == null)
{
throw new AbpException("A DbContext can only be created inside a unit of work!");
}
//var sss= unitOfWork.ServiceProvider.GetRequiredService<TDbContext>();
//Console.WriteLine("反户的:"+sss.SqlSugarClient.ContextID);
//return sss;
var connectionStringName = "Default";
var connectionString = await ResolveConnectionStringAsync(connectionStringName);
// var dbContextKey = $"{this.GetType().FullName}_{connectionString}";
var dbContextKey = "Default";
var databaseApi = unitOfWork.FindDatabaseApi(dbContextKey);
if (databaseApi == null)
{
databaseApi = new SqlSugarDatabaseApi(
await CreateDbContextAsync(unitOfWork, connectionStringName, connectionString)
);
unitOfWork.AddDatabaseApi(dbContextKey, databaseApi);
}
return (TDbContext)((SqlSugarDatabaseApi)databaseApi).DbContext; ;
}
protected virtual async Task<TDbContext> CreateDbContextAsync(IUnitOfWork unitOfWork, string connectionStringName, string connectionString)
{
var dbContext = await CreateDbContextAsync(unitOfWork);
Console.WriteLine("111111" + dbContext.SqlSugarClient.ContextID);
return dbContext;
}
protected virtual async Task<TDbContext> CreateDbContextAsync(IUnitOfWork unitOfWork)
{
return unitOfWork.Options.IsTransactional
? await CreateDbContextWithTransactionAsync(unitOfWork)
: unitOfWork.ServiceProvider.GetRequiredService<TDbContext>();
}
protected virtual async Task<TDbContext> CreateDbContextWithTransactionAsync(IUnitOfWork unitOfWork)
{
var transactionApiKey = $"Sqlsugar_Default".ToString();
var activeTransaction = unitOfWork.FindTransactionApi(transactionApiKey) as SqlSugarDatabaseApi;
if (activeTransaction == null)
{
var dbContext = unitOfWork.ServiceProvider.GetRequiredService<TDbContext>();
var transaction = new SqlSugarTransactionApi(
dbContext
);
unitOfWork.AddTransactionApi(transactionApiKey, transaction);
await Console.Out.WriteLineAsync("开始新的事务");
Console.WriteLine(dbContext.SqlSugarClient.ContextID);
await dbContext.SqlSugarClient.Ado.BeginTranAsync();
return dbContext;
}
else
{
await Console.Out.WriteLineAsync("继续老的事务");
Console.WriteLine(activeTransaction.DbContext.SqlSugarClient);
await activeTransaction.DbContext.SqlSugarClient.Ado.BeginTranAsync();
return (TDbContext)activeTransaction.DbContext;
}
}
protected virtual async Task<string> ResolveConnectionStringAsync(string connectionStringName)
{
if (typeof(TDbContext).IsDefined(typeof(IgnoreMultiTenancyAttribute), false))
{
using (CurrentTenant.Change(null))
{
return await ConnectionStringResolver.ResolveAsync(connectionStringName);
}
}
return await ConnectionStringResolver.ResolveAsync(connectionStringName);
}
}
}

View File

@@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\common.props" />
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="SqlSugarCore" Version="5.1.4.124" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Yi.Framework.SqlSugarCore.Abstractions\Yi.Framework.SqlSugarCore.Abstractions.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,92 @@
<?xml version="1.0"?>
<doc>
<assembly>
<name>Yi.Framework.SqlSugarCore</name>
</assembly>
<members>
<member name="P:Yi.Framework.SqlSugarCore.DbConnOptions.Url">
<summary>
连接字符串,必填
</summary>
</member>
<member name="P:Yi.Framework.SqlSugarCore.DbConnOptions.DbType">
<summary>
数据库类型
</summary>
</member>
<member name="P:Yi.Framework.SqlSugarCore.DbConnOptions.EnabledDbSeed">
<summary>
开启种子数据
</summary>
</member>
<member name="P:Yi.Framework.SqlSugarCore.DbConnOptions.EnabledReadWrite">
<summary>
开启读写分离
</summary>
</member>
<member name="P:Yi.Framework.SqlSugarCore.DbConnOptions.EnabledCodeFirst">
<summary>
开启codefirst
</summary>
</member>
<member name="P:Yi.Framework.SqlSugarCore.DbConnOptions.EnabledSqlLog">
<summary>
开启sql日志
</summary>
</member>
<member name="P:Yi.Framework.SqlSugarCore.DbConnOptions.EntityAssembly">
<summary>
实体程序集
</summary>
</member>
<member name="P:Yi.Framework.SqlSugarCore.DbConnOptions.ReadUrl">
<summary>
读写分离
</summary>
</member>
<member name="M:Yi.Framework.SqlSugarCore.Repositories.SqlSugarRepository`1.GetDbContextAsync">
<summary>
获取DB
</summary>
<returns></returns>
</member>
<member name="M:Yi.Framework.SqlSugarCore.Repositories.SqlSugarRepository`1.GetDbSimpleClientAsync">
<summary>
获取简单Db
</summary>
<returns></returns>
</member>
<member name="P:Yi.Framework.SqlSugarCore.SqlSugarDbContext.SqlSugarClient">
<summary>
SqlSugar 客户端
</summary>
</member>
<member name="M:Yi.Framework.SqlSugarCore.SqlSugarDbContext.OnSqlSugarClientConfig(SqlSugar.ISqlSugarClient)">
<summary>
上下文对象扩展
</summary>
<param name="sqlSugarClient"></param>
</member>
<member name="M:Yi.Framework.SqlSugarCore.SqlSugarDbContext.DataExecuting(System.Object,SqlSugar.DataFilterModel)">
<summary>
数据
</summary>
<param name="oldValue"></param>
<param name="entityInfo"></param>
</member>
<member name="M:Yi.Framework.SqlSugarCore.SqlSugarDbContext.OnLogExecuting(System.String,SqlSugar.SugarParameter[])">
<summary>
日志
</summary>
<param name="sql"></param>
<param name="pars"></param>
</member>
<member name="M:Yi.Framework.SqlSugarCore.SqlSugarDbContext.OnLogExecuted(System.String,SqlSugar.SugarParameter[])">
<summary>
日志
</summary>
<param name="sql"></param>
<param name="pars"></param>
</member>
</members>
</doc>

View File

@@ -0,0 +1,97 @@
using System.Reflection;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
using SqlSugar;
using Volo.Abp;
using Volo.Abp.Auditing;
using Volo.Abp.Data;
using Volo.Abp.Domain;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Modularity;
using Yi.Framework.SqlSugarCore.Abstractions;
using Yi.Framework.SqlSugarCore.Repositories;
using Yi.Framework.SqlSugarCore.Uow;
namespace Yi.Framework.SqlSugarCore
{
[DependsOn(typeof(AbpDddDomainModule))]
public class YiFrameworkSqlSugarCoreModule : AbpModule
{
public override Task ConfigureServicesAsync(ServiceConfigurationContext context)
{
var service = context.Services;
var configuration = service.GetConfiguration();
Configure<DbConnOptions>(configuration.GetSection("DbConnOptions"));
service.TryAddScoped<ISqlSugarDbContext, SqlSugarDbContext>();
//不开放sqlsugarClient
//service.AddTransient<ISqlSugarClient>(x => x.GetRequiredService<ISqlsugarDbContext>().SqlSugarClient);
service.AddTransient(typeof(IRepository<>), typeof(SqlSugarRepository<>));
service.AddTransient(typeof(IRepository<,>), typeof(SqlSugarRepository<,>));
service.AddTransient(typeof(ISqlSugarRepository<>), typeof(SqlSugarRepository<>));
service.AddTransient(typeof(ISqlSugarRepository<,>), typeof(SqlSugarRepository<,>));
service.AddTransient<IAuditingStore, SqlSugarLogAuditingStore>();
service.AddTransient(typeof(ISugarDbContextProvider<>), typeof(UnitOfWorkSqlsugarDbContextProvider<>));
return Task.CompletedTask;
}
public override Task OnApplicationInitializationAsync(ApplicationInitializationContext context)
{
var service = context.ServiceProvider;
return base.OnApplicationInitializationAsync(context);
}
public override async void OnPreApplicationInitialization(ApplicationInitializationContext context)
{
//进行CodeFirst
var service = context.ServiceProvider;
var options = service.GetRequiredService<IOptions<DbConnOptions>>().Value;
if (options.EnabledCodeFirst)
{
CodeFirst(service);
}
if (options.EnabledCodeFirst)
{
await DataSeedAsync(service);
}
}
private void CodeFirst(IServiceProvider service)
{
var options = service.GetRequiredService<IOptions<DbConnOptions>>().Value;
if (options.EnabledCodeFirst)
{
var moduleContainer = service.GetRequiredService<IModuleContainer>();
var db = service.GetRequiredService<ISqlSugarDbContext>().SqlSugarClient;
List<Type> types = new List<Type>();
foreach (var module in moduleContainer.Modules)
{
types.AddRange(module.Assembly.GetTypes().Where(x => x.GetCustomAttribute<SugarTable>() != null).Where(x => x.GetCustomAttribute<SplitTableAttribute>() is null));
}
if (types.Count > 0)
{
db.CodeFirst.InitTables(types.ToArray());
}
}
}
private async Task DataSeedAsync(IServiceProvider service)
{
var dataSeeder = service.GetRequiredService<IDataSeeder>();
await dataSeeder.SeedAsync();
}
}
}