chore: 构建稳定版本
This commit is contained in:
@@ -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; }
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user