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

428 lines
14 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
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;
using Microsoft.Data.SqlClient;
using Z.EntityFramework.Plus;
namespace IRaCIS.Core.Infra.EFCore
{
public class Repository<TEntity> : IRepository<TEntity>
where TEntity : Entity
{
public IMapper _mapper { get; set; }
public IRaCISDBContext _dbContext { get; set; }
public DbSet<TEntity> _dbSet => _dbContext.Set<TEntity>();
public Repository(IRaCISDBContext dbContext, IMapper mapper)
{
//if (typeof(TEntity) = typeof(DataInspection))
//{
//}
_dbContext = dbContext;
_mapper = mapper;
}
#region 异步部分
/// <summary>
/// 仅仅供字典表插入使用因为efcore 动态映射列的问题
/// </summary>
/// <typeparam name="TFrom"></typeparam>
/// <param name="from"></param>
/// <param name="verify"></param>
/// <returns></returns>
/// <exception cref="BusinessValidationFailedException"></exception>
public async Task<TEntity> InsertDictionaryAsync<TFrom>(TFrom from, params EntityVerifyExp<TEntity>[] verify)
{
var entity = _mapper.Map<TEntity>(from);
foreach (var verifyItem in verify.Where(t => t.verifyType != VerifyEnum.OnlyUpdate && t.IsVerify))
{
if (await _dbSet.IgnoreQueryFilters().AnyAsync(verifyItem.VerifyExp).ConfigureAwait(false))
{
throw new BusinessValidationFailedException(verifyItem.VerifyMsg);
}
}
if (typeof(TEntity) == typeof(Dictionary))
{
Type type = typeof(TFrom);
//以下是不要ID这个字段的 比如自增列ID 就不能像上名那样写
var properties = type.GetProperties().Where(t=>t.Name!="Id");
string strSqlName = string.Join(",", properties.Select(p => $"[{p.Name}]").ToArray());
string strSqlValue = string.Join(",", properties.Select(P => $"@{P.Name}").ToArray());
string strSql = $"insert into {nameof(Dictionary)} ( " + strSqlName + " ) values (" + strSqlValue + ")";
//para Sql是参数
SqlParameter[] para = properties.Select(p => new SqlParameter($"@{p.Name}", p.GetValue(from, null))).ToArray();
_dbContext.Database.ExecuteSqlRaw(strSql, para);
return entity;
}
else
{
throw new Exception("仅仅供字典表插入使用因为efcore 动态映射列的问题");
//await _dbSet.BulkInsertAsync(new List<TEntity>() { entity });
//return entity;
}
}
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.IgnoreQueryFilters().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.IgnoreQueryFilters().AnyAsync(verifyItem.VerifyExp).ConfigureAwait(false))
{
throw new BusinessValidationFailedException(verifyItem.VerifyMsg);
}
}
else if (verifyItem.verifyType == VerifyEnum.Both)
{
if (await _dbSet.IgnoreQueryFilters().AnyAsync(verifyItem.VerifyExp.And(t => t.Id != entity.Id)).ConfigureAwait(false))
{
throw new BusinessValidationFailedException(verifyItem.VerifyMsg);
}
}
}
var dbEntity = await _dbSet.IgnoreQueryFilters().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<IEnumerable<TEntity>> AddRangeAsync(IEnumerable<TEntity> entities)
{
await _dbSet.AddRangeAsync(entities).ConfigureAwait(false);
return entities;
}
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<TResult> MaxAsync<TResult>(Expression<Func<TEntity, TResult>> selector)
{
return await _dbSet.AsNoTracking().MaxAsync(selector);
}
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.IgnoreQueryFilters().Where(deleteFilter).DeleteFromQueryAsync() > 0;
}
public async Task<bool> UpdateFromQueryAsync(Expression<Func<TEntity, bool>> where, Expression<Func<TEntity, TEntity>> updateFactory)
{
return await _dbSet.IgnoreQueryFilters().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
}
}