357 lines
11 KiB
C#
357 lines
11 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using System.Linq.Expressions;
|
||
using System.Threading;
|
||
using System.Threading.Tasks;
|
||
using AutoMapper;
|
||
using IRaCIS.Core.Domain.Models;
|
||
using Microsoft.EntityFrameworkCore;
|
||
using Microsoft.EntityFrameworkCore.ChangeTracking;
|
||
using AutoMapper.QueryableExtensions;
|
||
using IRaCIS.Core.Infrastructure;
|
||
using IRaCIS.Core.Infrastructure.Extention;
|
||
|
||
namespace IRaCIS.Core.Infra.EFCore
|
||
{
|
||
public class Repository<TEntity> : IRepository<TEntity>
|
||
where TEntity : Entity
|
||
{
|
||
public IMapper _mapper { get; set; }
|
||
public IRaCISDBContext _dbContext { get; set; }
|
||
|
||
private DbSet<TEntity> _dbSet => _dbContext.Set<TEntity>();
|
||
|
||
|
||
public Repository(IRaCISDBContext dbContext, IMapper mapper)
|
||
{
|
||
_dbContext = dbContext;
|
||
_mapper = mapper;
|
||
}
|
||
|
||
#region 异步部分
|
||
|
||
|
||
public async Task<TEntity> InsertOrUpdateAsync<TFrom>(TFrom from, bool autoSave = false, params EntityVerifyExp<TEntity>[] verify)
|
||
{
|
||
var entity = _mapper.Map<TEntity>(from);
|
||
|
||
if (entity.Id == Guid.Empty)
|
||
{
|
||
|
||
|
||
foreach (var verifyItem in verify.Where(t => t.verifyType != VerifyEnum.OnlyUpdate && t.IsVerify))
|
||
{
|
||
if (await _dbSet.AnyAsync(verifyItem.VerifyExp).ConfigureAwait(false))
|
||
{
|
||
throw new BusinessValidationFailedException(verifyItem.VerifyMsg);
|
||
}
|
||
}
|
||
|
||
await _dbSet.AddAsync(entity).ConfigureAwait(false);
|
||
|
||
if (autoSave)
|
||
{
|
||
await SaveChangesAsync();
|
||
|
||
}
|
||
return entity;
|
||
|
||
}
|
||
else
|
||
{
|
||
|
||
|
||
foreach (var verifyItem in verify.Where(t => t.verifyType != VerifyEnum.OnlyAdd && t.IsVerify))
|
||
{
|
||
if (verifyItem.verifyType == VerifyEnum.OnlyUpdate)
|
||
{
|
||
if (await _dbSet.AnyAsync(verifyItem.VerifyExp).ConfigureAwait(false))
|
||
{
|
||
throw new BusinessValidationFailedException(verifyItem.VerifyMsg);
|
||
}
|
||
}
|
||
else if (verifyItem.verifyType == VerifyEnum.Both)
|
||
{
|
||
if (await _dbSet.AnyAsync(verifyItem.VerifyExp.And(t => t.Id != entity.Id)).ConfigureAwait(false))
|
||
{
|
||
throw new BusinessValidationFailedException(verifyItem.VerifyMsg);
|
||
}
|
||
}
|
||
}
|
||
|
||
var dbEntity = await _dbSet.FirstOrDefaultAsync(t => t.Id == entity.Id).ConfigureAwait(false);
|
||
|
||
var dbBeforEntity = dbEntity.Clone();
|
||
|
||
_mapper.Map(from, dbEntity);
|
||
|
||
if (autoSave)
|
||
{
|
||
await SaveChangesAsync();
|
||
}
|
||
return dbBeforEntity;
|
||
|
||
}
|
||
}
|
||
|
||
public async Task<bool> SaveChangesAsync(CancellationToken cancellationToken = default)
|
||
{
|
||
|
||
return await _dbContext.SaveChangesAsync(cancellationToken) > 0;
|
||
|
||
}
|
||
|
||
public async ValueTask<TEntity> FindAsync(Guid id, CancellationToken cancellationToken = default)
|
||
{
|
||
return await _dbContext.FindAsync<TEntity>(id);
|
||
}
|
||
|
||
//有可能是联合主键,本项目没用到,用Guid
|
||
public async ValueTask<TEntity> FindAsync(object[] keyValues, CancellationToken cancellationToken)
|
||
{
|
||
return await _dbContext.FindAsync<TEntity>(keyValues);
|
||
}
|
||
|
||
public async Task<TEntity> FirstOrDefaultAsync(Expression<Func<TEntity, bool>> exp = null, bool ignoreQueryFilters = false)
|
||
{
|
||
|
||
var query = _dbSet.AsQueryable();
|
||
|
||
if (ignoreQueryFilters)
|
||
{
|
||
query = query.IgnoreQueryFilters();
|
||
}
|
||
if (exp == null)
|
||
return await query.FirstOrDefaultAsync().ConfigureAwait(false);
|
||
return await query.FirstOrDefaultAsync(exp).ConfigureAwait(false);
|
||
}
|
||
|
||
public async ValueTask<TEntity> AddAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default)
|
||
{
|
||
|
||
await _dbSet.AddAsync(entity).ConfigureAwait(false);
|
||
|
||
if (autoSave)
|
||
{
|
||
await SaveChangesAsync(cancellationToken);
|
||
}
|
||
|
||
return entity;
|
||
}
|
||
|
||
public async Task<bool> AddRangeAsync(IEnumerable<TEntity> entities, bool autoSave = false, CancellationToken cancellationToken = default)
|
||
{
|
||
await _dbSet.AddRangeAsync(entities).ConfigureAwait(false);
|
||
|
||
if (autoSave)
|
||
{
|
||
return await SaveChangesAsync(cancellationToken);
|
||
}
|
||
else
|
||
{
|
||
return false;
|
||
}
|
||
}
|
||
|
||
public async Task<bool> UpdateAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default)
|
||
{
|
||
_dbSet.Update(entity);
|
||
|
||
if (autoSave)
|
||
{
|
||
return await SaveChangesAsync(cancellationToken);
|
||
}
|
||
else
|
||
{
|
||
return false;
|
||
}
|
||
}
|
||
|
||
public async Task<bool> UpdateManyAsync(IEnumerable<TEntity> entities, bool autoSave = false, CancellationToken cancellationToken = default)
|
||
{
|
||
_dbSet.UpdateRange(entities);
|
||
|
||
if (autoSave)
|
||
{
|
||
return await SaveChangesAsync(cancellationToken);
|
||
}
|
||
else
|
||
{
|
||
return false;
|
||
}
|
||
}
|
||
|
||
public async Task<bool> DeleteAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default)
|
||
{
|
||
_dbSet.Remove(entity);
|
||
|
||
//var entry = _dbSet.Attach(entity);
|
||
//entry.State = EntityState.Deleted;
|
||
|
||
if (autoSave)
|
||
{
|
||
return await SaveChangesAsync(cancellationToken);
|
||
}
|
||
else
|
||
{
|
||
return false;
|
||
}
|
||
}
|
||
|
||
public async Task<bool> DeleteManyAsync(IEnumerable<TEntity> entities, bool autoSave = false, CancellationToken cancellationToken = default)
|
||
{
|
||
_dbSet.RemoveRange(entities);
|
||
|
||
if (autoSave)
|
||
{
|
||
return await SaveChangesAsync(cancellationToken);
|
||
}
|
||
else
|
||
{
|
||
return false;
|
||
}
|
||
}
|
||
|
||
public async Task<bool> AnyAsync(Expression<Func<TEntity, bool>> exp, bool ignoreQueryFilters = false)
|
||
{
|
||
var query = _dbSet.AsQueryable();
|
||
|
||
if (ignoreQueryFilters)
|
||
{
|
||
query = query.IgnoreQueryFilters();
|
||
}
|
||
|
||
return await query.AsNoTracking().AnyAsync(exp);
|
||
}
|
||
|
||
public async Task<int> CountAsync(Expression<Func<TEntity, bool>> whereLambda = null, bool ignoreQueryFilters = false)
|
||
{
|
||
var query = _dbSet.AsQueryable();
|
||
|
||
if (ignoreQueryFilters)
|
||
{
|
||
query = query.IgnoreQueryFilters();
|
||
}
|
||
|
||
return whereLambda == null ? await query.AsNoTracking().CountAsync() : await query.AsNoTracking().CountAsync(whereLambda);
|
||
}
|
||
|
||
// Z.EntityFramework.Plus.EFCore
|
||
public async Task<bool> DeleteFromQueryAsync(Expression<Func<TEntity, bool>> deleteFilter)
|
||
{
|
||
return await _dbSet.Where(deleteFilter).DeleteFromQueryAsync() > 0;
|
||
}
|
||
|
||
public async Task<bool> UpdateFromQueryAsync(Expression<Func<TEntity, bool>> where, Expression<Func<TEntity, TEntity>> updateFactory)
|
||
{
|
||
return await _dbSet.Where(where).UpdateFromQueryAsync(updateFactory) > 0;
|
||
}
|
||
|
||
#endregion
|
||
|
||
|
||
|
||
#region 非异步部分
|
||
|
||
public TEntity ImageFind(Guid id, Type type)
|
||
{
|
||
//重传的时候 状态为修改 上传的时候状态为添加 内存中有,就不要重复查询数据库了
|
||
var list = _dbContext.ChangeTracker.Entries()
|
||
.Where(u => (u.State == EntityState.Added || u.State == EntityState.Modified) && (u.Entity.GetType() == type)).Select(t => t.Entity as TEntity);
|
||
|
||
var entity = list.FirstOrDefault(t => t.Id == id);
|
||
|
||
if (entity == null)
|
||
{
|
||
return _dbSet.FirstOrDefault(t => t.Id == id);
|
||
}
|
||
else
|
||
{
|
||
return entity;
|
||
}
|
||
|
||
}
|
||
|
||
public IQueryable<TEntity> AsQueryable( bool ignoreQueryFilters = false)
|
||
{
|
||
var query = _dbSet.AsQueryable();
|
||
|
||
if (ignoreQueryFilters)
|
||
{
|
||
query = query.IgnoreQueryFilters();
|
||
}
|
||
|
||
return query.AsNoTracking();
|
||
}
|
||
|
||
public IQueryable<TResult> Select<TResult>(Expression<Func<TEntity, TResult>> selector)
|
||
{
|
||
return _dbSet.AsNoTracking().Select(selector);
|
||
}
|
||
|
||
public IQueryable<TEntity> WhereIf(bool condition, Expression<Func<TEntity, bool>> filter)
|
||
{
|
||
return condition ? _dbSet.AsNoTracking().Where(filter) : _dbSet.AsNoTracking();
|
||
}
|
||
|
||
public IQueryable<TEntity> Where(Expression<Func<TEntity, bool>> exp = null, bool isTraking = false,bool ignoreQueryFilters = false)
|
||
{
|
||
IQueryable<TEntity> query = _dbSet;
|
||
|
||
if (!isTraking)
|
||
{
|
||
query = query.AsNoTracking();
|
||
}
|
||
|
||
if (ignoreQueryFilters)
|
||
{
|
||
query = query.IgnoreQueryFilters();
|
||
}
|
||
|
||
if (exp != null)
|
||
{
|
||
query = query.Where(exp);
|
||
}
|
||
return query;
|
||
}
|
||
|
||
public EntityEntry Entry(TEntity t)
|
||
{
|
||
return _dbContext.Entry(t);
|
||
}
|
||
|
||
public EntityEntry<TEntity> Attach(TEntity entity)
|
||
{
|
||
return _dbSet.Attach(entity);
|
||
}
|
||
|
||
public void Detached(TEntity t)
|
||
{
|
||
_dbContext.Entry(t).State = EntityState.Detached;
|
||
}
|
||
|
||
|
||
// automapper 相关
|
||
public IQueryable<TDestination> ProjectTo<TDestination>(IConfigurationProvider configuration, object parameters, params Expression<Func<TDestination, object>>[] membersToExpand)
|
||
{
|
||
return _dbSet.AsNoTracking().ProjectTo(configuration, parameters, membersToExpand);
|
||
}
|
||
|
||
public IQueryable<TDestination> ProjectTo<TDestination>(IConfigurationProvider configuration, params Expression<Func<TDestination, object>>[] membersToExpand)
|
||
{
|
||
return _dbSet.AsNoTracking().ProjectTo(configuration, membersToExpand);
|
||
}
|
||
|
||
public IQueryable<TDestination> ProjectTo<TDestination>(IConfigurationProvider configuration, IDictionary<string, object> parameters, params string[] membersToExpand)
|
||
{
|
||
return _dbSet.AsNoTracking().ProjectTo<TDestination>(configuration, parameters, membersToExpand);
|
||
}
|
||
|
||
|
||
|
||
#endregion
|
||
}
|
||
|
||
}
|