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; using EFCore.BulkExtensions; using Microsoft.Extensions.Localization; namespace IRaCIS.Core.Infra.EFCore { #region 泛型通用版本 public interface IRepository { IQueryable GetQueryable(bool ignoreQueryFilters = false) where T : Entity; DbSet Set() where T : Entity; EntityEntry Entry(T t) where T : Entity; Task SaveChangesAsync(); IQueryable WhereIf(bool condition, Expression> filter) where T : Entity; Task AnyAsync(Expression> filter, bool ignoreQueryFilters = false) where T : Entity; /// ///不跟踪 查询单个实体,不会出现NUll /// /// /// /// Task FirstAsync(Expression> exp = null, bool isTracking = false, 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; Task InsertOrUpdateAsync(TFrom from, bool autoSave = false, params EntityVerifyExp[] verify) where T : Entity; Task InsertFromDTOAsync(TFrom from, bool autoSave = false, params EntityVerifyExp[] verify) where T : Entity; Task UpdateFromDTOAsync(TFrom from, bool autoSave = false, bool ignoreDtoNullProperty = true, params EntityVerifyExp[] verify) 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 BatchDeleteAsync(Expression> deleteFilter) where T : Entity; Task BatchUpdateAsync(Expression> where, Expression> updateFactory) where T : Entity; Task UpdatePartialFromQueryAsync(Expression> updateFilter, Expression> 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 IStringLocalizer _localizer { get; set; } public Repository(IRaCISDBContext dbContext, IMapper mapper, IUserInfo userInfo, IStringLocalizer localizer) { _localizer = localizer; _dbContext = dbContext; _mapper = mapper; _userInfo = userInfo; } /// /// 设置是使用哪个仓储 默认不跟踪 /// /// /// /// public IQueryable GetQueryable(bool ignoreQueryFilters = false) where T : Entity { IQueryable query = _dbContext.Set(); if (ignoreQueryFilters) { query = query.IgnoreQueryFilters(); } return query.AsNoTracking(); } public DbSet Set() where T : Entity { return _dbContext.Set(); } public EntityEntry Entry(T t) where T : Entity { return _dbContext.Entry(t); } public IQueryable WhereIf(bool condition, Expression> filter) where T : Entity { IQueryable query = _dbContext.Set().AsNoTracking(); return condition ? query.Where(filter) : query; } private async Task SaveChangesAsync(bool autoSave) { if (autoSave) { return await SaveChangesAsync(); } else { return false; } } public async Task SaveChangesAsync() { return await _dbContext.SaveChangesAsync().ConfigureAwait(false) > 0; } #endregion public async Task InsertFromDTOAsync(TFrom from, bool autoSave = false, params EntityVerifyExp[] verify) where T : Entity { var entity = _mapper.Map(from); await _dbContext.EntityVerifyAsync(true, verify); entity = await AddAsync(entity, autoSave); return entity; } public async Task UpdateFromDTOAsync(TFrom from, bool autoSave = false, bool ignoreDtoNullProperty = true, params EntityVerifyExp[] verify) where T : Entity { var entity = _mapper.Map(from); await _dbContext.EntityVerifyAsync(false, verify, entity.Id); var dbEntity = await _dbContext.Set().IgnoreQueryFilters().FirstOrDefaultAsync(t => t.Id == entity.Id).ConfigureAwait(false); if (dbEntity == null) { throw new BusinessValidationFailedException(_localizer["Repository_UpdateError"]); } 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 InsertOrUpdateAsync(TFrom from, bool autoSave = false, params EntityVerifyExp[] verify) where T : Entity { var entity = _mapper.Map(from); if (entity.Id == Guid.Empty) { return await InsertFromDTOAsync(from, autoSave, verify); } else { return await UpdateFromDTOAsync(from, autoSave, false, verify); } } 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 FirstAsync(Expression> exp = null, bool isTracking = false, bool ignoreQueryFilters = false) where T : Entity { var query = _dbContext.Set().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 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); await SaveChangesAsync(autoSave); return entity; } public async Task AddRangeAsync(IEnumerable entities, bool autoSave = false) where T : Entity { await _dbContext.Set().AddRangeAsync(entities).ConfigureAwait(false); return await SaveChangesAsync(autoSave); } public async Task UpdateRange(IEnumerable entities, bool autoSave = false) where T : Entity { _dbContext.Set().UpdateRange(entities); await SaveChangesAsync(autoSave); } public async Task UpdateAsync(T entity, bool autoSave = false) where T : Entity { _dbContext.Set().Update(entity); return await SaveChangesAsync(autoSave); } public async Task DeleteAsync(T entity, bool autoSave = false) where T : Entity { _dbContext.Set().Remove(entity); return await SaveChangesAsync(autoSave); } public async Task DeleteManyAsync(IEnumerable entities, bool autoSave = false) where T : Entity { _dbContext.Set().RemoveRange(entities); return await SaveChangesAsync(autoSave); } #endregion public async Task BatchDeleteAsync(Expression> deleteFilter) where T : Entity { return await _dbContext.BatchDeleteNoTrackingAsync(deleteFilter); } public async Task BatchUpdateAsync(Expression> whereFilter, Expression> updateFactory) where T : Entity { return await _dbContext.BatchUpdateNoTrackingAsync(whereFilter, updateFactory, _userInfo.Id); //return await _dbContext.Set().IgnoreQueryFilters().Where(whereFilter).BatchUpdateAsync(updateFactory).ConfigureAwait(false) > 0; } public async Task UpdatePartialFromQueryAsync(Expression> updateFilter, Expression> updateFactory, bool autoSave = false, bool ignoreQueryFilter = false) where T : Entity { if (updateFilter == null) { throw new ArgumentException("更新过滤条件不允许为空", nameof(updateFilter)); } var query = ignoreQueryFilter ? _dbContext.Set().AsNoTracking().IgnoreQueryFilters() : _dbContext.Set().AsNoTracking(); var searchEntityList = await query.Where(updateFilter).ToListAsync(); foreach (var needUpdateEntity in searchEntityList) { _dbContext.EntityModifyPartialFiled(needUpdateEntity, updateFactory); } await SaveChangesAsync(autoSave); } public async Task UpdateAsync(T waitModifyEntity, Expression> updateFactory, bool autoSave = false) where T : Entity { _dbContext.EntityModifyPartialFiled(waitModifyEntity, updateFactory); return await SaveChangesAsync(autoSave); } } #endregion }