JKFZJCXT/BZPT.SqlSugarRepository/RepositoryBase.cs

496 lines
17 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/***********************************************************
**项目名称:
**功能描述: 仓储 的摘要说明
**作 者: 易栋梁
**版 本 号: 1.0
**创建日期: 2015/12/7 16:06:56
**修改历史:
************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using SqlSugar;
using Microsoft.AspNetCore.Http;
using System.Security.Claims;
using System.Text;
using NPlatform.Infrastructure.IdGenerators;
using NPlatform.Filters;
using System.DirectoryServices;
using DevExtreme.AspNet.Data;
namespace BZPT.Repositories
{
/// <summary>
/// 聚合仓储基类
/// </summary>
/// <typeparam name="TEntity">实体类型</typeparam>
/// <typeparam name="string">主键类型</typeparam>
public abstract class RepositoryBase<TEntity> : ResultHelper, IRepository<TEntity, string>, IRepositorySugarBase<TEntity, string> where TEntity : EntityBase<string>, new()
{
[Autowired]
public ILogger<RepositoryBase<TEntity>> loggerSvc { get; set; }
[Autowired]
public IHttpContextAccessor httpContextAccessor { get; set; }
protected IRepositoryOptions Options;
/// <summary>
/// 数据库连接承载对象,默认注入基础库,管理所有的租户连接。
/// </summary>
protected DBContext ContextManage;
// 构造函数
public RepositoryBase(DBContext dbContext)
{
ContextManage = dbContext ?? throw new ArgumentNullException(nameof(dbContext));
}
public string? GetUserId()
{
return httpContextAccessor.HttpContext?.User?.FindFirst(ClaimTypes.NameIdentifier)?.Value;
}
public string? GetUserName()
{
return httpContextAccessor.HttpContext?.User?.Identity?.Name;
}
public ISqlSugarClient DbDefault
{
get
{
return ContextManage;
}
}
/// <summary>
/// 获取业务库对象
/// </summary>
public ISqlSugarClient Db
{
get
{
var tenantId = httpContextAccessor.HttpContext?.User?.Claims?.Where(t => t.Type.ToUpper() =="TENANTID").FirstOrDefault()?.Value;
var connection = ContextManage.GetConnection("default");
if (!string.IsNullOrWhiteSpace(tenantId))
{
var tenant = ContextManage.GetConnection("default").Queryable<BZPT.Domains.Entity.Sys.Tenant>().Where(t => t.Id == tenantId).First();
var configId = tenantId;//集团ID也可以叫租户ID
if (!ContextManage.IsAnyConnection(configId))
{ //用非默认ConfigId进行测试
//添加业务库只在当前上下文有效原理SqlSugarScope模式入门文档去看
ContextManage.AddConnection(new ConnectionConfig()
{
ConfigId = configId,
ConnectionString = tenant.ConnectionString,
DbType = Enum.Parse<DbType>(tenant.DbType, true),
IsAutoCloseConnection = true
});
}
//原理说明
//IsAnyConnection、AddConnection和GetConnection 都是Scope周期不同请求不会有影响
connection = ContextManage.GetConnection(configId);
//可以给业务库result设置AOP和过滤滤器
}
// connection.QueryFilter.AddTableFilter<ILogicDelete>(it => it.IsDeleted == false);
//// 应用过滤器
//foreach (var ft in this.Options.QueryFilters)
//{
// var exp = ft.Value.GetFilter<TEntity>();
// if (exp != null)
// {
// connection.QueryFilter.AddTableFilter<TEntity>(exp);
// }
//}
return connection;
}
}
public TEntity this[string key]
{
get
{
if (EqualityComparer<string>.Default.Equals(key, default(string)))
{
return default(TEntity);
}
return this.Db.Queryable<TEntity>().Where(t => t.Id != null && t.Id.Equals(key)).First();
}
set
{
if (value is null)
{
throw new ArgumentNullException(nameof(value));
}
//功能写法可以将插入和更新拆开,然后调用插入和更新独有特性
var x = Db.Storageable(value).ToStorage();
var rst = x.AsInsertable.ExecuteCommand();//不存在插入
var rst2 = x.AsUpdateable.ExecuteCommand();//存在更新
}
}
/// <summary>
/// Initializes a new instance of the <see cref="RepositoryBase{TEntity,string}"/> class.
/// 仓储基类
/// </summary>
/// <param name="option">
/// 仓储配置
/// </param>
public RepositoryBase(IRepositoryOptions option, DBContext dbContext)
{
Options = option;
ContextManage = dbContext;
}
#region
/// <summary>
/// 异步新增
/// </summary>
/// <param name="items">新增对象的集合</param>
/// <returns><placeholder>A <see cref="Task"/> representing the asynchronous operation.</placeholder></returns>
public async virtual Task<int> AddsAsync(params TEntity[] items)
{
if (items is null)
{
throw new ArgumentNullException(nameof(items));
}
foreach(var item in items)
{
if(string.IsNullOrWhiteSpace(item.Id))
item.Id= StringObjectIdGenerator.Instance.GenerateId().ToString();
}
return await this.Db.Insertable<TEntity>(items).ExecuteCommandAsync();
}
/// <summary>
/// 异步新增
/// </summary>
/// <param name="items">新增对象的集合</param>
/// <returns><placeholder>A <see cref="Task"/> representing the asynchronous operation.</placeholder></returns>
public async virtual Task<int> AddOrUpdate(TEntity item)
{
if (item is null)
{
throw new ArgumentNullException(nameof(item));
}
Db.Ado.CommandTimeOut = 30; // 设置30秒超时
//功能写法可以将插入和更新拆开,然后调用插入和更新独有特性
var x = Db.Storageable(item).ToStorage();
var rst = await x.AsInsertable.ExecuteCommandAsync();//不存在插入
var rst2 = await x.AsUpdateable.ExecuteCommandAsync();//存在更新
return rst + rst2;
}
public virtual async Task<int> RemoveAsync(Expression<Func<TEntity, bool>> filter)
{
if (filter == null) return -1;
if (typeof(TEntity).IsAssignableFrom(typeof(ILogicDelete)))
{
var rst = this.Db.Updateable<TEntity>()
.SetColumns(t => ((ILogicDelete)t).IsDeleted == true)
.Where(filter);
return await rst.ExecuteCommandAsync();
}
else
return await Db.Deleteable<TEntity>().Where(filter).ExecuteCommandAsync();
}
public virtual async Task<int> RemoveAsync(params string[] keys)
{
if (keys == null)
{
throw new ArgumentNullException(nameof(keys));
}
return await this.RemoveAsync(t => keys.Contains(t.Id));
}
public async Task<int> UpdateAsync(TEntity item)
{
return await Db.Updateable<TEntity>(item).ExecuteCommandAsync();
}
public async Task<int> UpdateAsync(Expression<Func<TEntity, TEntity>> columns, Expression<Func<TEntity, bool>> where)
{
return await Db.Updateable<TEntity>()
.SetColumns(columns)//类只能在表达示里面不能提取
.Where(where)
.ExecuteCommandAsync();
}
public async Task<int> UpdatesAsync(List<TEntity> entities, Expression<Func<TEntity, object>> columns)
{
return await Db.Updateable(entities)
.UpdateColumns(columns)
.ExecuteCommandAsync();
}
#endregion
#region
public async virtual Task<bool> ExistsAsync(string key)
{
if (EqualityComparer<string>.Default.Equals(key, default(string)))
{
return false;
}
return await this.Db.Queryable<TEntity>().AnyAsync(t => t.Id != null && t.Id.Equals(key));
}
public async virtual Task<bool> ExistsAsync(Expression<Func<TEntity, bool>> filter)
{
if (filter == null)
{
return false;
}
//// 应用过滤器
//foreach (var ft in this.Options.QueryFilters)
//{
// var exp = ft.Value.GetFilter<TEntity>();
// if (exp != null)
// {
// filter = filter.AndAlso(exp);
// }
//}
return await this.Db.Queryable<TEntity>().AnyAsync(filter);
}
public async Task<IEnumerable<TEntity>> GetAllAsync(IEnumerable<SelectSort<TEntity>> sorts = null)
{
try
{
// 获取可查询对象
var query = ContextManage.Queryable<TEntity>();
// 如果有排序条件,则应用排序
if (sorts != null && sorts.Any())
{
query = query.OrderBy(sorts);
}
Type type = typeof(TEntity);
// 如果实现了ILogicDelete接口且filter不包含IsDeleted条件则添加IsDeleted=false条件
if (typeof(ILogicDelete).IsAssignableFrom(type))
{
query = query.Where(t => ((ILogicDelete)t).IsDeleted == false);
}
// 返回查询结果
return await query.ToListAsync();
}
catch (Exception ex)
{
throw new Exception("无法从数据库中检索数据.", ex);
}
}
public async virtual Task<TEntity> FindByAsync(string key)
{
if (EqualityComparer<string>.Default.Equals(key, default(string)))
{
return default(TEntity);
}
return await this.Db.Queryable<TEntity>().Where(t => t.Id != null && t.Id.Equals(key)).FirstAsync();
}
public async virtual Task<TEntity> GetFirstOrDefaultAsync(Expression<Func<TEntity, bool>> filter)
{
if (filter is null)
{
throw new ArgumentNullException(nameof(filter));
}
return await this.Db.Queryable<TEntity>().Where(filter).FirstAsync();
}
public async virtual Task<IEnumerable<TEntity>> GetListByExpAsync(Expression<Func<TEntity, bool>> filter, IEnumerable<SelectSort<TEntity>> sorts = null)
{
if (filter is null)
{
throw new ArgumentNullException(nameof(filter));
}
Type type = typeof(TEntity);
// 如果实现了ILogicDelete接口且filter不包含IsDeleted条件则添加IsDeleted=false条件
if (typeof(ILogicDelete).IsAssignableFrom(type))
{
if (!filter.ToString().Contains("IsDeleted"))
{
// 动态构建 t.IsDeleted == false 条件
filter = filter.AndAlso(t => ((ILogicDelete)t).IsDeleted == false);
}
}
var setAll = this.Db.Queryable<TEntity>().Where(filter);
if (sorts != null)
setAll = setAll.OrderBy(sorts);
return await setAll.ToListAsync();
}
/// <summary>
/// EF 版本EF实现指定字段查询比较困难所以先查出所有字段
/// </summary>
/// <param name="columnNames"></param>
/// <param name="filter"></param>
/// <param name="sorts"></param>
/// <returns></returns>
public async virtual Task<IEnumerable<TEntity>> GetListWithColumnsAsync(IEnumerable<string> columnNames, Expression<Func<TEntity, bool>> filter, IEnumerable<SelectSort<TEntity>> sorts = null)
{
if (filter is null)
{
throw new ArgumentNullException(nameof(filter));
}
Type type = typeof(TEntity);
// 如果实现了ILogicDelete接口且filter不包含IsDeleted条件则添加IsDeleted=false条件
if (typeof(ILogicDelete).IsAssignableFrom(type))
{
if (!filter.ToString().Contains("IsDeleted"))
{
// 动态构建 t.IsDeleted == false 条件
filter = filter.AndAlso(t => ((ILogicDelete)t).IsDeleted == false);
}
}
var rst = await GetListByExpAsync(filter, sorts);
return rst;
}
public async virtual Task<IListResult<TEntity>> GetPagedAsync(int pageIndex, int pageSize, Expression<Func<TEntity, bool>> filter, IEnumerable<SelectSort<TEntity>> sorts)
{
if (filter is null)
{
throw new ArgumentNullException(nameof(filter));
}
RefAsync<int> total = 0;
Type type = typeof(TEntity);
// 如果实现了ILogicDelete接口且filter不包含IsDeleted条件则添加IsDeleted=false条件
if (typeof(ILogicDelete).IsAssignableFrom(type))
{
if (!filter.ToString().Contains("IsDeleted"))
{
// 动态构建 t.IsDeleted == false 条件
filter = filter.AndAlso(t => ((ILogicDelete)t).IsDeleted == false);
}
}
var resultSet = this.Db.Queryable<TEntity>().Where(filter);
if (sorts != null)
resultSet = resultSet.OrderBy(sorts);
var pageData = await resultSet.ToPageListAsync(pageIndex, pageSize, total);
return base.ListData(pageData, total);
}
public async virtual Task<IListResult<TEntity>> GetPagedAsync(DataSourceLoadOptions loadOptions)
{
var query = this.Db.Queryable<TEntity>();
var datas=await query.LoadAsync(loadOptions);
return datas;
}
#endregion
#region
public async Task<int> CountAsync(Expression<Func<TEntity, bool>> filter)
{
if (filter is null)
{
throw new ArgumentNullException(nameof(filter));
}
return await this.Db.Queryable<TEntity>().CountAsync(filter);
}
public async Task<TValue> MaxAsync<TValue>(Expression<Func<TEntity, TValue>> selector, Expression<Func<TEntity, bool>> filter = null)
{
if (selector is null)
{
throw new ArgumentNullException(nameof(selector));
}
if (filter is null)
{
throw new ArgumentNullException(nameof(filter));
}
return await this.Db.Queryable<TEntity>().Where(filter).MaxAsync(selector);
}
public async Task<TValue> MinAsync<TValue>(Expression<Func<TEntity, TValue>> selector, Expression<Func<TEntity, bool>> filter = null)
{
if (selector is null)
{
throw new ArgumentNullException(nameof(selector));
}
if (filter is null)
{
throw new ArgumentNullException(nameof(filter));
}
return await this.Db.Queryable<TEntity>().Where(filter).MinAsync(selector);
}
public async Task<decimal> SumAsync(Expression<Func<TEntity, decimal>> selector, Expression<Func<TEntity, bool>> filter = null)
{
if (selector is null)
{
throw new ArgumentNullException(nameof(selector));
}
if (filter is null)
{
throw new ArgumentNullException(nameof(filter));
}
return await this.Db.Queryable<TEntity>().Where(filter).SumAsync(selector);
}
public async Task<decimal> AVGAsync(Expression<Func<TEntity, decimal>> selector, Expression<Func<TEntity, bool>> filter = null)
{
if (selector is null)
{
throw new ArgumentNullException(nameof(selector));
}
if (filter is null)
{
throw new ArgumentNullException(nameof(filter));
}
return await this.Db.Queryable<TEntity>().Where(filter).AvgAsync(selector);
}
public Task<int> SaveChangesAsync()
{
throw new NotImplementedException("sqlsugar 不支持");
}
#endregion
}
}