457 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C#
		
	
	
			
		
		
	
	
			457 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C#
		
	
	
| 
 | ||
| 
 | ||
| using AutoMapper;
 | ||
| using IRaCIS.Core.Domain.Models;
 | ||
| using IRaCIS.Core.Infrastructure;
 | ||
| using IRaCIS.Core.Infrastructure.Extention;
 | ||
| using Microsoft.EntityFrameworkCore;
 | ||
| using Microsoft.EntityFrameworkCore.ChangeTracking;
 | ||
| using System;
 | ||
| using System.Collections.Generic;
 | ||
| using System.Linq;
 | ||
| using System.Linq.Expressions;
 | ||
| using System.Threading.Tasks;
 | ||
| using IRaCIS.Core.Domain.Share;
 | ||
| 
 | ||
| namespace IRaCIS.Core.Infra.EFCore
 | ||
| {
 | ||
| 
 | ||
|     #region 泛型通用版本
 | ||
| 
 | ||
| 
 | ||
|     public interface IRepository
 | ||
|     {
 | ||
|         IQueryable<T> GetQueryable<T>(bool ignoreQueryFilters = false) where T : Entity;
 | ||
|         DbSet<T> Set<T>() where T : Entity;
 | ||
|         EntityEntry<T> Entry<T>(T t) where T : Entity;
 | ||
| 
 | ||
|         Task<bool> SaveChangesAsync();
 | ||
| 
 | ||
|         IQueryable<T> WhereIf<T>(bool condition, Expression<Func<T, bool>> filter) where T : Entity;
 | ||
| 
 | ||
| 
 | ||
|         Task<bool> AnyAsync<T>(Expression<Func<T, bool>> filter, bool ignoreQueryFilters = false) where T : Entity;
 | ||
| 
 | ||
|         /// <summary>
 | ||
|         ///不跟踪  查询单个实体,不会出现NUll
 | ||
|         /// </summary>
 | ||
|         /// <param name="exp"></param>
 | ||
|         /// <param name="ignoreQueryFilters"></param>
 | ||
|         /// <returns></returns>
 | ||
|         Task<T> FirstAsync<T>(Expression<Func<T, bool>> exp = null, bool isTracking = false, bool ignoreQueryFilters = false) where T : Entity;
 | ||
| 
 | ||
|         Task<T> FirstOrDefaultAsync<T>(Expression<Func<T, bool>> exp = null, bool ignoreQueryFilters = false) where T : Entity;
 | ||
|         Task<int> CountAsync<T>(Expression<Func<T, bool>> exp = null, bool ignoreQueryFilters = false) where T : Entity;
 | ||
| 
 | ||
|         IQueryable<T> Where<T>(Expression<Func<T, bool>> exp = null, bool isTraking = false, bool ignoreQueryFilters = false) where T : Entity;
 | ||
| 
 | ||
|         ValueTask<T> FindAsync<T>(Guid id) where T : Entity;
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|         Task<T> InsertOrUpdateAsync<T, TFrom>(TFrom from, bool autoSave = false, params EntityVerifyExp<T>[] verify) where T : Entity;
 | ||
| 
 | ||
|         Task<T> InsertFromDTOAsync<T, TFrom>(TFrom from, bool autoSave = false, params EntityVerifyExp<T>[] verify) where T : Entity;
 | ||
| 
 | ||
|         Task<T> UpdateFromDTOAsync<T, TFrom>(TFrom from, bool autoSave = false, bool ignoreDtoNullProperty = true, params EntityVerifyExp<T>[] verify) where T : Entity;
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|         ValueTask<T> AddAsync<T>(T entity, bool autoSave = false) where T : Entity;
 | ||
| 
 | ||
|         Task UpdateRange<T>(IEnumerable<T> entities, bool autoSave = false) where T : Entity;
 | ||
|         Task<bool> AddRangeAsync<T>(IEnumerable<T> entities, bool autoSave = false) where T : Entity;
 | ||
| 
 | ||
|         Task<bool> UpdateAsync<T>(T entity, bool autoSave = false) where T : Entity;
 | ||
| 
 | ||
|         Task<bool> DeleteAsync<T>(T entity, bool autoSave = false) where T : Entity;
 | ||
| 
 | ||
| 
 | ||
|         Task<bool> BatchDeleteAsync<T>(Expression<Func<T, bool>> deleteFilter) where T : Entity;
 | ||
| 
 | ||
|         Task<bool> BatchUpdateAsync<T>(Expression<Func<T, bool>> where, Expression<Func<T, T>> updateFactory) where T : Entity;
 | ||
| 
 | ||
|         Task UpdatePartialFromQueryAsync<T>(Expression<Func<T, bool>> updateFilter,
 | ||
|           Expression<Func<T, T>> updateFactory,
 | ||
|           bool autoSave = false, bool ignoreQueryFilter = false) where T : Entity;
 | ||
|     }
 | ||
| 
 | ||
|     public class Repository : IRepository
 | ||
|     {
 | ||
|         #region 构造 基本
 | ||
|         private IRaCISDBContext _dbContext { get; }
 | ||
|         public IMapper _mapper { get; set; }
 | ||
| 
 | ||
|         public IUserInfo _userInfo { get; set; }
 | ||
| 
 | ||
|         public Repository(IRaCISDBContext dbContext, IMapper mapper, IUserInfo userInfo)
 | ||
|         {
 | ||
|             _dbContext = dbContext;
 | ||
|             _mapper = mapper;
 | ||
|             _userInfo = userInfo;
 | ||
|         }
 | ||
| 
 | ||
|         /// <summary>
 | ||
|         /// 设置是使用哪个仓储 默认不跟踪
 | ||
|         /// </summary>
 | ||
|         /// <typeparam name="T"></typeparam>
 | ||
|         /// <param name="isTraking"></param>
 | ||
|         /// <returns></returns>
 | ||
| 
 | ||
|         public IQueryable<T> GetQueryable<T>(bool ignoreQueryFilters = false) where T : Entity
 | ||
|         {
 | ||
|             IQueryable<T> query = _dbContext.Set<T>();
 | ||
| 
 | ||
|             if (ignoreQueryFilters)
 | ||
|             {
 | ||
|                 query = query.IgnoreQueryFilters();
 | ||
|             }
 | ||
|             return query.AsNoTracking();
 | ||
|         }
 | ||
|         public DbSet<T> Set<T>() where T : Entity
 | ||
|         {
 | ||
|             return _dbContext.Set<T>();
 | ||
|         }
 | ||
| 
 | ||
|         public EntityEntry<T> Entry<T>(T t) where T : Entity
 | ||
|         {
 | ||
|             return _dbContext.Entry<T>(t);
 | ||
|         }
 | ||
|         public IQueryable<T> WhereIf<T>(bool condition, Expression<Func<T, bool>> filter) where T : Entity
 | ||
|         {
 | ||
|             IQueryable<T> query = _dbContext.Set<T>().AsNoTracking();
 | ||
|             return condition ? query.Where(filter) : query;
 | ||
|         }
 | ||
| 
 | ||
|         private async Task<bool> SaveChangesAsync(bool autoSave)
 | ||
|         {
 | ||
|             if (autoSave)
 | ||
|             {
 | ||
|                 return await SaveChangesAsync();
 | ||
|             }
 | ||
|             else
 | ||
|             {
 | ||
|                 return false;
 | ||
|             }
 | ||
|         }
 | ||
| 
 | ||
|         public async Task<bool> SaveChangesAsync()
 | ||
|         {
 | ||
| 
 | ||
|             return await _dbContext.SaveChangesAsync().ConfigureAwait(false) > 0;
 | ||
| 
 | ||
|         }
 | ||
| 
 | ||
|         #endregion
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|         public async Task<T> InsertFromDTOAsync<T, TFrom>(TFrom from, bool autoSave = false,
 | ||
|             params EntityVerifyExp<T>[] verify) where T : Entity
 | ||
|         {
 | ||
| 
 | ||
|             var entity = _mapper.Map<T>(from);
 | ||
| 
 | ||
|             await _dbContext.EntityVerifyAsync(true, verify);
 | ||
| 
 | ||
|             entity = await AddAsync(entity, autoSave);
 | ||
| 
 | ||
| 
 | ||
|             return entity;
 | ||
|         }
 | ||
| 
 | ||
|         public async Task<T> UpdateFromDTOAsync<T, TFrom>(TFrom from, bool autoSave = false, bool ignoreDtoNullProperty = true, params EntityVerifyExp<T>[] verify) where T : Entity
 | ||
|         {
 | ||
|             var entity = _mapper.Map<T>(from);
 | ||
| 
 | ||
| 
 | ||
|             await _dbContext.EntityVerifyAsync(false, verify, entity.Id);
 | ||
| 
 | ||
|             var dbEntity = await _dbContext.Set<T>().IgnoreQueryFilters().FirstOrDefaultAsync(t => t.Id == entity.Id).ConfigureAwait(false);
 | ||
| 
 | ||
|             if (dbEntity == null)
 | ||
|             {
 | ||
|                 throw new BusinessValidationFailedException(
 | ||
|                     " Update object not exist in db,Please check if the parameter Id is passed incorrectly");
 | ||
|             }
 | ||
| 
 | ||
|             var dbBeforEntity = dbEntity.Clone();
 | ||
| 
 | ||
| 
 | ||
|             _mapper.Map(from, dbEntity);
 | ||
| 
 | ||
| 
 | ||
|             //DTO  null  属性不更新  防止意外操作,导致保存数据错误,或者 add 和update 用一个模型,更新的时候,只传递了部分字段,导致,不想更新的字段,因为没传递值,用null覆盖了
 | ||
|             // Guid?属性 为null 时   映射到  Guid 时  默认会变成  Guid.Empty   
 | ||
|             if (ignoreDtoNullProperty)
 | ||
|             {
 | ||
|                 var dbEntityProp = typeof(T).GetProperties();
 | ||
|                 foreach (var propertyInfo in from.GetType().GetProperties())
 | ||
|                 {
 | ||
|                     if (propertyInfo.GetValue(from) == null && dbEntityProp.Any(t => t.Name == propertyInfo.Name))
 | ||
|                     {
 | ||
|                         _dbContext.Entry(dbEntity).Property(propertyInfo.Name).IsModified = false;
 | ||
|                     }
 | ||
|                 }
 | ||
|             }
 | ||
| 
 | ||
|             await SaveChangesAsync(autoSave);
 | ||
| 
 | ||
| 
 | ||
|             return dbBeforEntity;
 | ||
|         }
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|         public async Task<T> InsertOrUpdateAsync<T, TFrom>(TFrom from, bool autoSave = false, params EntityVerifyExp<T>[] verify) where T : Entity
 | ||
|         {
 | ||
|             var entity = _mapper.Map<T>(from);
 | ||
| 
 | ||
| 
 | ||
|             if (entity.Id == Guid.Empty)
 | ||
|             {
 | ||
|                 return await InsertFromDTOAsync(from, autoSave, verify);
 | ||
|             }
 | ||
|             else
 | ||
|             {
 | ||
|                 return await UpdateFromDTOAsync(from, autoSave, false, verify);
 | ||
|             }
 | ||
|         }
 | ||
| 
 | ||
| 
 | ||
|         public async Task<bool> AnyAsync<T>(Expression<Func<T, bool>> filter, bool ignoreQueryFilters = false) where T : Entity
 | ||
|         {
 | ||
| 
 | ||
|             var query = _dbContext.Set<T>().AsQueryable();
 | ||
| 
 | ||
|             if (ignoreQueryFilters)
 | ||
|             {
 | ||
|                 query = query.IgnoreQueryFilters();
 | ||
|             }
 | ||
| 
 | ||
|             return await query.AsNoTracking().AnyAsync(filter).ConfigureAwait(false);
 | ||
| 
 | ||
|         }
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|         #region 基本查询 异步
 | ||
| 
 | ||
|         /// <summary>
 | ||
|         /// 跟踪查询某个实体  --异步  默认是跟踪查询
 | ||
|         /// </summary>
 | ||
|         /// <typeparam name="T"></typeparam>
 | ||
|         /// <param name="exp"></param>
 | ||
|         /// <returns></returns>
 | ||
|         /// 
 | ||
|         public async Task<int> CountAsync<T>(Expression<Func<T, bool>> exp = null, bool ignoreQueryFilters = false) where T : Entity
 | ||
|         {
 | ||
|             var query = _dbContext.Set<T>().AsQueryable();
 | ||
| 
 | ||
|             if (ignoreQueryFilters)
 | ||
|             {
 | ||
|                 query = query.IgnoreQueryFilters();
 | ||
|             }
 | ||
| 
 | ||
|             if (exp != null)
 | ||
|             {
 | ||
|                 query = query.Where(exp);
 | ||
|             }
 | ||
| 
 | ||
|             return await query.CountAsync().ConfigureAwait(false);
 | ||
| 
 | ||
| 
 | ||
|         }
 | ||
| 
 | ||
|         public async Task<T> FirstAsync<T>(Expression<Func<T, bool>> exp = null, bool isTracking = false, bool ignoreQueryFilters = false) where T : Entity
 | ||
|         {
 | ||
| 
 | ||
|             var query = _dbContext.Set<T>().AsQueryable();
 | ||
| 
 | ||
|             if (!isTracking)
 | ||
|             {
 | ||
|                 query = query.AsNoTracking();
 | ||
|             }
 | ||
| 
 | ||
|             if (ignoreQueryFilters)
 | ||
|             {
 | ||
|                 query = query.IgnoreQueryFilters();
 | ||
|             }
 | ||
| 
 | ||
|             var entity = await query.FirstOrDefaultAsync();
 | ||
| 
 | ||
|             if (entity is null)
 | ||
|             {
 | ||
|                 throw new QueryBusinessObjectNotExistException($"The query object {typeof(T).Name} does not exist in database,  Please check the query parameters");
 | ||
|             }
 | ||
|             else
 | ||
|             {
 | ||
|                 return entity;
 | ||
|             }
 | ||
| 
 | ||
|         }
 | ||
|         public async Task<T> FirstOrDefaultAsync<T>(Expression<Func<T, bool>> exp = null, bool ignoreQueryFilters = false) where T : Entity
 | ||
|         {
 | ||
| 
 | ||
|             var query = _dbContext.Set<T>().AsQueryable();
 | ||
| 
 | ||
|             if (ignoreQueryFilters)
 | ||
|             {
 | ||
|                 query = query.IgnoreQueryFilters();
 | ||
|             }
 | ||
| 
 | ||
|             if (exp != null)
 | ||
|             {
 | ||
|                 query = query.Where(exp);
 | ||
|             }
 | ||
| 
 | ||
|             return await query.FirstOrDefaultAsync().ConfigureAwait(false);
 | ||
|         }
 | ||
| 
 | ||
|         /// <summary>
 | ||
|         /// 过滤  默认不跟踪
 | ||
|         /// </summary>
 | ||
|         /// <typeparam name="T"></typeparam>
 | ||
|         /// <param name="exp"></param>
 | ||
|         /// <param name="isTraking"></param>
 | ||
|         /// <returns></returns>
 | ||
|         public IQueryable<T> Where<T>(Expression<Func<T, bool>> exp = null, bool isTraking = false, bool ignoreQueryFilters = false) where T : Entity
 | ||
|         {
 | ||
|             IQueryable<T> query = _dbContext.Set<T>();
 | ||
| 
 | ||
|             if (ignoreQueryFilters)
 | ||
|             {
 | ||
|                 query = query.IgnoreQueryFilters();
 | ||
|             }
 | ||
| 
 | ||
|             if (!isTraking)
 | ||
|             {
 | ||
|                 query = query.AsNoTracking();
 | ||
|             }
 | ||
| 
 | ||
|             if (exp != null)
 | ||
|             {
 | ||
|                 query = query.Where(exp);
 | ||
|             }
 | ||
|             return query;
 | ||
|         }
 | ||
| 
 | ||
|         /// <summary>
 | ||
|         ///  首先在内存中查找,其次再找数据库
 | ||
|         /// </summary>
 | ||
|         /// <typeparam name="T"></typeparam>
 | ||
|         /// <param name="id"></param>
 | ||
|         /// <returns></returns>
 | ||
|         public async ValueTask<T> FindAsync<T>(Guid id) where T : Entity
 | ||
|         {
 | ||
|             return await _dbContext.Set<T>().FindAsync(id).ConfigureAwait(false);
 | ||
|         }
 | ||
| 
 | ||
|         #endregion
 | ||
| 
 | ||
|         #region 基本添加、更新、删除 异步
 | ||
| 
 | ||
|         public async ValueTask<T> AddAsync<T>(T entity, bool autoSave = false) where T : Entity
 | ||
|         {
 | ||
| 
 | ||
|             await _dbContext.Set<T>().AddAsync(entity).ConfigureAwait(false);
 | ||
| 
 | ||
|             await SaveChangesAsync(autoSave);
 | ||
| 
 | ||
|             return entity;
 | ||
|         }
 | ||
| 
 | ||
|         public async Task<bool> AddRangeAsync<T>(IEnumerable<T> entities, bool autoSave = false) where T : Entity
 | ||
|         {
 | ||
|             await _dbContext.Set<T>().AddRangeAsync(entities).ConfigureAwait(false);
 | ||
| 
 | ||
|             return await SaveChangesAsync(autoSave);
 | ||
|         }
 | ||
| 
 | ||
|         public async Task UpdateRange<T>(IEnumerable<T> entities, bool autoSave = false) where T : Entity
 | ||
|         {
 | ||
|             _dbContext.Set<T>().UpdateRange(entities);
 | ||
| 
 | ||
|              await SaveChangesAsync(autoSave);
 | ||
| 
 | ||
|         }
 | ||
| 
 | ||
|         public async Task<bool> UpdateAsync<T>(T entity, bool autoSave = false) where T : Entity
 | ||
|         {
 | ||
|             _dbContext.Set<T>().Update(entity);
 | ||
| 
 | ||
|             return await SaveChangesAsync(autoSave);
 | ||
|         }
 | ||
| 
 | ||
| 
 | ||
|         public async Task<bool> DeleteAsync<T>(T entity, bool autoSave = false) where T : Entity
 | ||
|         {
 | ||
|             _dbContext.Set<T>().Remove(entity);
 | ||
| 
 | ||
|             return await SaveChangesAsync(autoSave);
 | ||
| 
 | ||
|         }
 | ||
| 
 | ||
|         public async Task<bool> DeleteManyAsync<T>(IEnumerable<T> entities, bool autoSave = false) where T : Entity
 | ||
|         {
 | ||
|             _dbContext.Set<T>().RemoveRange(entities);
 | ||
| 
 | ||
|             return await SaveChangesAsync(autoSave);
 | ||
|         }
 | ||
| 
 | ||
|         #endregion
 | ||
| 
 | ||
|         public async Task<bool> BatchDeleteAsync<T>(Expression<Func<T, bool>> deleteFilter) where T : Entity
 | ||
|         {
 | ||
|             return await _dbContext.BatchDeleteNoTrackingAsync(deleteFilter);
 | ||
|         }
 | ||
| 
 | ||
|         public async Task<bool> BatchUpdateAsync<T>(Expression<Func<T, bool>> whereFilter, Expression<Func<T, T>> updateFactory) where T : Entity
 | ||
|         {
 | ||
| 
 | ||
|             return await _dbContext.BatchUpdateNoTrackingAsync(whereFilter, updateFactory, _userInfo.Id);
 | ||
|          
 | ||
|         }
 | ||
| 
 | ||
| 
 | ||
|         public async Task UpdatePartialFromQueryAsync<T>(Expression<Func<T, bool>> updateFilter,
 | ||
|            Expression<Func<T, T>> updateFactory,
 | ||
|            bool autoSave = false, bool ignoreQueryFilter = false) where T : Entity
 | ||
|         {
 | ||
|             if (updateFilter == null)
 | ||
|             {
 | ||
|                 throw new ArgumentException("更新过滤条件不允许为空", nameof(updateFilter));
 | ||
|             }
 | ||
|             var query = ignoreQueryFilter ? _dbContext.Set<T>().AsNoTracking().IgnoreQueryFilters() : _dbContext.Set<T>().AsNoTracking();
 | ||
| 
 | ||
|             var searchEntityList = await query.Where(updateFilter).ToListAsync();
 | ||
| 
 | ||
|             foreach (var needUpdateEntity in searchEntityList)
 | ||
|             {
 | ||
|                 _dbContext.EntityModifyPartialFiled(needUpdateEntity, updateFactory);
 | ||
|             }
 | ||
| 
 | ||
|             await SaveChangesAsync(autoSave);
 | ||
|         }
 | ||
| 
 | ||
|         public async Task<bool> UpdateAsync<T>(T waitModifyEntity, Expression<Func<T, T>> updateFactory, bool autoSave = false) where T : Entity
 | ||
|         {
 | ||
|      
 | ||
|             _dbContext.EntityModifyPartialFiled(waitModifyEntity, updateFactory);
 | ||
| 
 | ||
|             return await SaveChangesAsync(autoSave);
 | ||
| 
 | ||
|         }
 | ||
| 
 | ||
| 
 | ||
|     }
 | ||
| 
 | ||
|     #endregion
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| }
 |