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 : ICommandRepository, IQueryRepository where TEntity : Entity { } #region 泛型通用版本 public interface IRepository { IQueryable GetQueryable(bool isTraking = false) where T : Entity; DbSet Set() where T : Entity; IQueryable WhereIf(bool condition, Expression> filter) where T : Entity; Task InsertOrUpdateAsync(TFrom from, bool autoSave = false, params EntityVerifyExp[] verify) where T : Entity; EntityEntry Entry(T t) where T : Entity; //Task InsertOrUpdateAsync(this DbSet dbset, TFrom from, bool autoSave = false, params EntityVerifyExp[] verify) where T : Entity; Task AnyAsync(Expression> filter, bool ignoreQueryFilters = false) where T : Entity; Task FirstOrDefaultAsync(Expression> exp = null, bool ignoreQueryFilters = false) where T : Entity; Task CountAsync(Expression> exp = null, bool ignoreQueryFilters = false) where T : Entity; IQueryable Where(Expression> exp = null, bool isTraking = false, bool ignoreQueryFilters = false) where T : Entity; ValueTask FindAsync(Guid id) where T : Entity; ValueTask AddAsync(T entity, bool autoSave = false) where T : Entity; Task UpdateRange(IEnumerable entities, bool autoSave = false) where T : Entity; Task AddRangeAsync(IEnumerable entities, bool autoSave = false) where T : Entity; Task UpdateAsync(T entity, bool autoSave = false) where T : Entity; Task DeleteAsync(T entity, bool autoSave = false) where T : Entity; Task DeleteManyAsync(IEnumerable entities, bool autoSave = false) where T : Entity; Task SaveChangesAsync(); Task BatchDeleteAsync(Expression> deleteFilter) where T : Entity; Task BatchUpdateAsync(Expression> where, Expression> 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; } /// /// 设置是使用哪个仓储 默认不跟踪 /// /// /// /// public IQueryable GetQueryable(bool isTraking = false) where T : Entity { IQueryable query = _dbContext.Set(); if (!isTraking) { query = query.AsNoTracking(); } return query; } public DbSet Set() where T : Entity { return _dbContext.Set(); } public IQueryable WhereIf(bool condition, Expression> filter) where T : Entity { IQueryable query = _dbContext.Set().AsNoTracking(); return condition ? query.Where(filter) : query; } public async Task InsertOrUpdateAsync(TFrom from, bool autoSave = false, params EntityVerifyExp[] verify) where T : Entity { var entity = _mapper.Map(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().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().AnyAsync(verifyItem.VerifyExp).ConfigureAwait(false)) { throw new BusinessValidationFailedException(verifyItem.VerifyMsg); } } await _dbContext.Set().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().AnyAsync(verifyItem.VerifyExp).ConfigureAwait(false)) // { // throw new BusinessValidationFailedException(verifyItem.VerifyMsg); // } // } // else if (verifyItem.verifyType == VerifyEnum.Both) // { // if (await _dbContext.Set().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().IgnoreQueryFilters().AnyAsync(verifyItem.VerifyExp).ConfigureAwait(false)) { throw new BusinessValidationFailedException(verifyItem.VerifyMsg); } } else if (verifyItem.verifyType == VerifyEnum.Both) { if (await _dbContext.Set().IgnoreQueryFilters().AnyAsync(verifyItem.VerifyExp.And(t => t.Id != entity.Id)).ConfigureAwait(false)) { throw new BusinessValidationFailedException(verifyItem.VerifyMsg); } } } var dbEntity = await FirstOrDefaultAsync(t => t.Id == entity.Id).ConfigureAwait(false); var dbBeforEntity = dbEntity.Clone(); _mapper.Map(from, dbEntity); if (autoSave) { await SaveChangesAsync(); } return dbBeforEntity; } } public EntityEntry Entry(T t) where T : Entity { return _dbContext.Entry(t); } public async Task AnyAsync(Expression> filter, bool ignoreQueryFilters = false) where T : Entity { var query = _dbContext.Set().AsQueryable(); if (ignoreQueryFilters) { query = query.IgnoreQueryFilters(); } return await query.AsNoTracking().AnyAsync(filter).ConfigureAwait(false); } #region 基本查询 异步 /// /// 跟踪查询某个实体 --异步 默认是跟踪查询 /// /// /// /// /// public async Task CountAsync(Expression> exp = null, bool ignoreQueryFilters = false) where T : Entity { var query = _dbContext.Set().AsQueryable(); if (ignoreQueryFilters) { query = query.IgnoreQueryFilters(); } if (exp != null) { query = query.Where(exp); } return await query.CountAsync().ConfigureAwait(false); } public async Task FirstOrDefaultAsync(Expression> exp = null, bool ignoreQueryFilters = false) where T : Entity { var query = _dbContext.Set().AsQueryable(); if (ignoreQueryFilters) { query = query.IgnoreQueryFilters(); } if (exp != null) { query = query.Where(exp); } return await query.FirstOrDefaultAsync().ConfigureAwait(false); } /// /// 过滤 默认不跟踪 /// /// /// /// /// public IQueryable Where(Expression> exp = null, bool isTraking = false, bool ignoreQueryFilters = false) where T : Entity { IQueryable query = _dbContext.Set(); if (ignoreQueryFilters) { query = query.IgnoreQueryFilters(); } if (!isTraking) { query = query.AsNoTracking(); } if (exp != null) { query = query.Where(exp); } return query; } /// /// 首先在内存中查找,其次再找数据库 /// /// /// /// public async ValueTask FindAsync(Guid id) where T : Entity { return await _dbContext.Set().FindAsync(id).ConfigureAwait(false); } #endregion #region 基本添加、更新、删除 异步 public async ValueTask AddAsync(T entity, bool autoSave = false) where T : Entity { await _dbContext.Set().AddAsync(entity).ConfigureAwait(false); if (autoSave) { await SaveChangesAsync(); } return entity; } public async Task AddRangeAsync(IEnumerable entities, bool autoSave = false) where T : Entity { await _dbContext.Set().AddRangeAsync(entities).ConfigureAwait(false); if (autoSave) { return await SaveChangesAsync(); } else { return false; } } public async Task UpdateRange(IEnumerable entities, bool autoSave = false) where T : Entity { _dbContext.Set().UpdateRange(entities); if (autoSave) { await SaveChangesAsync(); } } public async Task UpdateAsync(T entity, bool autoSave = false) where T : Entity { _dbContext.Set().Update(entity); if (autoSave) { return await SaveChangesAsync(); } else { return false; } } public async Task DeleteAsync(T entity, bool autoSave = false) where T : Entity { _dbContext.Set().Remove(entity); if (autoSave) { return await SaveChangesAsync(); } else { return false; } } public async Task DeleteManyAsync(IEnumerable entities, bool autoSave = false) where T : Entity { _dbContext.Set().RemoveRange(entities); if (autoSave) { return await SaveChangesAsync(); } else { return false; } } public async Task SaveChangesAsync() { return await _dbContext.SaveChangesAsync().ConfigureAwait(false) > 0; } #endregion public async Task BatchDeleteAsync(Expression> deleteFilter) where T : Entity { if (deleteFilter == null) throw new ArgumentNullException(nameof(deleteFilter)); return await _dbContext.Set().AsNoTracking().Where(deleteFilter).BatchDeleteAsync().ConfigureAwait(false) > 0; } public async Task BatchUpdateAsync(Expression> whereFilter, Expression> 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>(member, Expression.Parameter(typeof(T), "x")); return await _dbContext.Set().AsNoTracking().IgnoreQueryFilters().Where(whereFilter).BatchUpdateAsync(updateFactory).ConfigureAwait(false) > 0; } } #endregion }