EI-Image-Viewer-Api/IRaCIS.Core.Infra.EFCore/Repository/IRepository.cs

439 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 EFCore.BulkExtensions;
using IRaCIS.Core.Domain.Share;
namespace IRaCIS.Core.Infra.EFCore
{
public interface IRepository<TEntity> : ICommandRepository<TEntity>, IQueryRepository<TEntity> where TEntity : Entity
{
}
#region 泛型通用版本
public interface IRepository
{
IQueryable<T> GetQueryable<T>(bool isTraking = false) where T : Entity;
DbSet<T> Set<T>() where T : Entity;
IQueryable<T> WhereIf<T>(bool condition, Expression<Func<T, bool>> filter) where T : Entity;
Task<T> InsertOrUpdateAsync<T, TFrom>(TFrom from, bool autoSave = false, params EntityVerifyExp<T>[] verify) where T : Entity;
EntityEntry<T> Entry<T>(T t) where T : Entity;
//Task<T> InsertOrUpdateAsync<T, TFrom>(this DbSet<T> dbset, TFrom from, bool autoSave = false, params EntityVerifyExp<T>[] verify) where T : Entity;
Task<bool> AnyAsync<T>(Expression<Func<T, bool>> filter, 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;
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> DeleteManyAsync<T>(IEnumerable<T> entities, bool autoSave = false) where T : Entity;
Task<bool> SaveChangesAsync();
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;
}
public class Repository : IRepository
{
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 isTraking = false) where T : Entity
{
IQueryable<T> query = _dbContext.Set<T>();
if (!isTraking)
{
query = query.AsNoTracking();
}
return query;
}
public DbSet<T> Set<T>() where T : Entity
{
return _dbContext.Set<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;
}
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)
{
// verifyExp
//await verify.Where(t => t.verifyType != VerifyEnum.OnlyUpdate && t.IsVerify).ToList().ForeachAsync(async verifyItem =>
//{
// if (await _dbContext.Set<T>().AnyAsync(verifyItem.VerifyExp).ConfigureAwait(false))
// {
// throw new BusinessValidationFailedException(verifyItem.VerifyMsg);
// }
//});
foreach (var verifyItem in verify.Where(t => t.verifyType != VerifyEnum.OnlyUpdate && t.IsVerify))
{
if (await _dbContext.Set<T>().AnyAsync(verifyItem.VerifyExp).ConfigureAwait(false))
{
throw new BusinessValidationFailedException(verifyItem.VerifyMsg);
}
}
await _dbContext.Set<T>().AddAsync(entity).ConfigureAwait(false);
if (autoSave)
{
await SaveChangesAsync();
}
return entity;
}
else
{
// verifyExp
//await verify.Where(t => t.verifyType != VerifyEnum.OnlyAdd && t.IsVerify).ToList().ForeachAsync(async verifyItem =>
// {
// if (verifyItem.verifyType == VerifyEnum.OnlyUpdate)
// {
// if (await _dbContext.Set<T>().AnyAsync(verifyItem.VerifyExp).ConfigureAwait(false))
// {
// throw new BusinessValidationFailedException(verifyItem.VerifyMsg);
// }
// }
// else if (verifyItem.verifyType == VerifyEnum.Both)
// {
// if (await _dbContext.Set<T>().AnyAsync(verifyItem.VerifyExp.And(t => t.Id != entity.Id)).ConfigureAwait(false))
// {
// throw new BusinessValidationFailedException(verifyItem.VerifyMsg);
// }
// }
// });
foreach (var verifyItem in verify.Where(t => t.verifyType != VerifyEnum.OnlyAdd && t.IsVerify))
{
if (verifyItem.verifyType == VerifyEnum.OnlyUpdate)
{
if (await _dbContext.Set<T>().IgnoreQueryFilters().AnyAsync(verifyItem.VerifyExp).ConfigureAwait(false))
{
throw new BusinessValidationFailedException(verifyItem.VerifyMsg);
}
}
else if (verifyItem.verifyType == VerifyEnum.Both)
{
if (await _dbContext.Set<T>().IgnoreQueryFilters().AnyAsync(verifyItem.VerifyExp.And(t => t.Id != entity.Id)).ConfigureAwait(false))
{
throw new BusinessValidationFailedException(verifyItem.VerifyMsg);
}
}
}
var dbEntity = await FirstOrDefaultAsync<T>(t => t.Id == entity.Id).ConfigureAwait(false);
var dbBeforEntity = dbEntity.Clone();
_mapper.Map(from, dbEntity);
if (autoSave)
{
await SaveChangesAsync();
}
return dbBeforEntity;
}
}
public EntityEntry<T> Entry<T>(T t) where T : Entity
{
return _dbContext.Entry<T>(t);
}
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> 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);
if (autoSave)
{
await SaveChangesAsync();
}
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);
if (autoSave)
{
return await SaveChangesAsync();
}
else
{
return false;
}
}
public async Task UpdateRange<T>(IEnumerable<T> entities, bool autoSave = false) where T : Entity
{
_dbContext.Set<T>().UpdateRange(entities);
if (autoSave)
{
await SaveChangesAsync();
}
}
public async Task<bool> UpdateAsync<T>(T entity, bool autoSave = false) where T : Entity
{
_dbContext.Set<T>().Update(entity);
if (autoSave)
{
return await SaveChangesAsync();
}
else
{
return false;
}
}
public async Task<bool> DeleteAsync<T>(T entity, bool autoSave = false) where T : Entity
{
_dbContext.Set<T>().Remove(entity);
if (autoSave)
{
return await SaveChangesAsync();
}
else
{
return false;
}
}
public async Task<bool> DeleteManyAsync<T>(IEnumerable<T> entities, bool autoSave = false) where T : Entity
{
_dbContext.Set<T>().RemoveRange(entities);
if (autoSave)
{
return await SaveChangesAsync();
}
else
{
return false;
}
}
public async Task<bool> SaveChangesAsync()
{
return await _dbContext.SaveChangesAsync().ConfigureAwait(false) > 0;
}
#endregion
public async Task<bool> BatchDeleteAsync<T>(Expression<Func<T, bool>> deleteFilter) where T : Entity
{
if (deleteFilter == null) throw new ArgumentNullException(nameof(deleteFilter));
return await _dbContext.Set<T>().AsNoTracking().Where(deleteFilter).BatchDeleteAsync().ConfigureAwait(false) > 0;
}
public async Task<bool> BatchUpdateAsync<T>(Expression<Func<T, bool>> whereFilter, Expression<Func<T, T>> updateFactory) where T : Entity
{
if (whereFilter == null) throw new ArgumentNullException(nameof(whereFilter));
var bindings = ((MemberInitExpression)updateFactory.Body).Bindings.ToList();
if (typeof(IAuditUpdate).IsAssignableFrom(typeof(T)))
{
bindings.Add(Expression.Bind(typeof(T).GetMember(nameof(IAuditUpdate.UpdateTime))[0], Expression.Constant(DateTime.Now)));
bindings.Add(Expression.Bind(typeof(TR).GetMember(nameof(IAuditUpdate.UpdateUserId))[0], Expression.Constant(_userInfo.Id)));
}
var member = Expression.MemberInit(Expression.New(typeof(T)), bindings);
var factory = Expression.Lambda<Func<T, T>>(member, Expression.Parameter(typeof(T), "x"));
return await _dbContext.Set<T>().AsNoTracking().IgnoreQueryFilters().Where(whereFilter).BatchUpdateAsync(updateFactory).ConfigureAwait(false) > 0;
}
}
#endregion
}