Vol/Net6.SqlSugar/VOL.Core/BaseProvider/RepositoryBase.cs

555 lines
22 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.

using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.EntityFrameworkCore.Storage;
using OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Threading.Tasks;
using VOL.Core.DbContext;
using VOL.Core.DBManager;
using VOL.Core.DbSqlSugar;
using VOL.Core.Enums;
using VOL.Core.Extensions;
using VOL.Core.Utilities;
using VOL.Entity;
using VOL.Entity.SystemModels;
namespace VOL.Core.BaseProvider
{
public abstract class RepositoryBase<TEntity> where TEntity : BaseEntity, new()
{
public RepositoryBase(VOLContext dbContext)
{
this.DefaultDbContext = dbContext;
}
private VOLContext DefaultDbContext { get; set; }
public VOLContext VOLContext
{
get
{
return DefaultDbContext;
}
}
public virtual ISqlSugarClient DbContext
{
get { return DefaultDbContext.SqlSugarClient; }
}
public virtual ISqlSugarClient SqlSugarClient
{
get
{
return DefaultDbContext.SqlSugarClient;
}
}
private ISugarQueryable<TEntity> DBSet
{
get { return VOLContext.Set<TEntity>(); }
}
/// <summary>
/// 执行事务
/// </summary>
/// <param name="action">如果返回false则回滚事务(可自行定义规则)</param>
/// <returns></returns>
public virtual WebResponseContent DbContextBeginTransaction(Func<WebResponseContent> action)
{
WebResponseContent webResponse = new WebResponseContent();
try
{
DbContext.Ado.BeginTran();
webResponse = action();
if (webResponse.Status)
{
DbContext.Ado.CommitTran();
}
else
{
DbContext.Ado.RollbackTran();
}
return webResponse;
}
catch (Exception ex)
{
DbContext.Ado.RollbackTran();
return new WebResponseContent().Error(ex.Message + ex.InnerException + ex.StackTrace);
}
}
public virtual bool Exists<TExists>(Expression<Func<TExists, bool>> predicate, bool filterDeleted = true) where TExists : class
{
return VOLContext.Set<TExists>(filterDeleted).Any(predicate);
}
public virtual Task<bool> ExistsAsync<TExists>(Expression<Func<TExists, bool>> predicate, bool filterDeleted = true) where TExists : class
{
return VOLContext.Set<TExists>(filterDeleted).AnyAsync(predicate);
}
public virtual bool Exists(Expression<Func<TEntity, bool>> predicate, bool filterDeleted = true)
{
return VOLContext.Set<TEntity>(filterDeleted).Any(predicate);
}
public virtual Task<bool> ExistsAsync(Expression<Func<TEntity, bool>> predicate, bool filterDeleted = true)
{
return VOLContext.Set<TEntity>(filterDeleted).AnyAsync(predicate);
}
public virtual ISugarQueryable<TEntity> WhereIF(bool checkCondition, Expression<Func<TEntity, bool>> predicate)
{
if (checkCondition)
{
return VOLContext.Set<TEntity>().Where(predicate);
}
return VOLContext.Set<TEntity>();
}
public virtual ISugarQueryable<T> WhereIF<T>(bool checkCondition, Expression<Func<T, bool>> predicate) where T : class
{
if (checkCondition)
{
return VOLContext.Set<T>().Where(predicate);
}
return VOLContext.Set<T>();
}
public virtual List<TFind> Find<TFind>(Expression<Func<TFind, bool>> predicate, bool filterDeleted = true) where TFind : class
{
return VOLContext.Set<TFind>(filterDeleted).Where(predicate).ToList();
}
public virtual Task<TFind> FindAsyncFirst<TFind>(Expression<Func<TFind, bool>> predicate, bool filterDeleted = true) where TFind : class
{
return FindAsISugarQueryable(predicate, filterDeleted).FirstOrDefaultAsync();
}
public virtual Task<TEntity> FindAsyncFirst(Expression<Func<TEntity, bool>> predicate, bool filterDeleted = true)
{
return FindAsISugarQueryable<TEntity>(predicate, filterDeleted).FirstOrDefaultAsync();
}
public virtual Task<List<TFind>> FindAsync<TFind>(Expression<Func<TFind, bool>> predicate, bool filterDeleted = true) where TFind : class
{
return FindAsISugarQueryable<TFind>(predicate, filterDeleted).ToListAsync();
}
public virtual Task<List<TEntity>> FindAsync(Expression<Func<TEntity, bool>> predicate, bool filterDeleted = true)
{
return FindAsISugarQueryable(predicate, filterDeleted).ToListAsync();
}
public virtual Task<TEntity> FindFirstAsync(Expression<Func<TEntity, bool>> predicate, bool filterDeleted = true)
{
return FindAsISugarQueryable(predicate, filterDeleted).FirstOrDefaultAsync();
}
public virtual Task<List<T>> FindAsync<T>(Expression<Func<TEntity, bool>> predicate, Expression<Func<TEntity, T>> selector, bool filterDeleted = true)
{
return FindAsISugarQueryable(predicate, filterDeleted).Select(selector).ToListAsync();
}
public virtual Task<T> FindFirstAsync<T>(Expression<Func<TEntity, bool>> predicate, Expression<Func<TEntity, T>> selector, bool filterDeleted = true)
{
return FindAsISugarQueryable(predicate, filterDeleted).Select(selector).FirstOrDefaultAsync();
}
private ISugarQueryable<TFind> FindAsISugarQueryable<TFind>(Expression<Func<TFind, bool>> predicate, bool filterDeleted = true) where TFind : class
{
return VOLContext.Set<TFind>(filterDeleted).Where(predicate);
}
public virtual List<T> Find<T>(Expression<Func<TEntity, bool>> predicate, Expression<Func<TEntity, T>> selector, bool filterDeleted = true)
{
return VOLContext.Set<TEntity>(filterDeleted).Where(predicate).Select(selector).ToList();
}
/// <summary>
/// 单表查询
/// </summary>
/// <param name="predicate"></param>
/// <returns></returns>
public virtual List<TEntity> Find(Expression<Func<TEntity, bool>> predicate, bool filterDeleted = true)
{
return FindAsISugarQueryable(predicate, filterDeleted).ToList();
}
/// <summary>
///
/// </summary>
/// <param name="predicate"></param>
/// <param name=""></param>
/// <param name="orderBy">排序字段</param>
/// <returns></returns>
public virtual TEntity FindFirst(Expression<Func<TEntity, bool>> predicate, bool filterDeleted = true)
{
return VOLContext.Set<TEntity>(filterDeleted).Where(predicate).FirstOrDefault();
}
public ISugarQueryable<TEntity> FindAsIQueryable(Expression<Func<TEntity, bool>> predicate, Expression<Func<TEntity, Dictionary<object, QueryOrderBy>>> orderBy = null)
{
//if (orderBy != null)
// return DbContext.Set<TEntity>().Where(predicate).GetISugarQueryableOrderBy(orderBy.GetExpressionToDic());
return DbContext.Set<TEntity>().Where(predicate);
}
public ISugarQueryable<TEntity> Include<TProperty>(Expression<Func<TEntity, TProperty>> incluedProperty)
{
return DbContext.Set<TEntity>().Includes(incluedProperty);
}
/// <summary>
/// 通过条件查询返回指定列的数据(将TEntity映射到匿名或实体T)
///var result = Sys_UserRepository.GetInstance.Find(x => x.UserName == loginInfo.userName, p => new { uname = p.UserName });
/// <summary>
///
/// </summary>
/// <typeparam name="TKey"></typeparam>
/// <param name="pageIndex"></param>
/// <param name="pagesize"></param>
/// <param name="rowcount"></param>
/// <param name="predicate">查询条件</param>
/// <param name="orderBySelector">多个排序字段key为字段value为升序/降序</param>
/// <returns></returns>
public virtual ISugarQueryable<TFind> IQueryablePage<TFind>(int pageIndex, int pagesize, out int rowcount, Expression<Func<TFind, bool>> predicate, Expression<Func<TEntity, Dictionary<object, QueryOrderBy>>> orderBy, bool returnRowCount = true) where TFind : class
{
pageIndex = pageIndex <= 0 ? 1 : pageIndex;
pagesize = pagesize <= 0 ? 10 : pagesize;
if (predicate == null)
{
predicate = x => 1 == 1;
}
var _db = DbContext.Set<TFind>();
rowcount = returnRowCount ? _db.Count(predicate) : 0;
return DbContext.Set<TFind>().Where(predicate)
.GetISugarQueryableOrderBy(orderBy.GetExpressionToDic())
.Skip((pageIndex - 1) * pagesize)
.Take(pagesize);
}
/// <summary>
/// 分页排序
/// </summary>
/// <param name="queryable"></param>
/// <param name="pageIndex"></param>
/// <param name="pagesize"></param>
/// <param name="rowcount"></param>
/// <param name="orderBy"></param>
/// <returns></returns>
public virtual ISugarQueryable<TEntity> IQueryablePage(ISugarQueryable<TEntity> queryable, int pageIndex, int pagesize, out int rowcount, Dictionary<string, QueryOrderBy> orderBy, bool returnRowCount = true)
{
pageIndex = pageIndex <= 0 ? 1 : pageIndex;
pagesize = pagesize <= 0 ? 10 : pagesize;
rowcount = returnRowCount ? queryable.Count() : 0;
return queryable.GetISugarQueryableOrderBy<TEntity>(orderBy)
.Skip((pageIndex - 1) * pagesize)
.Take(pagesize);
}
/// <summary>
/// 更新表数据
/// </summary>
/// <param name="entity"></param>
/// <param name="saveChanges">是否保存</param>
/// <param name="properties">格式 Expression<Func<entityt, object>> expTree = x => new { x.字段1, x.字段2 };</param>
public virtual int Update(TEntity entity, Expression<Func<TEntity, object>> properties, bool saveChanges = false)
{
return Update<TEntity>(entity, properties, saveChanges);
}
public virtual int Update<TSource>(TSource entity, Expression<Func<TSource, object>> properties, bool saveChanges = false) where TSource : class, new()
{
return UpdateRange<TSource>(new List<TSource>
{
entity
}, properties, saveChanges);
}
public virtual int Update<TSource>(TSource entity, string[] properties, bool saveChanges = false) where TSource : class, new()
{
return UpdateRange<TSource>(new List<TSource>() { entity }, properties, saveChanges);
}
public virtual int Update<TSource>(TSource entity, bool saveChanges = false) where TSource : class, new()
{
return UpdateRange<TSource>(new List<TSource>() { entity }, new string[0], saveChanges);
}
public virtual int UpdateRange<TSource>(IEnumerable<TSource> entities, Expression<Func<TSource, object>> properties, bool saveChanges = false) where TSource : class, new()
{
return UpdateRange<TSource>(entities, properties?.GetExpressionProperty(), saveChanges);
}
public virtual int UpdateRange<TSource>(IEnumerable<TSource> entities, bool saveChanges = false) where TSource : class, new()
{
return UpdateRange<TSource>(entities, new string[0], saveChanges);
}
/// <summary>
/// 更新表数据
/// </summary>
/// <param name="models"></param>
/// <param name="properties">格式 Expression<Func<entityt, object>> expTree = x => new { x.字段1, x.字段2 };</param>
public int UpdateRange<TSource>(IEnumerable<TSource> entities, string[] properties, bool saveChanges = false) where TSource : class, new()
{
return DbContext.UpdateRange(entities, properties, saveChanges);
}
/// <summary>
///
/// </summary>
/// <param name="entity"></param>
/// <param name="updateDetail">是否修改明细</param>
/// <param name="delNotExist">是否删除明细不存在的数据</param>
/// <param name="updateMainFields">主表指定修改字段</param>
/// <param name="updateDetailFields">明细指定修改字段</param>
/// <param name="saveChange">是否保存</param>
/// <returns></returns>
public virtual WebResponseContent UpdateRange<Detail>(TEntity entity,
bool updateDetail = false,
bool delNotExist = false,
Expression<Func<TEntity, object>> updateMainFields = null,
Expression<Func<Detail, object>> updateDetailFields = null,
bool saveChange = false) where Detail : class, new()
{
WebResponseContent webResponse = new WebResponseContent();
Update(entity, updateMainFields);
string message = "";
if (updateDetail)
{
PropertyInfo[] properties = typeof(TEntity).GetProperties();
PropertyInfo detail = properties.Where(x => x.PropertyType.Name == "List`1").ToList().FirstOrDefault();
if (detail != null)
{
PropertyInfo key = properties.GetKeyProperty();
object obj = detail.GetValue(entity);
Type detailType = typeof(TEntity).GetCustomAttribute<EntityAttribute>().DetailTable[0];
message = UpdateDetail<Detail>(obj as List<Detail>, key.Name, key.GetValue(entity), updateDetailFields, delNotExist);
}
}
if (!saveChange) return webResponse.OK();
DbContext.SaveChanges();
return webResponse.OK("修改成功,明细" + message, entity);
}
private string UpdateDetail<TDetail>(List<TDetail> list,
string keyName,
object keyValue,
Expression<Func<TDetail, object>> updateDetailFields = null,
bool delNotExist = false) where TDetail : class, new()
{
if (list == null) return "";
PropertyInfo property = typeof(TDetail).GetKeyProperty();
string detailKeyName = property.Name;
var details = DbContext.Set<TDetail>();
Expression<Func<TDetail, object>> selectExpression = detailKeyName.GetExpression<TDetail, object>();
Expression<Func<TDetail, bool>> whereExpression = keyName.CreateExpression<TDetail>(keyValue, LinqExpressionType.Equal);
//这里有问题, Expression<Func<TDetail, object>>会转换为查询所有字段20231020
//List<object> detailKeys = details.Where(whereExpression).Select(selectExpression).ToList();
List<object> detailKeys = details.Where(whereExpression).ToList().Select(selectExpression.Compile()).ToList();
//获取主键默认值
string keyDefaultVal = property.PropertyType
.Assembly
.CreateInstance(property.PropertyType.FullName).ToString();
int addCount = 0;
int editCount = 0;
int delCount = 0;
PropertyInfo mainKeyProperty = typeof(TDetail).GetProperty(keyName);
List<object> keys = new List<object>();
list.ForEach(x =>
{
var set = DbContext.Set<TDetail>();
object val = property.GetValue(x);
//主键是默认值的为新增的数据
if (val.ToString() == keyDefaultVal)
{
x.SetCreateDefaultVal();
//设置主表的值,也可以不设置
mainKeyProperty.SetValue(x, keyValue);
DbContext.Insertable(x).AddQueue();
addCount++;
}
else//修改的数据
{
//获取所有修改的key,如果从数据库查来的key,不在修改中的key则为删除的数据
keys.Add(val);
x.SetModifyDefaultVal();
Update<TDetail>(x, updateDetailFields);
// repository.DbContext.Entry<TDetail>(x).State = EntityState.Modified;
editCount++;
}
});
//删除
if (delNotExist)
{
detailKeys.Where(x => !keys.Contains(x)).ToList().ForEach(d =>
{
delCount++;
TDetail detail = Activator.CreateInstance<TDetail>();
property.SetValue(detail, d);
DbContext.Deleteable<TDetail>(detail).AddQueue();
for (int i = 0; i < list.Count(); i++)
{
if (property.GetValue(list[i]) == d)
{
list.RemoveAt(i);
}
}
});
}
return $"修改[{editCount}]条,新增[{addCount}]条,删除[{delCount}]条";
}
public virtual void Delete(TEntity model, bool saveChanges = false)
{
DbContext.Deleteable(model).AddQueue();
if (saveChanges)
{
DbContext.SaveChanges();
}
}
public virtual void Delete<T>(T model, bool saveChanges) where T : class, new()
{
DbContext.Deleteable(model).AddQueue();
if (saveChanges)
{
DbContext.SaveChanges();
}
}
/// <summary>
/// 通过主键批量删除
/// </summary>
/// <param name="keys">主键key</param>
/// <param name="delList">是否连明细一起删除</param>
/// <returns></returns>
public virtual int DeleteWithKeys(object[] keys, bool saveChange = false)
{
var keyPro = typeof(TEntity).GetKeyProperty();
foreach (var key in keys.Distinct())
{
TEntity entity = Activator.CreateInstance<TEntity>();
keyPro.SetValue(entity, key.ChangeType(keyPro.PropertyType));
DbContext.Deleteable(entity).AddQueue();
// DbContext.Entry<TEntity>(entity).State = EntityState.Deleted;
}
if (saveChange)
{
DbContext.SaveChanges();
}
return keys.Length;
}
/// <summary>
/// 写入数据并设置自增
/// </summary>
/// <param name="entity"></param>
public virtual void AddWithSetIdentity(TEntity entity)
{
//var keyProperty = typeof(TEntity).GetKeyProperty();
//int id = DbContext.Insertable(entity).ExecuteReturnIdentity();
//keyProperty.SetValue(id, entity);
DbContext.Insertable(entity).ExecuteReturnEntity();
}
public virtual void AddWithSetIdentity<T>(T entity) where T : class, new()
{
DbContext.Insertable(entity).ExecuteReturnEntity();
}
public virtual void Add(TEntity entities, bool saveChanges = false)
{
AddRange(new List<TEntity>() { entities }, saveChanges);
}
public virtual void Add<T>(T entities, bool saveChanges = false) where T : class, new()
{
DbContext.Insertable(entities).AddQueue();
if (saveChanges) DbContext.SaveChanges();
}
public virtual void AddRange(List<TEntity> entities, bool saveChanges = false)
{
DbContext.Insertable(entities).AddQueue();
//DbContext.Insertable(entities).ExecuteReturnIdentity();
if (saveChanges) DbContext.SaveChanges();
}
public virtual void AddRange<T>(List<T> entities, bool saveChanges = false) where T : class, new()
{
DbContext.Insertable(entities).AddQueue();
if (saveChanges) DbContext.SaveChanges();
}
public virtual int SaveChanges()
{
return VOLContext.SaveChanges();
}
public virtual Task<int> SaveChangesAsync()
{
return VOLContext.SqlSugarClient.SaveChangesAsync();
}
public virtual int ExecuteSqlCommand(string sql, params SugarParameter[] SugarParameters)
{
return DbContext.Ado.ExecuteCommand(sql, SugarParameters);
// return DbContext.Database.ExecuteSqlRaw(sql, SugarParameters);
}
public virtual List<TEntity> FromSql(string sql, params SugarParameter[] SugarParameters)
{
return DbContext.Ado.SqlQuery<TEntity>(sql, SugarParameters).ToList();
}
/// <summary>
/// 执行sql
/// 使用方式 FormattableString sql=$"select * from xx where name ={xx} and pwd={xx1} "
/// FromSqlInterpolated内部处理sql注入的问题直接在{xx}写对应的值即可
/// 注意sql必须 select * 返回所有TEntity字段
/// </summary>
/// <param name="formattableString"></param>
/// <returns></returns>
//public virtual ISugarQueryable<TEntity> FromSqlInterpolated([NotNull] FormattableString sql)
//{
// //DBSet.FromSqlInterpolated(sql).Select(x => new { x,xxx}).ToList();
// return DbContext.Ado.SqlQuery<TEntity>(sql);
//}
/// <summary>
/// 取消上下文跟踪
/// </summary>
/// <param name="entity"></param>
public virtual void Detached(TEntity entity)
{
// DbContext.Entry(entity).State = EntityState.Detached;
}
public virtual void DetachedRange(IEnumerable<TEntity> entities)
{
//foreach (var entity in entities)
//{
// DbContext.Entry(entity).State = EntityState.Detached;
//}
}
}
}