1592 lines
		
	
	
		
			59 KiB
		
	
	
	
		
			C#
		
	
	
			
		
		
	
	
			1592 lines
		
	
	
		
			59 KiB
		
	
	
	
		
			C#
		
	
	
using System;
 | 
						||
using System.Collections.Generic;
 | 
						||
using System.ComponentModel.DataAnnotations;
 | 
						||
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 EFCore.BulkExtensions;
 | 
						||
using IRaCIS.Core.Domain.Share;
 | 
						||
using IRaCIS.Core.Infrastructure;
 | 
						||
using IRaCIS.Core.Infrastructure.Extention;
 | 
						||
using Microsoft.Data.SqlClient;
 | 
						||
using Newtonsoft.Json;
 | 
						||
using Newtonsoft.Json.Linq;
 | 
						||
using IRaCIS.Core.Domain.Common;
 | 
						||
using IRaCIS.Core.Infra.EFCore.Common.Dto;
 | 
						||
 | 
						||
namespace IRaCIS.Core.Infra.EFCore
 | 
						||
{
 | 
						||
    public class Repository<TEntity> : IRepository<TEntity>
 | 
						||
        where TEntity : Entity, new()
 | 
						||
    {
 | 
						||
 | 
						||
        public IMapper _mapper { get; set; }
 | 
						||
        public IRaCISDBContext _dbContext { get; set; }
 | 
						||
 | 
						||
        public DbSet<TEntity> _dbSet => _dbContext.Set<TEntity>();
 | 
						||
 | 
						||
        public IUserInfo _userInfo { get; set; }
 | 
						||
 | 
						||
        public Repository(IRaCISDBContext dbContext, IMapper mapper, IUserInfo userInfo)
 | 
						||
        {
 | 
						||
            _dbContext = dbContext;
 | 
						||
            _mapper = mapper;
 | 
						||
            _userInfo = userInfo;
 | 
						||
 | 
						||
        }
 | 
						||
 | 
						||
 | 
						||
        #region 异步 EF 跟踪 添加
 | 
						||
        public async Task<IEnumerable<TEntity>> AddRangeAsync(IEnumerable<TEntity> entities, bool isSaveAudit = false)
 | 
						||
        {
 | 
						||
            foreach (var addEntity in entities)
 | 
						||
            {
 | 
						||
                await AddAsync(addEntity, isSaveAudit);
 | 
						||
            }
 | 
						||
 | 
						||
            return entities;
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>EF跟踪方式 添加</summary>
 | 
						||
        public async ValueTask<TEntity> AddAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default, bool isSaveAudit = false)
 | 
						||
        {
 | 
						||
 | 
						||
            await _dbSet.AddAsync(entity).ConfigureAwait(false);
 | 
						||
 | 
						||
            // 添加稽查
 | 
						||
            //await AddInspectionAsync(entity, isSaveAudit);
 | 
						||
 | 
						||
            if (autoSave)
 | 
						||
            {
 | 
						||
                await SaveChangesAsync(cancellationToken);
 | 
						||
            }
 | 
						||
 | 
						||
            return entity;
 | 
						||
        }
 | 
						||
 | 
						||
 | 
						||
 | 
						||
        public async Task<TEntity> InsertFromDTOAsync<TFrom>(TFrom from, bool autoSave = false, params EntityVerifyExp<TEntity>[] verify)
 | 
						||
        {
 | 
						||
            var entity = _mapper.Map<TEntity>(from);
 | 
						||
 | 
						||
            await EntityVerifyAsync(true, verify);
 | 
						||
 | 
						||
 | 
						||
            entity = await AddAsync(entity, autoSave);
 | 
						||
 | 
						||
 | 
						||
            return entity;
 | 
						||
 | 
						||
        }
 | 
						||
        #endregion
 | 
						||
 | 
						||
 | 
						||
        #region 异步 EF 跟踪  部分字段更新
 | 
						||
 | 
						||
 | 
						||
        /// <summary>用前端传递的视图模型字段,更新,同时返回数据库该条记录的原始信息,方便对比某些字段是否更改,进行相应的逻辑操作</summary>
 | 
						||
 | 
						||
        public async Task<TEntity> UpdateFromDTOAsync<TFrom>(TFrom from, bool autoSave = false, bool ignoreDtoNullProperty = true, params EntityVerifyExp<TEntity>[] verify)
 | 
						||
        {
 | 
						||
 | 
						||
            var entity = _mapper.Map<TEntity>(from);
 | 
						||
 | 
						||
            await EntityVerifyAsync(false, verify, entity.Id);
 | 
						||
 | 
						||
            var dbEntity = await _dbSet.IgnoreQueryFilters().FirstOrDefaultAsync(t => t.Id == entity.Id).ConfigureAwait(false);
 | 
						||
 | 
						||
            if (dbEntity == null)
 | 
						||
            {
 | 
						||
                throw new BusinessValidationFailedException(
 | 
						||
                    " Update object not exist in db,Please check if the parameter Id is passed incorrectly");
 | 
						||
            }
 | 
						||
 | 
						||
            var dbBeforEntity = dbEntity.Clone();
 | 
						||
 | 
						||
 | 
						||
            _mapper.Map(from, dbEntity);
 | 
						||
 | 
						||
 | 
						||
            //DTO  null  属性不更新  防止意外操作,导致保存数据错误,或者 add 和update 用一个模型,更新的时候,只传递了部分字段,导致,不想更新的字段,因为没传递值,用null覆盖了
 | 
						||
            // Guid?属性 为null 时   映射到  Guid 时  默认会变成  Guid.Empty   
 | 
						||
            if (ignoreDtoNullProperty)
 | 
						||
            {
 | 
						||
                var dbEntityProp = typeof(TEntity).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;
 | 
						||
        }
 | 
						||
 | 
						||
 | 
						||
 | 
						||
        /// <summary> EF跟踪方式  生成 部分字段更新, 通过主键id  和表达式树 更新部分字段
 | 
						||
        /// 例如  Guid.Parse("8a90c96e-0776-4f7b-82a6-18933d339584"),u => new Dictionary() { ParentId = null, Code = "test" }默认会去处理更新更新人 更新时间</summary>
 | 
						||
 | 
						||
        public async Task UpdatePartialNoQueryAsync(Guid id, Expression<Func<TEntity, TEntity>> updateFactory, bool autoSave = false, params EntityVerifyExp<TEntity>[] verify)
 | 
						||
        {
 | 
						||
            await SetPartialFieldUpdateAsync(id, updateFactory, verify);
 | 
						||
 | 
						||
            await SaveChangesAsync(autoSave);
 | 
						||
 | 
						||
        }
 | 
						||
 | 
						||
 | 
						||
        /// <summary> EF跟踪方式  生成 部分字段立即更新,默认会去处理更新更新人 更新时间  </summary>
 | 
						||
        public async Task<bool> UpdatePartialNowNoQueryAsync(Guid id, Expression<Func<TEntity, TEntity>> updateFactory,
 | 
						||
            params EntityVerifyExp<TEntity>[] verify)
 | 
						||
        {
 | 
						||
            await SetPartialFieldUpdateAsync(id, updateFactory, verify);
 | 
						||
            return await SaveChangesAsync(true);
 | 
						||
        }
 | 
						||
 | 
						||
 | 
						||
        /// <summary>注意 模型标注了 ConcurrencyCheck的属性,这样的实体,不适合用部分字段更新,ef生成的更新sql会自动带上ConcurrencyCheck的属性条件</summary>
 | 
						||
        private async Task SetPartialFieldUpdateAsync(Guid id, Expression<Func<TEntity, TEntity>> updateFactory, params EntityVerifyExp<TEntity>[] verify)
 | 
						||
        {
 | 
						||
            await EntityVerifyAsync(false, verify, id);
 | 
						||
 | 
						||
            var entity = new TEntity() { Id = id };
 | 
						||
 | 
						||
            var entityEntry = _dbContext.Entry(entity);
 | 
						||
 | 
						||
            entityEntry.State = EntityState.Detached;
 | 
						||
 | 
						||
 | 
						||
            List<PropertyInfo> list = ((MemberInitExpression)updateFactory.Body).Bindings.Select(mb => mb.Member.Name)
 | 
						||
                .Select(propName => typeof(TEntity).GetProperty(propName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)).ToList();
 | 
						||
 | 
						||
            Func<TEntity, TEntity> func = updateFactory.Compile();
 | 
						||
 | 
						||
            TEntity applyObj = func(entity);
 | 
						||
 | 
						||
            foreach (PropertyInfo prop in list)
 | 
						||
            {
 | 
						||
                object value = prop.GetValue((object)applyObj);
 | 
						||
                prop.SetValue((object)entity, value);
 | 
						||
 | 
						||
                _dbContext.Entry(entity).Property(prop.Name).IsModified = true;
 | 
						||
            }
 | 
						||
 | 
						||
            #region Test
 | 
						||
 | 
						||
 | 
						||
            //updateFactory.Compile()(entity);
 | 
						||
 | 
						||
            //List<string> propNameList = ((MemberInitExpression)updateFactory.Body).Bindings.Select(mb => mb.Member.Name).ToList();
 | 
						||
 | 
						||
            //foreach (string propName in propNameList)
 | 
						||
            //{
 | 
						||
            //    _dbContext.Entry(entity).Property(propName).IsModified = true;
 | 
						||
            //}
 | 
						||
 | 
						||
            #endregion
 | 
						||
        }
 | 
						||
 | 
						||
 | 
						||
        #endregion
 | 
						||
 | 
						||
 | 
						||
        #region 异步  EF 跟踪 自动生成 更新 和删除语句
 | 
						||
 | 
						||
 | 
						||
        /// <summary>EF跟踪方式 更新,全字段更新  不好</summary>
 | 
						||
        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;
 | 
						||
            }
 | 
						||
        }
 | 
						||
 | 
						||
 | 
						||
        /// <summary>EF跟踪方式  外层先有查询好的完成实体,再更新部分字段  稽查的时候需要完整的实体信息</summary>
 | 
						||
        public async Task<bool> UpdateAsync(TEntity waitModifyEntity, Expression<Func<TEntity, TEntity>> updateFactory, bool autoSave = false, CancellationToken cancellationToken = default)
 | 
						||
        {
 | 
						||
            var entityEntry = _dbContext.Entry(waitModifyEntity);
 | 
						||
            entityEntry.State = EntityState.Detached;
 | 
						||
 | 
						||
 | 
						||
            ModifyPartialFiled(waitModifyEntity, updateFactory);
 | 
						||
 | 
						||
            return await SaveChangesAsync(autoSave);
 | 
						||
 | 
						||
        }
 | 
						||
 | 
						||
 | 
						||
        /// <summary>EF跟踪方式  先查询出来,再更新部分字段 稽查的时候需要完整的实体信息</summary>
 | 
						||
        public async Task<TEntity> UpdatePartialFromQueryAsync(Guid id, Expression<Func<TEntity, TEntity>> updateFactory,
 | 
						||
            bool autoSave = false, bool ignoreQueryFilter = false, CancellationToken cancellationToken = default)
 | 
						||
        {
 | 
						||
 | 
						||
            var query = ignoreQueryFilter ? _dbSet.AsNoTracking().IgnoreQueryFilters() : _dbSet.AsNoTracking();
 | 
						||
            //不跟踪 查询出来的实体就是Detached
 | 
						||
            var searchEntity = await query.FirstOrDefaultAsync(t => t.Id == id);
 | 
						||
 | 
						||
            if (searchEntity == null)
 | 
						||
            {
 | 
						||
                throw new BusinessValidationFailedException(
 | 
						||
                    " Update object not exist in db,Please check if the parameter Id is passed incorrectly");
 | 
						||
            }
 | 
						||
 | 
						||
 | 
						||
            ModifyPartialFiled(searchEntity, updateFactory);
 | 
						||
 | 
						||
 | 
						||
            await SaveChangesAsync(autoSave);
 | 
						||
 | 
						||
            return searchEntity;
 | 
						||
        }
 | 
						||
 | 
						||
        public async Task UpdatePartialFromQueryAsync(Expression<Func<TEntity, bool>> updateFilter,
 | 
						||
            Expression<Func<TEntity, TEntity>> updateFactory,
 | 
						||
            bool autoSave = false, bool ignoreQueryFilter = false, CancellationToken cancellationToken = default)
 | 
						||
        {
 | 
						||
            if (updateFilter == null)
 | 
						||
            {
 | 
						||
                throw new ArgumentException("更新过滤条件不允许为空", nameof(updateFilter));
 | 
						||
            }
 | 
						||
            var query = ignoreQueryFilter ? _dbSet.AsNoTracking().IgnoreQueryFilters() : _dbSet.AsNoTracking();
 | 
						||
 | 
						||
            var searchEntityList = await query.Where(updateFilter).ToListAsync();
 | 
						||
 | 
						||
            foreach (var needUpdateEntity in searchEntityList)
 | 
						||
            {
 | 
						||
                await UpdateAsync(needUpdateEntity, updateFactory, autoSave);
 | 
						||
            }
 | 
						||
 | 
						||
        }
 | 
						||
 | 
						||
 | 
						||
        /// <summary>更新后拥有完整的实体信息,便于稽查</summary>
 | 
						||
        private void ModifyPartialFiled(TEntity waitModifyEntity, Expression<Func<TEntity, TEntity>> updateFactory)
 | 
						||
        {
 | 
						||
            List<PropertyInfo> list = ((MemberInitExpression)updateFactory.Body).Bindings.Select(mb => mb.Member.Name)
 | 
						||
                .Select(propName => typeof(TEntity).GetProperty(propName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)).ToList();
 | 
						||
 | 
						||
            Func<TEntity, TEntity> func = updateFactory.Compile();
 | 
						||
 | 
						||
            TEntity applyObj = func(waitModifyEntity);
 | 
						||
 | 
						||
            //深拷贝更新之前实体信息
 | 
						||
            //var copyObj = waitModifyEntity.Clone();
 | 
						||
 | 
						||
            foreach (PropertyInfo prop in list)
 | 
						||
            {
 | 
						||
                object value = prop.GetValue(applyObj);
 | 
						||
                prop.SetValue(waitModifyEntity, value);
 | 
						||
 | 
						||
                _dbContext.Entry(waitModifyEntity).Property(prop.Name).IsModified = true;
 | 
						||
            }
 | 
						||
 | 
						||
 | 
						||
        }
 | 
						||
 | 
						||
 | 
						||
        /// <summary>EF跟踪方式 删除</summary>
 | 
						||
        public async Task<bool> DeleteAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default)
 | 
						||
        {
 | 
						||
            _dbSet.Remove(entity);
 | 
						||
 | 
						||
            return await SaveChangesAsync(autoSave);
 | 
						||
        }
 | 
						||
 | 
						||
 | 
						||
        /// <summary>EF跟踪方式(查询出来,再删除 浪费性能,但是稽查 或者触发某些操作时,需要知道数据库实体信息 不可避免用这种)</summary>
 | 
						||
        public async Task<TEntity> DeleteFromQueryAsync(Guid id, bool autoSave = false, bool ignoreQueryFilter = false)
 | 
						||
        {
 | 
						||
            var query = ignoreQueryFilter ? _dbSet.AsNoTracking().IgnoreQueryFilters() : _dbSet.AsNoTracking();
 | 
						||
 | 
						||
            var waitDelete = await query.Where(t => t.Id == id).FirstOrDefaultAsync();
 | 
						||
 | 
						||
            if (waitDelete == null)
 | 
						||
            {
 | 
						||
                throw new BusinessValidationFailedException(
 | 
						||
                    " Delete object not exist in db,Please check if the parameter Id is passed incorrectly");
 | 
						||
            }
 | 
						||
 | 
						||
            await DeleteAsync(waitDelete, autoSave);
 | 
						||
 | 
						||
            return waitDelete;
 | 
						||
        }
 | 
						||
 | 
						||
 | 
						||
        /// <summary>批量删除,EF跟踪方式(所有查询出来,再删除 浪费性能,但是稽查 或者触发某些操作时,需要知道数据库实体信息 不可避免用这种)</summary>
 | 
						||
        public async Task<List<TEntity>> DeleteFromQueryAsync(Expression<Func<TEntity, bool>> deleteFilter, bool autoSave = false, bool ignoreQueryFilter = false)
 | 
						||
        {
 | 
						||
            var query = ignoreQueryFilter ? _dbSet.AsNoTracking().IgnoreQueryFilters() : _dbSet.AsNoTracking();
 | 
						||
            var waitDeleteList = await query.Where(deleteFilter).ToListAsync();
 | 
						||
 | 
						||
            foreach (var deleteItem in waitDeleteList)
 | 
						||
            {
 | 
						||
                await DeleteAsync(deleteItem, false);
 | 
						||
            }
 | 
						||
 | 
						||
            await SaveChangesAsync(autoSave);
 | 
						||
 | 
						||
            return waitDeleteList;
 | 
						||
 | 
						||
        }
 | 
						||
 | 
						||
        public async Task<List<TEntity>> SoftDeleteFromQueryAsync(Expression<Func<TEntity, bool>> deleteFilter, bool autoSave = false, bool ignoreQueryFilter = false)
 | 
						||
        {
 | 
						||
            var query = ignoreQueryFilter ? _dbSet.IgnoreQueryFilters() : _dbSet;
 | 
						||
            var waitDeleteList =  await query.Where(deleteFilter).ToListAsync();
 | 
						||
     
 | 
						||
            foreach (var deleteItem in waitDeleteList)
 | 
						||
            {
 | 
						||
                if(deleteItem is ISoftDelete softDeleteItem)
 | 
						||
                {
 | 
						||
                    softDeleteItem.IsDeleted = true;
 | 
						||
                }
 | 
						||
            }
 | 
						||
 | 
						||
            await SaveChangesAsync(autoSave);
 | 
						||
 | 
						||
            return waitDeleteList;
 | 
						||
        }
 | 
						||
 | 
						||
        #endregion
 | 
						||
 | 
						||
 | 
						||
 | 
						||
        #region 不走EF 跟踪机制的删除 更新  以及批量操作
 | 
						||
 | 
						||
        /// <summary>批量删除,相当于原生sql,  没用EF跟踪方式(所有查询出来,再删除 浪费性能)</summary>
 | 
						||
        public async Task<bool> BatchDeleteNoTrackingAsync(Expression<Func<TEntity, bool>> deleteFilter)
 | 
						||
        {
 | 
						||
            return await _dbSet.IgnoreQueryFilters().Where(deleteFilter).BatchDeleteAsync() > 0;
 | 
						||
        }
 | 
						||
 | 
						||
 | 
						||
        /// <summary>批量更新,相当于原生sql,  没用EF跟踪方式(所有查询出来,再更新 浪费性能)</summary>
 | 
						||
        public async Task<bool> BatchUpdateNoTrackingAsync(Expression<Func<TEntity, bool>> where,
 | 
						||
            Expression<Func<TEntity, TEntity>> updateFactory)
 | 
						||
        {
 | 
						||
 | 
						||
            var bindings = ((MemberInitExpression)updateFactory.Body).Bindings.ToList();
 | 
						||
 | 
						||
            var hasPropNameList = bindings.Select(t => t.Member.Name).ToList();
 | 
						||
 | 
						||
 | 
						||
            if (typeof(IAuditUpdate).IsAssignableFrom(typeof(TEntity)))
 | 
						||
            {
 | 
						||
 | 
						||
                if (!hasPropNameList.Contains(nameof(IAuditUpdate.UpdateTime)))
 | 
						||
                {
 | 
						||
                    bindings.Add(Expression.Bind(typeof(TEntity).GetMember(nameof(IAuditUpdate.UpdateTime))[0], Expression.Constant(DateTime.Now)));
 | 
						||
 | 
						||
                }
 | 
						||
 | 
						||
                if (!hasPropNameList.Contains(nameof(IAuditUpdate.UpdateUserId)))
 | 
						||
                {
 | 
						||
                    bindings.Add(Expression.Bind(typeof(TEntity).GetMember(nameof(IAuditUpdate.UpdateUserId))[0], Expression.Constant(_userInfo.Id)));
 | 
						||
 | 
						||
                }
 | 
						||
            }
 | 
						||
 | 
						||
 | 
						||
            var member = Expression.MemberInit(Expression.New(typeof(TEntity)), bindings);
 | 
						||
 | 
						||
            var factory = Expression.Lambda<Func<TEntity, TEntity>>(member, Expression.Parameter(typeof(TEntity), "x"));
 | 
						||
 | 
						||
 | 
						||
            return await _dbSet.IgnoreQueryFilters().Where(where).BatchUpdateAsync(factory) > 0;
 | 
						||
 | 
						||
 | 
						||
 | 
						||
        }
 | 
						||
 | 
						||
        #endregion
 | 
						||
 | 
						||
 | 
						||
        #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)
 | 
						||
            {
 | 
						||
                return await InsertFromDTOAsync(from, autoSave, verify);
 | 
						||
            }
 | 
						||
            else
 | 
						||
            {
 | 
						||
                return await UpdateFromDTOAsync(from, autoSave, false, verify);
 | 
						||
            }
 | 
						||
        }
 | 
						||
        private async Task EntityVerifyAsync(bool isAdd, EntityVerifyExp<TEntity>[] verify, Guid? entitydId = null)
 | 
						||
        {
 | 
						||
 | 
						||
            if (isAdd)
 | 
						||
            {
 | 
						||
                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);
 | 
						||
                    }
 | 
						||
                }
 | 
						||
            }
 | 
						||
            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 != entitydId)).ConfigureAwait(false))
 | 
						||
                        {
 | 
						||
                            throw new BusinessValidationFailedException(verifyItem.VerifyMsg);
 | 
						||
                        }
 | 
						||
                    }
 | 
						||
                }
 | 
						||
            }
 | 
						||
 | 
						||
        }
 | 
						||
 | 
						||
        private async Task<bool> SaveChangesAsync(bool autoSave)
 | 
						||
        {
 | 
						||
            if (autoSave)
 | 
						||
            {
 | 
						||
                return await SaveChangesAsync();
 | 
						||
            }
 | 
						||
            else
 | 
						||
            {
 | 
						||
                return false;
 | 
						||
            }
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 忽略空值属性
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="entity"></param>
 | 
						||
        /// <param name="ignoreNullValues"></param>
 | 
						||
        private void IgnoreNullValues(ref TEntity entity, bool? ignoreNullValues = null)
 | 
						||
        {
 | 
						||
            var isIgnore = ignoreNullValues;
 | 
						||
            if (isIgnore == false) return;
 | 
						||
 | 
						||
            // 获取所有的属性
 | 
						||
            var properties = _dbSet.EntityType.GetProperties();
 | 
						||
            if (properties == null) return;
 | 
						||
 | 
						||
            foreach (var propety in properties)
 | 
						||
            {
 | 
						||
                var entityProperty = _dbContext.Entry(entity).Property(propety.Name);
 | 
						||
                var propertyValue = entityProperty?.CurrentValue;
 | 
						||
                var propertyType = entityProperty?.Metadata?.PropertyInfo?.PropertyType;
 | 
						||
 | 
						||
                // 判断是否是无效的值,比如为 null,默认时间,以及空 Guid 值
 | 
						||
                var isInvalid = propertyValue == null
 | 
						||
                                || (propertyType == typeof(DateTime) && propertyValue?.ToString() == new DateTime().ToString())
 | 
						||
                                || (propertyType == typeof(DateTimeOffset) && propertyValue?.ToString() == new DateTimeOffset().ToString())
 | 
						||
                                || (propertyType == typeof(Guid) && propertyValue?.ToString() == Guid.Empty.ToString());
 | 
						||
 | 
						||
                if (isInvalid && entityProperty != null)
 | 
						||
                {
 | 
						||
                    entityProperty.IsModified = false;
 | 
						||
                }
 | 
						||
            }
 | 
						||
        }
 | 
						||
 | 
						||
 | 
						||
        public async Task<bool> SaveChangesAsync(CancellationToken cancellationToken = default)
 | 
						||
        {
 | 
						||
            return await _dbContext.SaveChangesAsync(cancellationToken) > 0;
 | 
						||
        }
 | 
						||
 | 
						||
 | 
						||
        #endregion
 | 
						||
 | 
						||
        #region 不常用
 | 
						||
        /// <summary>EF跟踪方式  生成 部分字段更新  (只更新传递的字段名 new[] {nameof(User.Name), nameof(User.Age))</summary>
 | 
						||
        public async Task<TEntity> UpdatePartialFieldsAsync(TEntity entity, string[] propertyNames,
 | 
						||
            bool autoSave = false, bool ignoreEntityNullProperty = true, params EntityVerifyExp<TEntity>[] verify)
 | 
						||
        {
 | 
						||
            await EntityVerifyAsync(false, verify, entity.Id);
 | 
						||
 | 
						||
            var entityEntry = _dbContext.Entry(entity);
 | 
						||
            entityEntry.State = EntityState.Detached;
 | 
						||
 | 
						||
 | 
						||
            foreach (var propertyName in propertyNames)
 | 
						||
            {
 | 
						||
                _dbContext.Entry(entity).Property(propertyName).IsModified = true;
 | 
						||
            }
 | 
						||
 | 
						||
            // 忽略空值
 | 
						||
            IgnoreNullValues(ref entity, ignoreEntityNullProperty);
 | 
						||
 | 
						||
            return entityEntry.Entity;
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>更新  排除某些字段的更新  排除方式: new[] {nameof(User.Name), nameof(User.Age)</summary>
 | 
						||
        public async Task<TEntity> UpdateExcludeFields(TEntity entity, string[] propertyNames, bool autoSave = false, bool ignoreEntityNullProperty = true, params EntityVerifyExp<TEntity>[] verify)
 | 
						||
        {
 | 
						||
 | 
						||
            await EntityVerifyAsync(false, verify, entity.Id);
 | 
						||
 | 
						||
            var entityEntry = _dbContext.Entry(entity);
 | 
						||
            entityEntry.State = EntityState.Modified;
 | 
						||
 | 
						||
 | 
						||
            foreach (var propertyName in propertyNames)
 | 
						||
            {
 | 
						||
                _dbContext.Entry(entity).Property(propertyName).IsModified = false;
 | 
						||
            }
 | 
						||
 | 
						||
            // 忽略空值
 | 
						||
            IgnoreNullValues(ref entity, ignoreEntityNullProperty);
 | 
						||
 | 
						||
            return entityEntry.Entity;
 | 
						||
        }
 | 
						||
 | 
						||
 | 
						||
        #endregion
 | 
						||
 | 
						||
        #region 稽查
 | 
						||
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 翻译稽查数据
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="dto">传入Dto</param>
 | 
						||
        /// <returns></returns>
 | 
						||
        public async Task<List<string>> SetInspectionEnumValue(SetInspectionEnumValueDto dto)
 | 
						||
        {
 | 
						||
            foreach (var item in dto.Items)
 | 
						||
            {
 | 
						||
                item.Json = await GetInspectionEnumValue(item.Identification, item.Json);
 | 
						||
                item.Json = await SetEnum(dto.TrialId, item.Identification, item.Json);
 | 
						||
                item.Json = await SetDataInspectionDateType(item.Identification, item.Json);
 | 
						||
            }
 | 
						||
            return dto.Items.Select(x => x.Json).ToList();
 | 
						||
        }
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 格式化日期和时间
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="Data">稽查数据</param>
 | 
						||
        /// <returns></returns>
 | 
						||
        public async Task<string> SetDataInspectionDateType(string identification, string json)
 | 
						||
        {
 | 
						||
            var list = await (from parent in _dbContext.FrontAuditConfig.AsQueryable().Where(x => x.Identification == identification)
 | 
						||
                              join child in _dbContext.FrontAuditConfig.AsQueryable().Where(x => x.EnumType == "Date" && x.IsEnable.HasValue && x.IsEnable.Value) on parent.Id equals child.ParentId
 | 
						||
                              select new DateDto()
 | 
						||
                              {
 | 
						||
                                  Code = child.Code,
 | 
						||
                                  DateType = child.DateType,
 | 
						||
                              }).ToListAsync();
 | 
						||
 | 
						||
            var JsonData = JsonConvert.DeserializeObject<IDictionary<string, object>>(json);
 | 
						||
 | 
						||
            if (JsonData == null)
 | 
						||
            {
 | 
						||
                return json;
 | 
						||
            }
 | 
						||
 | 
						||
            foreach (var item in JsonData.Keys)
 | 
						||
            {
 | 
						||
                var datefirst = list.FirstOrDefault(x => x.Code.ToLower() == item.ToLower());
 | 
						||
                if (datefirst != null && !IsNullOrEmpty(JsonData[item]))
 | 
						||
                {
 | 
						||
                    try
 | 
						||
                    {
 | 
						||
                        if (datefirst.DateType == "Date")
 | 
						||
                        {
 | 
						||
                            JsonData[item] = DateTime.Parse(JsonData[item].ToString()).ToString("yyyy-MM-dd");
 | 
						||
                        }
 | 
						||
 | 
						||
                        if (datefirst.DateType == "DateTime")
 | 
						||
                        {
 | 
						||
                            JsonData[item] = DateTime.Parse(JsonData[item].ToString()).ToString("yyyy-MM-dd HH:mm:ss");
 | 
						||
                        }
 | 
						||
                    }
 | 
						||
                    catch (Exception)
 | 
						||
                    {
 | 
						||
                        continue;
 | 
						||
                    }
 | 
						||
                }
 | 
						||
 | 
						||
            }
 | 
						||
 | 
						||
            return JsonConvert.SerializeObject(JsonData);
 | 
						||
 | 
						||
          
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 获取外键表数据
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="Table">表名称</param>
 | 
						||
        /// <param name="ForeignKeyValue">外键value</param>
 | 
						||
        /// <param name="ForeignKeyText">要查询的外键值</param>
 | 
						||
        /// <param name="value">传入的纸</param>
 | 
						||
        /// <returns></returns>
 | 
						||
        public async Task<string> GetInspectionEnumValue(string identification, string json)
 | 
						||
        {
 | 
						||
            var list = await (from u in _dbContext.FrontAuditConfig.Where(x => x.Identification == identification)
 | 
						||
                              join p in _dbContext.FrontAuditConfig.Where(x => x.EnumType == "Foreign" && x.IsEnable.HasValue && x.IsEnable.Value) on u.Id equals p.ParentId
 | 
						||
                              select new
 | 
						||
                              {
 | 
						||
                                  Key = p.Code,
 | 
						||
                                  ForeignKeyValue = p.ForeignKeyValue,
 | 
						||
                                  ForeignKeyText = p.ForeignKeyText,
 | 
						||
                                  ForeignKeyTable = p.ForeignKeyTable
 | 
						||
                              }).ToListAsync();
 | 
						||
 | 
						||
            var JsonDataValue = JsonConvert.DeserializeObject<IDictionary<string, object>>(json);
 | 
						||
            foreach (var item in list)
 | 
						||
            {
 | 
						||
                if (!JsonDataValue.ContainsKey(item.Key))
 | 
						||
                {
 | 
						||
                    continue;
 | 
						||
                }
 | 
						||
                string Table = item.ForeignKeyTable;
 | 
						||
                string ForeignKeyValue = item.ForeignKeyValue;
 | 
						||
                string ForeignKeyText = item.ForeignKeyText;
 | 
						||
                string value = JsonDataValue[item.Key].ToString();
 | 
						||
                string para = string.Empty;
 | 
						||
                string sql = string.Empty;
 | 
						||
                var JsonData = JsonConvert.DeserializeObject<IDictionary<string, object>>(JsonConvert.SerializeObject(new { item = value }));
 | 
						||
                if (JsonData["item"].GetType() == typeof(JArray))
 | 
						||
                {
 | 
						||
                    foreach (var v in JsonData["item"] as JArray)
 | 
						||
                    {
 | 
						||
                        para += para == string.Empty ? $"'{v.ToString()}'" : $",'{v.ToString()}'";
 | 
						||
                    }
 | 
						||
                    sql = $"select {ForeignKeyText} Text from {Table} where {ForeignKeyValue} in (@para)";
 | 
						||
                }
 | 
						||
                else
 | 
						||
                {
 | 
						||
                    para = $"{JsonData["item"].ToString()}";
 | 
						||
                    sql = $"select {ForeignKeyText}  Text from {Table} where {ForeignKeyValue} = @para";
 | 
						||
                }
 | 
						||
                SqlParameter[] paravalue = new SqlParameter[] {
 | 
						||
                   new SqlParameter("@para",para)
 | 
						||
                                             };
 | 
						||
                JsonDataValue[item.Key] = string.Join(",", _dbContext.Database.SqlQuery<ForeignKey>(sql, paravalue).Select(x => x.Text).ToList());
 | 
						||
            }
 | 
						||
            return JsonConvert.SerializeObject(JsonDataValue);
 | 
						||
 | 
						||
        }
 | 
						||
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 获取枚举
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="Identification">标识</param>
 | 
						||
        /// <param name="json">Json对象</param>
 | 
						||
        /// <returns></returns>
 | 
						||
        /// <exception cref="BusinessValidationFailedException"></exception>
 | 
						||
        public async Task<string> SetEnum(Guid trilaid, string identification, string json)
 | 
						||
        {
 | 
						||
            var list = await (from u in _dbContext.FrontAuditConfig.Where(x => x.Identification == identification)
 | 
						||
                              join p in _dbContext.FrontAuditConfig.Where(x => x.Code != "AuditState" && x.EnumType == "Dictionary"&&x.IsEnable.HasValue&& x.IsEnable.Value) on u.Id equals p.ParentId
 | 
						||
                              select new
 | 
						||
                              {
 | 
						||
                                  Key = p.Code,
 | 
						||
                                  Code = p.DictionaryCode,
 | 
						||
                                  Type = p.DictionaryType
 | 
						||
                              }).ToListAsync();
 | 
						||
 | 
						||
            // 添加单双审
 | 
						||
            var trialtype = await _dbContext.Trial.AsQueryable().Where(x => x.Id == trilaid).Select(x => x.QCProcessEnum).FirstOrDefaultAsync();
 | 
						||
 | 
						||
            list.Add(new
 | 
						||
            {
 | 
						||
 | 
						||
                Key = "AuditState",
 | 
						||
                Code = trialtype == TrialQCProcess.SingleAudit ? "AuditStateRC" : "AuditStatePE",
 | 
						||
                Type = "Code",
 | 
						||
            });
 | 
						||
 | 
						||
            var JsonData = JsonConvert.DeserializeObject<IDictionary<string, object>>(json);
 | 
						||
            foreach (var item in list)
 | 
						||
            {
 | 
						||
                try
 | 
						||
                {
 | 
						||
 | 
						||
                    if (!JsonData.ContainsKey(item.Key))
 | 
						||
                    {
 | 
						||
                        continue;
 | 
						||
                    }
 | 
						||
                    var value = JsonData[item.Key];
 | 
						||
                    if (value.GetType() == typeof(JArray))
 | 
						||
                    {
 | 
						||
                        JArray arrays = (JArray)value;
 | 
						||
                        if (item.Type.ToLower() == "id".ToLower())
 | 
						||
                        {
 | 
						||
                            List<Guid> guids = new List<Guid>();
 | 
						||
                            arrays.ForEach(x =>
 | 
						||
                            {
 | 
						||
                                guids.Add(Guid.Parse(x.ToString()));
 | 
						||
                            });
 | 
						||
                            JsonData[item.Key] = string.Join(',', await _dbContext.Dictionary.Where(x => guids.Contains(x.Id)).Select(x => x.ValueCN).ToListAsync());
 | 
						||
                        }
 | 
						||
                        else if (item.Type.ToLower() == "ChildGroup".ToLower())
 | 
						||
                        {
 | 
						||
                            List<string> guids = new List<string>();
 | 
						||
                            arrays.ForEach(x =>
 | 
						||
                            {
 | 
						||
                                guids.Add(x.ToString());
 | 
						||
                            });
 | 
						||
                            JsonData[item.Key] = string.Join(',', await
 | 
						||
                               _dbContext.Dictionary.Where(x => x.Code == item.Code).GroupJoin(
 | 
						||
                                    _dbContext.Dictionary.Where(x => guids.Contains(x.ChildGroup)), a => a.Id, b => b.ParentId, (a, b) => new
 | 
						||
                                    {
 | 
						||
                                        parent = b
 | 
						||
                                    }).SelectMany(a => a.parent, (m, n) => new
 | 
						||
                                    {
 | 
						||
                                        value = n.ValueCN
 | 
						||
                                    }).Select(x => x.value).ToListAsync()
 | 
						||
                                    );
 | 
						||
                        }
 | 
						||
                        else
 | 
						||
                        {
 | 
						||
                            List<string> guids = new List<string>();
 | 
						||
                            arrays.ForEach(x =>
 | 
						||
                            {
 | 
						||
                                guids.Add(x.ToString());
 | 
						||
                            });
 | 
						||
                            JsonData[item.Key] = string.Join(',', await
 | 
						||
                                _dbContext.Dictionary.Where(x => x.Code == item.Code).GroupJoin(
 | 
						||
                                     _dbContext.Dictionary.Where(x => guids.Contains(x.Code)), a => a.Id, b => b.ParentId, (a, b) => new
 | 
						||
                                     {
 | 
						||
                                         parent = b
 | 
						||
                                     }).SelectMany(a => a.parent, (m, n) => new
 | 
						||
                                     {
 | 
						||
                                         value = n.ValueCN
 | 
						||
                                     }).Select(x => x.value).ToListAsync()
 | 
						||
                                    );
 | 
						||
                        }
 | 
						||
                    }
 | 
						||
                    else
 | 
						||
                    {
 | 
						||
                        if (item.Type.ToLower() == "id".ToLower())
 | 
						||
                        {
 | 
						||
                            Guid guid = Guid.Parse(value.ToString());
 | 
						||
                            JsonData[item.Key] = await _dbContext.Dictionary.Where(x => guid == x.Id).Select(x => x.ValueCN).FirstOrDefaultAsync();
 | 
						||
                        }
 | 
						||
                        else if (item.Type.ToLower() == "ChildGroup".ToLower())
 | 
						||
                        {
 | 
						||
                            JsonData[item.Key] = await _dbContext.Dictionary.Where(x => x.Code == item.Code).Join(_dbContext.Dictionary.Where(x => x.ChildGroup == value.ToString()), a => a.Id, b => b.ParentId, (a, b) => new
 | 
						||
                            {
 | 
						||
                                value = b.ValueCN
 | 
						||
                            }).Select(x => x.value).FirstOrDefaultAsync();
 | 
						||
                        }
 | 
						||
                        else
 | 
						||
                        {
 | 
						||
                            JsonData[item.Key] = await _dbContext.Dictionary.Where(x => x.Code == item.Code).Join(_dbContext.Dictionary.Where(x => x.Code == value.ToString()), a => a.Id, b => b.ParentId, (a, b) => new
 | 
						||
                            {
 | 
						||
                                value = b.ValueCN
 | 
						||
                            }).Select(x => x.value).FirstOrDefaultAsync();
 | 
						||
 | 
						||
                        }
 | 
						||
                    }
 | 
						||
                }
 | 
						||
                catch (Exception)
 | 
						||
                {
 | 
						||
 | 
						||
                    //throw new BusinessValidationFailedException("Json 对象枚举异常");
 | 
						||
                }
 | 
						||
            }
 | 
						||
 | 
						||
 | 
						||
 | 
						||
            return JsonConvert.SerializeObject(JsonData);
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 添加稽查记录
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="entity">实体</param>
 | 
						||
        /// <param name="isSaveAudit">是否保存</param>
 | 
						||
        /// <returns></returns>
 | 
						||
        private async Task AddInspectionAsync(TEntity entity, bool isSaveAudit = false)
 | 
						||
        {
 | 
						||
            bool needsave = true;
 | 
						||
            DataInspection inspectionData = new DataInspection()
 | 
						||
            {
 | 
						||
                Identification = $"{GetRequestUrl()}/{ typeof(TEntity).ToString().Substring(typeof(TEntity).ToString().LastIndexOf('.') + 1)}/Add",
 | 
						||
            };
 | 
						||
 | 
						||
 | 
						||
            MapData(entity, inspectionData);
 | 
						||
 | 
						||
            var createtime = DateTime.Now;
 | 
						||
            // 项目
 | 
						||
            if (typeof(TEntity) == typeof(Trial))
 | 
						||
            {
 | 
						||
                Trial data = entity as Trial;
 | 
						||
                inspectionData = new DataInspection()
 | 
						||
                {
 | 
						||
                    TrialId = data.Id,
 | 
						||
                    SubjectId = data.Id,
 | 
						||
                    TrialName = data.ExperimentName,
 | 
						||
                    ResearchProgramNo = data.ResearchProgramNo,
 | 
						||
                    IsSign = false,
 | 
						||
                    CreateTime = createtime,
 | 
						||
                    Identification = "Init|Trial|Status|Trial Setting-Infomation",   // 初始化项目
 | 
						||
                    JsonDetail = entity.ToJcJson()
 | 
						||
                };
 | 
						||
            }
 | 
						||
            // 项目人员
 | 
						||
            else if (typeof(TEntity) == typeof(TrialUser))
 | 
						||
            {
 | 
						||
 | 
						||
            }
 | 
						||
            // 受试者
 | 
						||
            else if (typeof(TEntity) == typeof(Subject))
 | 
						||
            {
 | 
						||
                Subject data = entity as Subject;
 | 
						||
                inspectionData = new DataInspection()
 | 
						||
                {
 | 
						||
                    TrialId = data.TrialId,
 | 
						||
                    SiteId = data.SiteId,
 | 
						||
                    SubjectId = data.Id,
 | 
						||
                    SubjectCode = data.Code,
 | 
						||
                    IsSign = false,
 | 
						||
                    CreateTime = createtime,
 | 
						||
                    Identification = "Init|Subject|Status|Subject",   // 初始化受试者信息
 | 
						||
                    JsonDetail = entity.ToJcJson()
 | 
						||
                };
 | 
						||
            }
 | 
						||
 | 
						||
            // Dicom序列   // 移动不进来
 | 
						||
            //if (typeof(TEntity) == typeof(DicomSeries))
 | 
						||
            //{
 | 
						||
            //    DicomSeries dicomStudy = entity as DicomSeries;
 | 
						||
            //    datas.Add(new DataInspection()
 | 
						||
            //    {
 | 
						||
 | 
						||
            //        SiteId = dicomStudy.SiteId,
 | 
						||
            //        SubjectId = dicomStudy.SubjectId,
 | 
						||
            //        TrialId = dicomStudy.TrialId,
 | 
						||
            //        GeneralId = dicomStudy.StudyId,
 | 
						||
            //        SubjectVisitId = dicomStudy.SubjectVisitId,
 | 
						||
            //        CreateTime = createtime.AddMilliseconds(10),
 | 
						||
            //        Identification = "Init|DICOM Series|Status|Visit-Image Upload",
 | 
						||
            //        JsonDetail = JsonConvert.SerializeObject(new
 | 
						||
            //        {
 | 
						||
            //            StudyCode = dicomStudy.StudyCode,
 | 
						||
            //            Modalities = dicomStudy.Modalities,
 | 
						||
            //            SeriesNumber = dicomSeries.SeriesNumber,
 | 
						||
            //            InstanceCount = dicomSeries.InstanceCount,
 | 
						||
            //            SeriesTime = dicomSeries.SeriesTime,
 | 
						||
            //            IsReading = dicomSeries.IsReading,
 | 
						||
            //            IsDeleted = dicomSeries.IsReading,
 | 
						||
 | 
						||
            //        })
 | 
						||
            //    });
 | 
						||
            //}
 | 
						||
            // dicom影像
 | 
						||
            else if (typeof(TEntity) == typeof(DicomStudy))
 | 
						||
            {
 | 
						||
                DicomStudy data = entity as DicomStudy;
 | 
						||
                await UpdateSubjectVisit(data.SubjectVisitId, SubmitStateEnum.ToSubmit, "上传Dicom影像");
 | 
						||
            }
 | 
						||
            // 非Dicom影像
 | 
						||
            else if (typeof(TEntity) == typeof(NoneDicomStudyFile))
 | 
						||
            {
 | 
						||
                NoneDicomStudyFile data = entity as NoneDicomStudyFile;
 | 
						||
                var subjectVisitId = await _dbContext.NoneDicomStudy.Where(x => x.Id == data.NoneDicomStudyId).Select(x => x.SubjectVisitId).FirstOrDefaultAsync();
 | 
						||
                await UpdateSubjectVisit(subjectVisitId, SubmitStateEnum.ToSubmit, "上传非Dicom影像");
 | 
						||
            }
 | 
						||
            else
 | 
						||
            {
 | 
						||
                needsave = false;
 | 
						||
            }
 | 
						||
 | 
						||
            // 修改访视状态记录稽查
 | 
						||
            async Task UpdateSubjectVisit(Guid subvisitVisit, SubmitStateEnum submit, string reason)
 | 
						||
            {
 | 
						||
                var subjectvisit = await _dbContext.SubjectVisit.AsNoTracking().AsQueryable().Where(x => x.Id == subvisitVisit).FirstOrDefaultAsync();
 | 
						||
                if (subjectvisit.SubmitState != submit)
 | 
						||
                {
 | 
						||
                    subjectvisit.SubmitState = submit;
 | 
						||
 | 
						||
                    inspectionData = new DataInspection()
 | 
						||
                    {
 | 
						||
                        Identification = "Edit|Visit|Status|Visit-Image Upload|Add Image",
 | 
						||
                        TrialId = subjectvisit.TrialId,
 | 
						||
                        SiteId = subjectvisit.SiteId,
 | 
						||
                        SubjectId = subjectvisit.SubjectId,
 | 
						||
                        SubjectVisitId = subjectvisit.Id,
 | 
						||
                        Reason = reason,
 | 
						||
                        CreateTime = createtime.AddMilliseconds(100),
 | 
						||
                        JsonDetail = subjectvisit.ToJcJson(),
 | 
						||
                    };
 | 
						||
                }
 | 
						||
 | 
						||
            }
 | 
						||
 | 
						||
 | 
						||
            if (needsave)
 | 
						||
            {
 | 
						||
                await AddInspectionRecordAsync(inspectionData, entity);
 | 
						||
            }
 | 
						||
 | 
						||
        }
 | 
						||
 | 
						||
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 获取URl参数
 | 
						||
        /// </summary>
 | 
						||
        /// <returns></returns>
 | 
						||
        private string GetRequestUrl()
 | 
						||
        {
 | 
						||
            return _userInfo.RequestUrl;
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 映射数据
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="data"></param>
 | 
						||
        /// <param name="mapData">要赋值的对象</param>
 | 
						||
        private void MapData(dynamic data, dynamic mapData)
 | 
						||
        {
 | 
						||
            List<string> column = new List<string>() { "TrialId", "SiteId", "SubjectId", "SubjectVisitId", "CreateUserName", "TrialName", "SiteName", "SubjectCode", "SubjectVisitName", "RoleName", "SiteCode", "ResearchProgramNo" };
 | 
						||
            foreach (var item in column)
 | 
						||
            {
 | 
						||
                try
 | 
						||
                {
 | 
						||
                    var i = mapData.GetType().GetProperty(item).GetValue(mapData);
 | 
						||
                    if (i == null)
 | 
						||
                    {
 | 
						||
                        var value = data.GetType().GetProperty(item).GetValue(data);
 | 
						||
                        mapData.GetType().GetProperty(item).SetValue(mapData, value);
 | 
						||
                    }
 | 
						||
 | 
						||
                }
 | 
						||
                catch (Exception)
 | 
						||
                {
 | 
						||
                    continue;
 | 
						||
 | 
						||
                }
 | 
						||
            }
 | 
						||
        }
 | 
						||
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 添加稽查记录
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="add">稽查数据</param>
 | 
						||
        /// <param name="data">实体信息</param>
 | 
						||
        /// <returns></returns>
 | 
						||
        public async Task AddInspectionRecordAsync(DataInspection add, dynamic data)
 | 
						||
        {
 | 
						||
            InspectionGeneralData generalData = new InspectionGeneralData();
 | 
						||
            MapData(add, generalData);
 | 
						||
            await SetInspectionNameValue(generalData);
 | 
						||
            #region 处理标识
 | 
						||
            try
 | 
						||
            {
 | 
						||
                var from = await _dbContext.FrontAuditConfig.FirstOrDefaultAsync(x => x.Identification == add.Identification);
 | 
						||
                add.ObjectType = from?.ObjectTypeId;
 | 
						||
                add.OptType = from?.OptTypeId;
 | 
						||
                add.ChildrenType = from?.ChildrenTypeId;
 | 
						||
                add.ModuleType = from?.ModuleTypeId;
 | 
						||
            }
 | 
						||
            catch (Exception)
 | 
						||
            {
 | 
						||
 | 
						||
                throw new BusinessValidationFailedException("操作标识异常");
 | 
						||
            }
 | 
						||
            #endregion
 | 
						||
            if (add.ParentId == null)
 | 
						||
            {
 | 
						||
                add.ParentId = (await _dbContext.DataInspection.AsQueryable().Where(x => x.TrialId == add.TrialId && x.SubjectVisitId == add.SubjectVisitId && x.SubjectId == add.SubjectId && x.SiteId == add.SiteId && x.ChildrenType == add.ChildrenType && x.ObjectType == add.ObjectType && x.VisitStageId == add.VisitStageId && x.GeneralId == add.GeneralId).OrderByDescending(x => x.CreateTime).FirstOrDefaultAsync())?.Id;
 | 
						||
 | 
						||
            }
 | 
						||
            add.CreateUserId = _userInfo.Id;
 | 
						||
            add.IP = _userInfo.IP;
 | 
						||
            if (add.CreateTime == default(DateTime))
 | 
						||
            {
 | 
						||
                add.CreateTime = DateTime.Now;
 | 
						||
            }
 | 
						||
            var inspectionData = new InspectionData()
 | 
						||
            {
 | 
						||
                Data = data,
 | 
						||
                Inspection = generalData
 | 
						||
            };
 | 
						||
 | 
						||
            add.JsonDetail = inspectionData.ToJcJson();
 | 
						||
            await SetDataInspectionDateType(add);
 | 
						||
 | 
						||
            await _dbContext.DataInspection.AddAsync(add);
 | 
						||
        }
 | 
						||
 | 
						||
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 添加稽查记录
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="datas"></param>
 | 
						||
        /// <returns></returns>
 | 
						||
        public async Task AddListInspectionRecordAsync(List<DataInspection> datas)
 | 
						||
        {
 | 
						||
 | 
						||
            //var trialIds= datas.Select(x=>x.TrialId).Distinct().ToList();
 | 
						||
            //var subjectVisitIds= datas.Select(x=>x.SubjectVisitId).Distinct().ToList();
 | 
						||
            //var subjectIds = datas.Select(x => x.SubjectId).Distinct().ToList();
 | 
						||
            //var siteIds = datas.Select(x => x.SiteId).Distinct().ToList();
 | 
						||
            //var childrenTypes= datas.Select(x => x.ChildrenType).Distinct().ToList();
 | 
						||
            //var objectTypes = datas.Select(x => x.ObjectType).Distinct().ToList();
 | 
						||
 | 
						||
            foreach (var add in datas)
 | 
						||
            {
 | 
						||
                await SetInspectionNameValue(add);
 | 
						||
                if (add.ParentId == null)
 | 
						||
                {
 | 
						||
                    add.ParentId = (await _dbContext.DataInspection.AsQueryable().Where(x => x.TrialId == add.TrialId && x.SubjectVisitId == add.SubjectVisitId && x.SubjectId == add.SubjectId && x.SiteId == add.SiteId && x.ChildrenType == add.ChildrenType && x.ObjectType == add.ObjectType && x.VisitStageId == add.VisitStageId && x.GeneralId == add.GeneralId).OrderByDescending(x => x.CreateTime).FirstOrDefaultAsync())?.Id;
 | 
						||
 | 
						||
                }
 | 
						||
                add.CreateUserId = _userInfo.Id;
 | 
						||
                add.IP = _userInfo.IP;
 | 
						||
                if (add.CreateTime == default(DateTime))
 | 
						||
                {
 | 
						||
                    add.CreateTime = DateTime.Now;
 | 
						||
                }
 | 
						||
                //add.JsonDetail = await SetEnum(add.TrialId, add.Identification, add.JsonDetail);
 | 
						||
                await SetDataInspectionDateType(add);
 | 
						||
            }
 | 
						||
 | 
						||
            //await _dbContext.DataInspection.AddRangeAsync(datas);
 | 
						||
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 格式化日期和时间
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="Data">稽查数据</param>
 | 
						||
        /// <returns></returns>
 | 
						||
        public async Task<DataInspection> SetDataInspectionDateType(DataInspection Data)
 | 
						||
        {
 | 
						||
            var list = await (from parent in _dbContext.FrontAuditConfig.AsQueryable().Where(x => x.Identification == Data.Identification)
 | 
						||
                              join child in _dbContext.FrontAuditConfig.AsQueryable().Where(x => x.EnumType == "Date") on parent.Id equals child.ParentId
 | 
						||
                              select new DateDto()
 | 
						||
                              {
 | 
						||
                                  Code = child.Code,
 | 
						||
                                  DateType = child.DateType,
 | 
						||
                              }).ToListAsync();
 | 
						||
 | 
						||
            var JsonData = JsonConvert.DeserializeObject<IDictionary<string, object>>(Data.JsonDetail);
 | 
						||
 | 
						||
            foreach (var item in JsonData.Keys)
 | 
						||
            {
 | 
						||
                var datefirst = list.FirstOrDefault(x => x.Code.ToLower() == item.ToLower());
 | 
						||
                if (datefirst != null && !IsNullOrEmpty(JsonData[item]))
 | 
						||
                {
 | 
						||
                    try
 | 
						||
                    {
 | 
						||
                        if (datefirst.DateType == "Date")
 | 
						||
                        {
 | 
						||
                            JsonData[item] = DateTime.Parse(JsonData[item].ToString()).ToString("yyyy-MM-dd");
 | 
						||
                        }
 | 
						||
 | 
						||
                        if (datefirst.DateType == "DateTime")
 | 
						||
                        {
 | 
						||
                            JsonData[item] = DateTime.Parse(JsonData[item].ToString()).ToString("yyyy-MM-dd HH:mm:ss");
 | 
						||
                        }
 | 
						||
                    }
 | 
						||
                    catch (Exception)
 | 
						||
                    {
 | 
						||
                        continue;
 | 
						||
                    }
 | 
						||
                }
 | 
						||
 | 
						||
            }
 | 
						||
            Data.JsonDetail = JsonConvert.SerializeObject(JsonData);
 | 
						||
 | 
						||
            return Data;
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// IsNullOrEmpty
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="value"></param>
 | 
						||
        /// <returns></returns>
 | 
						||
        private bool IsNullOrEmpty(object value)
 | 
						||
        {
 | 
						||
            if (value == null || value.ToString() == string.Empty)
 | 
						||
            {
 | 
						||
                return true;
 | 
						||
            }
 | 
						||
            else
 | 
						||
            {
 | 
						||
                return false;
 | 
						||
            }
 | 
						||
        }
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 设置项目以及名称
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="Data"></param>
 | 
						||
        /// <returns></returns>
 | 
						||
        public async Task SetInspectionNameValue(DataInspection Data)
 | 
						||
        {
 | 
						||
            #region 项目名称
 | 
						||
 | 
						||
            var trialdata = await _dbContext.Trial.Select(x => new { x.Id, x.ResearchProgramNo, x.ExperimentName, }).FirstOrDefaultAsync(x => x.Id == Data.TrialId);
 | 
						||
            if (IsNullOrEmpty(Data.ResearchProgramNo))
 | 
						||
            {
 | 
						||
 | 
						||
                Data.ResearchProgramNo = trialdata?.ResearchProgramNo;
 | 
						||
            }
 | 
						||
 | 
						||
            if (IsNullOrEmpty(Data.TrialName))
 | 
						||
            {
 | 
						||
                Data.TrialName = trialdata?.ExperimentName;
 | 
						||
            }
 | 
						||
            #endregion
 | 
						||
 | 
						||
            #region 测试中心名称
 | 
						||
 | 
						||
 | 
						||
            Data.SiteCode = (await _dbContext.TrialSite.IgnoreQueryFilters().FirstOrDefaultAsync(x => x.TrialId == Data.TrialId && x.SiteId == Data.SiteId))?.TrialSiteCode;
 | 
						||
 | 
						||
 | 
						||
 | 
						||
            if (IsNullOrEmpty(Data.SiteName) && Data.SiteId != null)
 | 
						||
            {
 | 
						||
                var sitedata = await _dbContext.Site.Where(x => x.Id == Data.SiteId).Select(x => new { x.SiteName }).FirstOrDefaultAsync();
 | 
						||
                Data.SiteName = sitedata?.SiteName;
 | 
						||
            }
 | 
						||
            #endregion
 | 
						||
 | 
						||
            #region 受试者
 | 
						||
 | 
						||
 | 
						||
            if (IsNullOrEmpty(Data.SubjectCode) && Data.SubjectId != null)
 | 
						||
            {
 | 
						||
 | 
						||
                Data.SubjectCode = (await _dbContext.Subject.Where(x => x.Id == Data.SubjectId).Select(x => new { x.Code }).FirstOrDefaultAsync())?.Code;
 | 
						||
            }
 | 
						||
            #endregion
 | 
						||
 | 
						||
            #region 访视
 | 
						||
            if (IsNullOrEmpty(Data.SubjectVisitName))
 | 
						||
            {
 | 
						||
                Data.SubjectVisitName = (await _dbContext.SubjectVisit.Where(x => x.Id == Data.SubjectVisitId).Select(x => new { x.VisitName }).FirstOrDefaultAsync())?.VisitName;
 | 
						||
            }
 | 
						||
            #endregion
 | 
						||
 | 
						||
            #region 创建者
 | 
						||
 | 
						||
            if (IsNullOrEmpty(Data.CreateUserName))
 | 
						||
            {
 | 
						||
                Data.CreateUserName = _userInfo.RealName;
 | 
						||
            }
 | 
						||
 | 
						||
            if (IsNullOrEmpty(Data.RoleName))
 | 
						||
            {
 | 
						||
                Data.RoleName = _userInfo.UserTypeShortName;
 | 
						||
            }
 | 
						||
 | 
						||
            //if (IsNullOrEmpty(Data.CreateUserName) || IsNullOrEmpty(Data.RoleName))
 | 
						||
            //{
 | 
						||
            //    var userdata = await _dbContext.Users.AsQueryable().Where(x => x.Id == Data.CreateUserId).GroupJoin(_dbContext.UserType.AsQueryable(), a => a.UserTypeId, b => b.Id, (a, b) => new
 | 
						||
            //    {
 | 
						||
            //        UserName = a.FirstName + a.LastName,
 | 
						||
            //        Role = b
 | 
						||
            //    }).SelectMany(a => a.Role, (m, n) => new
 | 
						||
            //    {
 | 
						||
            //        UserName = m.UserName,
 | 
						||
            //        RoleName = n.UserTypeShortName
 | 
						||
            //    }).FirstOrDefaultAsync();
 | 
						||
 | 
						||
            //    if (userdata != null)
 | 
						||
            //    {
 | 
						||
            //        if (IsNullOrEmpty(Data.CreateUserName))
 | 
						||
            //        {
 | 
						||
            //            Data.CreateUserName = userdata?.UserName;
 | 
						||
            //        }
 | 
						||
 | 
						||
 | 
						||
            //        if (IsNullOrEmpty(Data.RoleName))
 | 
						||
            //        {
 | 
						||
            //            Data.RoleName = userdata?.RoleName;
 | 
						||
            //        }
 | 
						||
            //    }
 | 
						||
            //}
 | 
						||
            #endregion
 | 
						||
 | 
						||
            #region 取操作类型
 | 
						||
            try
 | 
						||
            {
 | 
						||
                var from = await _dbContext.FrontAuditConfig.FirstOrDefaultAsync(x => x.Identification == Data.Identification);
 | 
						||
                Data.ObjectType = from.ObjectTypeId;
 | 
						||
                Data.OptType = from.OptTypeId;
 | 
						||
                Data.ChildrenType = from.ChildrenTypeId;
 | 
						||
                Data.ModuleType = from.ModuleTypeId;
 | 
						||
            }
 | 
						||
            catch (Exception)
 | 
						||
            {
 | 
						||
 | 
						||
                throw new BusinessValidationFailedException("操作标识异常");
 | 
						||
            }
 | 
						||
 | 
						||
 | 
						||
            #endregion
 | 
						||
 | 
						||
        }
 | 
						||
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 设置项目以及名称
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="Data"></param>
 | 
						||
        /// <returns></returns>
 | 
						||
        public async Task SetInspectionNameValue(InspectionGeneralData Data)
 | 
						||
        {
 | 
						||
            #region 项目名称
 | 
						||
 | 
						||
            var trialdata = await _dbContext.Trial.Select(x => new { x.Id, x.ResearchProgramNo, x.ExperimentName, }).FirstOrDefaultAsync(x => x.Id == Data.TrialId);
 | 
						||
            if (IsNullOrEmpty(Data.ResearchProgramNo))
 | 
						||
            {
 | 
						||
 | 
						||
                Data.ResearchProgramNo = trialdata?.ResearchProgramNo;
 | 
						||
            }
 | 
						||
 | 
						||
            if (IsNullOrEmpty(Data.TrialName))
 | 
						||
            {
 | 
						||
                Data.TrialName = trialdata?.ExperimentName;
 | 
						||
            }
 | 
						||
            #endregion
 | 
						||
 | 
						||
            #region 测试中心名称
 | 
						||
 | 
						||
 | 
						||
            Data.SiteCode = (await _dbContext.TrialSite.IgnoreQueryFilters().FirstOrDefaultAsync(x => x.TrialId == Data.TrialId && x.SiteId == Data.SiteId))?.TrialSiteCode;
 | 
						||
 | 
						||
 | 
						||
 | 
						||
            if (IsNullOrEmpty(Data.SiteName) && Data.SiteId != null)
 | 
						||
            {
 | 
						||
                var sitedata = await _dbContext.Site.Where(x => x.Id == Data.SiteId).Select(x => new { x.SiteName }).FirstOrDefaultAsync();
 | 
						||
                Data.SiteName = sitedata?.SiteName;
 | 
						||
            }
 | 
						||
            #endregion
 | 
						||
 | 
						||
            #region 受试者
 | 
						||
 | 
						||
 | 
						||
            if (IsNullOrEmpty(Data.SubjectCode) && Data.SubjectId != null)
 | 
						||
            {
 | 
						||
 | 
						||
                Data.SubjectCode = (await _dbContext.Subject.Where(x => x.Id == Data.SubjectId).Select(x => new { x.Code }).FirstOrDefaultAsync())?.Code;
 | 
						||
            }
 | 
						||
            #endregion
 | 
						||
 | 
						||
            #region 访视
 | 
						||
            if (IsNullOrEmpty(Data.SubjectVisitName))
 | 
						||
            {
 | 
						||
                Data.SubjectVisitName = (await _dbContext.SubjectVisit.Where(x => x.Id == Data.SubjectVisitId).Select(x => new { x.VisitName }).FirstOrDefaultAsync())?.VisitName;
 | 
						||
            }
 | 
						||
            #endregion
 | 
						||
 | 
						||
            #region 创建者
 | 
						||
 | 
						||
            if (IsNullOrEmpty(Data.CreateUserName))
 | 
						||
            {
 | 
						||
                Data.CreateUserName = _userInfo.RealName;
 | 
						||
            }
 | 
						||
 | 
						||
            if (IsNullOrEmpty(Data.RoleName))
 | 
						||
            {
 | 
						||
                Data.RoleName = _userInfo.UserTypeShortName;
 | 
						||
            }
 | 
						||
            #endregion
 | 
						||
 | 
						||
 | 
						||
 | 
						||
        }
 | 
						||
        #endregion
 | 
						||
 | 
						||
 | 
						||
        #region 异步查询
 | 
						||
 | 
						||
 | 
						||
 | 
						||
        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);
 | 
						||
        }
 | 
						||
 | 
						||
        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)
 | 
						||
            {
 | 
						||
                query = query.Where(exp);
 | 
						||
            }
 | 
						||
 | 
						||
            return await query.FirstOrDefaultAsync().ConfigureAwait(false);
 | 
						||
 | 
						||
        }
 | 
						||
 | 
						||
        #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
 | 
						||
 | 
						||
        #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<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;
 | 
						||
            }
 | 
						||
        }
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
        #endregion
 | 
						||
    }
 | 
						||
 | 
						||
}
 |