diff --git a/IRaCIS.Core.Application/Service/QC/QCOperationService.cs b/IRaCIS.Core.Application/Service/QC/QCOperationService.cs index 31ca2d8f0..af7d67268 100644 --- a/IRaCIS.Core.Application/Service/QC/QCOperationService.cs +++ b/IRaCIS.Core.Application/Service/QC/QCOperationService.cs @@ -20,6 +20,7 @@ using Newtonsoft.Json; using IRaCIS.Core.Application.Service.Inspection.Interface; using IRaCIS.Core.Infrastructure; using IRaCIS.Core.Application.Service.Inspection.DTO; +using Nito.AsyncEx; namespace IRaCIS.Core.Application.Image.QA { @@ -35,6 +36,8 @@ namespace IRaCIS.Core.Application.Image.QA private readonly IInspectionService _inspectionService; private object _locker = new object(); + private readonly AsyncLock _mutex = new AsyncLock(); + public QCOperationService(DicomFileStoreHelper dicomFileStoreHelper, IRepository subjectVisitRepository, IRepository trialRepository, IMediator mediator, @@ -83,60 +86,21 @@ namespace IRaCIS.Core.Application.Image.QA if (await _repository.AnyAsync(t => t.IsClosed == false && t.SubjectVisitId == qaQuestionCommand.SubjectVisitId && t.ReuploadEnum == QCChanllengeReuploadEnum.QCAgreeUpload)) { throw new BusinessValidationFailedException("当前访视有未关闭的 同意CRC上传的质疑,不允许再次添加质疑"); - + + } + var trialConfig = _repository.Where(t => t.Id == trialId).Select(t => new { TrialId = t.Id, t.QCProcessEnum, t.IsImageConsistencyVerification }).FirstOrDefault(); + + + //获取编号 + var code = _repository.Where(t => t.TrialId == trialId).Select(t => t.ChallengeCode).DefaultIfEmpty().Max(); + if (trialConfig == null) + { + throw new BusinessValidationFailedException("项目不存在"); } - QCChallenge? qcChallenge = null; - var success = false; - lock (_locker) + using (await _mutex.LockAsync()) { - var trialConfig = _repository.Where(t => t.Id == trialId).Select(t => new { TrialId = t.Id, t.QCProcessEnum, t.IsImageConsistencyVerification }).FirstOrDefault(); - - if (trialConfig == null) - { - throw new BusinessValidationFailedException("项目不存在"); - } - - #region 处理访视状态变更 - //var dbSubjectVisit = _subjectVisitRepository.FirstOrDefault(t => t.Id == qaQuestionCommand.SubjectVisitId); - - //if (trialConfig.QCProcessEnum == TrialQCProcess.NotAudit) - //{ - // return ResponseOutput.NotOk("项目配置为不审,不允许添加QA质疑 "); - //} - //else if (trialConfig.QCProcessEnum == TrialQCProcess.SingleAudit) - //{ - // if ((int)dbSubjectVisit.AuditState == (int)SubjectVisitStateEnum.Submitted) - // { - // dbSubjectVisit.AuditState = AuditStateEnum.InPrimaryQC; - // } - // else - // { - // return ResponseOutput.NotOk($"项目配置为单审,当前审核状态不为{SubjectVisitStateEnum.Submitted},不允许添加QA质疑 "); - // } - //} - //else if (trialConfig.QCProcessEnum == TrialQCProcess.DoubleAudit) - //{ - // if ((int)dbSubjectVisit.AuditState == (int)SubjectVisitStateEnum.Submitted) - // { - // dbSubjectVisit.AuditState = AuditStateEnum.InPrimaryQC; - // } - // else if ((int)dbSubjectVisit.AuditState == (int)SubjectVisitStateEnum.PrimaryQCPassed) - // { - // dbSubjectVisit.AuditState = AuditStateEnum.InSecondaryQC; - // } - // else - // { - // return ResponseOutput.NotOk($"项目配置为双审,访视状态为 {SubjectVisitStateEnum.Submitted}或{SubjectVisitStateEnum.PrimaryQCPassed}才允许添加QA质疑 "); - // } - //} - - #endregion - - //获取编号 - var code = _repository.Where(t => t.TrialId == trialId).Select(t => t.ChallengeCode).DefaultIfEmpty().Max(); - - qcChallenge = _mapper.Map(qaQuestionCommand); + var qcChallenge = _mapper.Map(qaQuestionCommand); qcChallenge.QCProcessEnum = trialConfig.QCProcessEnum; qcChallenge.CurrentQCEnum = currentQCType; @@ -144,53 +108,18 @@ namespace IRaCIS.Core.Application.Image.QA qcChallenge.CreateUser = _userInfo.RealName; qcChallenge.ChallengeCode = code + 1; qcChallenge.UserTypeEnum = (UserTypeEnum)_userInfo.UserTypeEnumInt; - _ = _repository.AddAsync(qcChallenge).Result; - success = _repository.SaveChangesAsync().Result; + qcChallenge= await _repository.AddAsync(qcChallenge,true); + + return qcChallenge; } - - //分开两个事务 处理访视质疑状态 - await DealChallengeState(qcChallenge.SubjectVisitId); - - return qcChallenge; - - #region 添加的时候把记录给留存 - //var templateItems = _mapper.Map>(visitQaCommand.QATrialTemplateItemList); - //templateItems.ForEach(u => - //{ - // u.IQA = _userInfo.RealName; - // u.IQACreateTime = DateTime.Now; - // u.IQANote = visitQaCommand.QARecord.Note; - // u.IQADeadline = visitQaCommand.QARecord.DeadlineTime; - // u.QARecordId = qaRecord.Id; - // qaRecord.QARecordTemplateItemDetailList.Add(u); - //}); - - ////添加了QA记录 引用了QA模板后就不允许删除和编辑,需要维护项目模板状态 传统做法 - //var qaTrailTemplate = _qaTrailTemplateRepository.FirstOrDefault(t => t.Id == visitQaCommand.QARecord.QATrialTemplateId); - //qaTrailTemplate.Status = QATrialTemplateStatus.HasQuote; - #endregion - } else { - var qcChallenge = await _repository.FirstOrDefaultAsync(t => t.Id == qaQuestionCommand.Id); + return await _repository.UpdateFromDTOAsync(qaQuestionCommand, true); - if (qcChallenge == null) - { - throw new BusinessValidationFailedException("QC问题不存在"); - }; - - _mapper.Map(qaQuestionCommand, qcChallenge); - - var success = await _repository.SaveChangesAsync(); - - await DealChallengeState(qcChallenge.SubjectVisitId); - - - return qcChallenge; } @@ -237,39 +166,14 @@ namespace IRaCIS.Core.Application.Image.QA var success = await _repository.SaveChangesAsync(); - await DealChallengeState(subjectVisitId); return ResponseOutput.Result(success); } - /// - /// 访视级别统计 质疑最新的状态 - /// - /// - private async Task DealChallengeState(Guid subjectVisitId) - { - var sv = await _repository.FirstOrDefaultAsync(t => t.Id == subjectVisitId); - var closedStateList = await _repository.Where(t => t.SubjectVisitId == subjectVisitId).Select(t => t.IsClosed).ToListAsync(); - - if (closedStateList.Count == 0) - { - sv.ChallengeState = ChallengeStateEnum.No; - } - else if (closedStateList.All(t => t is true)) - { - sv.ChallengeState = ChallengeStateEnum.HaveAndAllClosed; - } - else - { - sv.ChallengeState = ChallengeStateEnum.HaveAndHaveNotClosed; - } - await _repository.SaveChangesAsync(); - } - /// /// 删除QC质疑记录 @@ -532,9 +436,9 @@ namespace IRaCIS.Core.Application.Image.QA var success = await _repository.SaveChangesAsync(); - // var signSuccess = await _repository.UpdateFromQueryAsync(t => t.Id == signId, u => new TrialSign() { IsCompleted = true }); + // var signSuccess = await _repository.UpdateFromQueryAsync(t => t.Id == signId, u => new TrialSign() { IsCompleted = true }); - return ResponseOutput.Result( success); + return ResponseOutput.Result(success); } @@ -549,7 +453,7 @@ namespace IRaCIS.Core.Application.Image.QA /// [HttpPost("{trialId:guid}")] [TypeFilter(typeof(TrialResourceFilter))] - public async Task UploadVisitCheckExcel(IFormFile file, Guid trialId) + public async Task UploadVisitCheckExcel(IFormFile file, Guid trialId) { if (_userInfo.UserTypeEnumInt != (int)UserTypeEnum.ProjectManager) { @@ -902,13 +806,13 @@ namespace IRaCIS.Core.Application.Image.QA public async Task UpdateModality(Guid id, int type, [FromQuery] string modality, [FromQuery] string bodyPart) { - var DicomSeriesdata = await _repository.GetQueryable().Where(x=>x.StudyId==id).ToListAsync(); + var DicomSeriesdata = await _repository.GetQueryable().Where(x => x.StudyId == id).ToListAsync(); var study = await _repository.FirstOrDefaultAsync(t => t.Id == id); List datas = new List(); DateTime time = DateTime.Now.AddMilliseconds(500); if (type == 1) { - + if (study == null) return Null404NotFound(study); study.BodyPartForEdit = bodyPart; @@ -977,7 +881,7 @@ namespace IRaCIS.Core.Application.Image.QA { } - + await _trialRepository.AddListInspectionRecordAsync(datas); await _repository.SaveChangesAsync(); return ResponseOutput.Ok(); @@ -999,8 +903,8 @@ namespace IRaCIS.Core.Application.Image.QA } return ResponseOutput.Ok(); } - - + + /// @@ -1021,7 +925,7 @@ namespace IRaCIS.Core.Application.Image.QA { return ResponseOutput.NotOk("CRC Has Submited Image,can not delete"); } - var waitDeleteStudyList= await _dicomStudyRepository.Where(x => ids.Contains(x.Id)).ToListAsync(); + var waitDeleteStudyList = await _dicomStudyRepository.Where(x => ids.Contains(x.Id)).ToListAsync(); List datas = new List(); @@ -1035,18 +939,18 @@ namespace IRaCIS.Core.Application.Image.QA SiteId = x.SiteId, SubjectId = x.SubjectId, TrialId = x.TrialId, - SubjectVisitId=x.SubjectVisitId, - GeneralId=x.Id, - CreateTime=DateTime.Now, - Identification= "Delete|DICOM Study|Data|Visit-Image Upload", + SubjectVisitId = x.SubjectVisitId, + GeneralId = x.Id, + CreateTime = DateTime.Now, + Identification = "Delete|DICOM Study|Data|Visit-Image Upload", JsonDetail = JsonConvert.SerializeObject(new { - studyUid=x.StudyCode, - modality=x.Modalities, - bodyPart=x.BodyPartForEdit, - seriesNum=x.SeriesCount, + studyUid = x.StudyCode, + modality = x.Modalities, + bodyPart = x.BodyPartForEdit, + seriesNum = x.SeriesCount, fileNum = x.InstanceCount, - studyTime=x.StudyTime?.ToString("yyyy-MM-dd") + studyTime = x.StudyTime?.ToString("yyyy-MM-dd") }) }); @@ -1060,22 +964,23 @@ namespace IRaCIS.Core.Application.Image.QA var id = study.Id; - await _dicomStudyRepository.DeleteAsync(study,true); + await _dicomStudyRepository.DeleteAsync(study, true); var succeess2 = await _repository.BatchDeleteAsync(t => t.StudyId == id); - var DicomSeriess = await _repository.GetQueryable().Where(t => t.StudyId == id).Select(x => new { + var DicomSeriess = await _repository.GetQueryable().Where(t => t.StudyId == id).Select(x => new + { x.StudyId, - x.SubjectId, - x.SiteId, - x.TrialId, - x.Id, - x.SubjectVisitId, - x.SeriesTime, - x.IsReading, - x.InstanceCount, - x.SeriesNumber, - StudyCode= x.DicomStudy.StudyCode, - Modalities=x.DicomStudy.Modalities, + x.SubjectId, + x.SiteId, + x.TrialId, + x.Id, + x.SubjectVisitId, + x.SeriesTime, + x.IsReading, + x.InstanceCount, + x.SeriesNumber, + StudyCode = x.DicomStudy.StudyCode, + Modalities = x.DicomStudy.Modalities, }).ToListAsync(); @@ -1128,7 +1033,7 @@ namespace IRaCIS.Core.Application.Image.QA var subvisit = await _repository.GetQueryable().FirstOrDefaultAsync(x => x.Id == subjectVisitId); - + datas.Add(new DataInspection() { @@ -1197,7 +1102,7 @@ namespace IRaCIS.Core.Application.Image.QA #region 处理验证 - if (dbSubjectVisit.IsTake&& dbSubjectVisit.CurrentActionUserId!=_userInfo.Id) + if (dbSubjectVisit.IsTake && dbSubjectVisit.CurrentActionUserId != _userInfo.Id) { return ResponseOutput.NotOk("当前已被领取,不允许领取"); } @@ -1274,12 +1179,12 @@ namespace IRaCIS.Core.Application.Image.QA } else if (trialConfig.QCProcessEnum == TrialQCProcess.SingleAudit) { - + if (dbSubjectVisit.SubmitState == SubmitStateEnum.Submitted && dbSubjectVisit.AuditState == AuditStateEnum.InPrimaryQC) { dbSubjectVisit.AuditState = AuditStateEnum.ToAudit; } - + else { return ResponseOutput.NotOk("项目配置为单审,不满足SubmmitState:已提交 或者 AuditState:InPrimaryQC, 不允许释放"); @@ -1287,7 +1192,7 @@ namespace IRaCIS.Core.Application.Image.QA } else if (trialConfig.QCProcessEnum == TrialQCProcess.DoubleAudit) { - + //提交 并且初审通过 那么领取后进入 复审中 if (dbSubjectVisit.SubmitState == SubmitStateEnum.Submitted && dbSubjectVisit.AuditState == AuditStateEnum.InSecondaryQC) { @@ -1298,7 +1203,7 @@ namespace IRaCIS.Core.Application.Image.QA { dbSubjectVisit.AuditState = AuditStateEnum.ToAudit; } - + else { return ResponseOutput.NotOk("项目配置为复审,不满足提交状态:已提交 或者 审核状态:InPrimaryQC/InSecondaryQC, 不允许领取"); @@ -1437,7 +1342,7 @@ namespace IRaCIS.Core.Application.Image.QA // JsonDetail = JsonConvert.SerializeObject(new // { // SubmitState = "已提交", - + // }) // }); @@ -1482,7 +1387,7 @@ namespace IRaCIS.Core.Application.Image.QA [TypeFilter(typeof(TrialResourceFilter))] public async Task QCPassedOrFailed(Guid trialId, Guid subjectVisitId, [FromRoute] AuditStateEnum auditState) { - + if (!await _repository.AnyAsync(t => t.TrialId == trialId && t.UserId == _userInfo.Id)) { @@ -1596,7 +1501,7 @@ namespace IRaCIS.Core.Application.Image.QA // 单审 if (dbSubjectVisit.AuditState == AuditStateEnum.ToAudit) { - dbSubjectVisit.AuditState = AuditStateEnum.QCFailed; + dbSubjectVisit.AuditState = AuditStateEnum.QCFailed; } else @@ -1625,7 +1530,7 @@ namespace IRaCIS.Core.Application.Image.QA //删除 软删除的物理文件 - + var instanceIdList = await _repository.Where(t => t.DicomSerie.IsDeleted && t.SubjectVisitId == subjectVisitId) .Select(t => new { InstanceId = t.Id, t.SeriesId, t.StudyId, t.SubjectId, t.SiteId }).ToListAsync(); @@ -1638,14 +1543,14 @@ namespace IRaCIS.Core.Application.Image.QA SeriesNumber = x.SeriesNumber, InstanceCount = x.InstanceCount, SeriesTime = x.SeriesTime, - TrialId=x.TrialId, - SiteId=x.SiteId, + TrialId = x.TrialId, + SiteId = x.SiteId, x.SubjectId, x.SubjectVisitId, x.IsDeleted, x.IsReading, x.Id, - + }).ToListAsync(); DateTime time = DateTime.Now.AddMilliseconds(500); DicomSeriesdata.ForEach(x => @@ -1666,8 +1571,8 @@ namespace IRaCIS.Core.Application.Image.QA SeriesNumber = x.SeriesNumber, InstanceCount = x.InstanceCount, SeriesTime = x.SeriesTime, - IsReading=x.IsReading, - IsDeleted=x.IsDeleted, + IsReading = x.IsReading, + IsDeleted = x.IsDeleted, }) @@ -1675,7 +1580,7 @@ namespace IRaCIS.Core.Application.Image.QA }); - + await _inspectionService.AddListInspectionRecordAsync(datas); instanceIdList.ForEach(t => { @@ -1980,9 +1885,9 @@ namespace IRaCIS.Core.Application.Image.QA }) }); } - - await _inspectionService.AddListInspectionRecordAsync(datas); + + await _inspectionService.AddListInspectionRecordAsync(datas); } ////受试者基线 入组确认 或者访视PD 进展 默认加急 @@ -2026,7 +1931,7 @@ namespace IRaCIS.Core.Application.Image.QA foreach (var subjectVisitId in subjectVisitIdList) { - + var info = await _subjectVisitRepository.Where(t => t.Id == subjectVisitId).ProjectTo(_mapper.ConfigurationProvider).FirstOrDefaultAsync(); Dictionary keyValuePairs = new Dictionary() { @@ -2038,11 +1943,11 @@ namespace IRaCIS.Core.Application.Image.QA }; DataInspection data = new DataInspection() { - TrialId= info.TrialId, - SiteId=info.SiteId, - SubjectId=info.SubjectId, - SubjectVisitId= subjectVisitId, - Identification= "NaN-14-0" + TrialId = info.TrialId, + SiteId = info.SiteId, + SubjectId = info.SubjectId, + SubjectVisitId = subjectVisitId, + Identification = "NaN-14-0" }; var targetPath = "/IMPORT-IMAGES/" + info.TrialCode + "_" + info.SubjectCode + "_" + info.VisitName; @@ -2111,14 +2016,14 @@ namespace IRaCIS.Core.Application.Image.QA } await _subjectVisitRepository.BatchUpdateAsync(t => t.Id == subjectVisitId, - u => new SubjectVisit() { ForwardState = ForwardStateEnum.Forwarded,ForwardUserId = _userInfo.Id,ForwardTime = DateTime.Now}); + u => new SubjectVisit() { ForwardState = ForwardStateEnum.Forwarded, ForwardUserId = _userInfo.Id, ForwardTime = DateTime.Now }); keyValuePairs["ForwardState"] = "转发成功"; data.JsonDetail = JsonConvert.SerializeObject(keyValuePairs); datas.Add(data); } - await _subjectVisitRepository.AddListInspectionRecordAsync(datas); + await _subjectVisitRepository.AddListInspectionRecordAsync(datas); await _subjectVisitRepository.SaveChangesAsync(); diff --git a/IRaCIS.Core.Infra.EFCore/Repository/IRepository.cs b/IRaCIS.Core.Infra.EFCore/Repository/IRepository.cs index 39f1b8979..797dc9ad7 100644 --- a/IRaCIS.Core.Infra.EFCore/Repository/IRepository.cs +++ b/IRaCIS.Core.Infra.EFCore/Repository/IRepository.cs @@ -55,9 +55,11 @@ namespace IRaCIS.Core.Infra.EFCore Task InsertOrUpdateAsync(TFrom from, bool autoSave = false, params EntityVerifyExp[] verify) where T : Entity; - EntityEntry Entry(T t) where T : Entity; + Task InsertFromDTOAsync(TFrom from, bool autoSave = false, params EntityVerifyExp[] verify) where T : Entity; - //Task InsertOrUpdateAsync(this DbSet dbset, TFrom from, bool autoSave = false, params EntityVerifyExp[] verify) where T : Entity; + Task UpdateFromDTOAsync(TFrom from, bool autoSave = false, bool ignoreDtoNullProperty = true, params EntityVerifyExp[] verify) where T : Entity; + + EntityEntry Entry(T t) where T : Entity; Task AnyAsync(Expression> filter, bool ignoreQueryFilters = false) where T : Entity; @@ -77,7 +79,7 @@ namespace IRaCIS.Core.Infra.EFCore Task DeleteAsync(T entity, bool autoSave = false) where T : Entity; - Task DeleteManyAsync(IEnumerable entities, bool autoSave = false) where T : Entity; + //Task DeleteManyAsync(IEnumerable entities, bool autoSave = false) where T : Entity; Task SaveChangesAsync(); @@ -90,6 +92,8 @@ namespace IRaCIS.Core.Infra.EFCore { private IRaCISDBContext _dbContext { get; } + + public IMapper _mapper { get; set; } public IUserInfo _userInfo { get; set; } @@ -130,65 +134,21 @@ namespace IRaCIS.Core.Infra.EFCore } - - public async Task InsertOrUpdateAsync(TFrom from, bool autoSave = false, params EntityVerifyExp[] verify) where T : Entity + private async Task EntityVerifyAsync(bool isAdd, EntityVerifyExp[] verify, Guid? entitydId = null) where T : Entity { - var entity = _mapper.Map(from); - - if (entity.Id == Guid.Empty) + if (isAdd) { - // verifyExp - - //await verify.Where(t => t.verifyType != VerifyEnum.OnlyUpdate && t.IsVerify).ToList().ForeachAsync(async verifyItem => - //{ - // if (await _dbContext.Set().AnyAsync(verifyItem.VerifyExp).ConfigureAwait(false)) - // { - // throw new BusinessValidationFailedException(verifyItem.VerifyMsg); - // } - //}); - foreach (var verifyItem in verify.Where(t => t.verifyType != VerifyEnum.OnlyUpdate && t.IsVerify)) { - if (await _dbContext.Set().AnyAsync(verifyItem.VerifyExp).ConfigureAwait(false)) + if (await _dbContext.Set().IgnoreQueryFilters().AnyAsync(verifyItem.VerifyExp).ConfigureAwait(false)) { throw new BusinessValidationFailedException(verifyItem.VerifyMsg); } } - - await _dbContext.Set().AddAsync(entity).ConfigureAwait(false); - - if (autoSave) - { - await SaveChangesAsync(); - - } - return entity; - } else { - // verifyExp - - //await verify.Where(t => t.verifyType != VerifyEnum.OnlyAdd && t.IsVerify).ToList().ForeachAsync(async verifyItem => - // { - // if (verifyItem.verifyType == VerifyEnum.OnlyUpdate) - // { - // if (await _dbContext.Set().AnyAsync(verifyItem.VerifyExp).ConfigureAwait(false)) - // { - // throw new BusinessValidationFailedException(verifyItem.VerifyMsg); - // } - // } - // else if (verifyItem.verifyType == VerifyEnum.Both) - // { - // if (await _dbContext.Set().AnyAsync(verifyItem.VerifyExp.And(t => t.Id != entity.Id)).ConfigureAwait(false)) - // { - // throw new BusinessValidationFailedException(verifyItem.VerifyMsg); - // } - // } - - // }); - foreach (var verifyItem in verify.Where(t => t.verifyType != VerifyEnum.OnlyAdd && t.IsVerify)) { if (verifyItem.verifyType == VerifyEnum.OnlyUpdate) @@ -200,25 +160,97 @@ namespace IRaCIS.Core.Infra.EFCore } else if (verifyItem.verifyType == VerifyEnum.Both) { - if (await _dbContext.Set().IgnoreQueryFilters().AnyAsync(verifyItem.VerifyExp.And(t => t.Id != entity.Id)).ConfigureAwait(false)) + if (await _dbContext.Set().IgnoreQueryFilters().AnyAsync(verifyItem.VerifyExp.And(t => t.Id != entitydId)).ConfigureAwait(false)) { throw new BusinessValidationFailedException(verifyItem.VerifyMsg); } } } + } - var dbEntity = await FirstOrDefaultAsync(t => t.Id == entity.Id).ConfigureAwait(false); + } - var dbBeforEntity = dbEntity.Clone(); + public async Task InsertFromDTOAsync(TFrom from, bool autoSave = false, + params EntityVerifyExp[] verify) where T : Entity + { - _mapper.Map(from, dbEntity); + var entity = _mapper.Map(from); - if (autoSave) + await EntityVerifyAsync(true, verify); + + + entity = await AddAsync(entity, autoSave); + + + return entity; + } + + public async Task UpdateFromDTOAsync(TFrom from, bool autoSave = false, bool ignoreDtoNullProperty = true, params EntityVerifyExp[] verify) where T : Entity + { + var entity = _mapper.Map(from); + + await EntityVerifyAsync(false, verify, entity.Id); + + var dbEntity = await _dbContext.Set().IgnoreQueryFilters().FirstOrDefaultAsync(t => t.Id == entity.Id).ConfigureAwait(false); + + if (dbEntity == null) + { + throw new BusinessValidationFailedException( + " 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(T).GetProperties(); + foreach (var propertyInfo in from.GetType().GetProperties()) { - await SaveChangesAsync(); + if (propertyInfo.GetValue(from) == null && dbEntityProp.Any(t => t.Name == propertyInfo.Name)) + { + _dbContext.Entry(dbEntity).Property(propertyInfo.Name).IsModified = false; + } } - return dbBeforEntity; + } + await SaveChangesAsync(autoSave); + + + return dbBeforEntity; + } + + + private async Task SaveChangesAsync(bool autoSave) + { + if (autoSave) + { + return await SaveChangesAsync(); + } + else + { + return false; + } + } + + + public async Task InsertOrUpdateAsync(TFrom from, bool autoSave = false, params EntityVerifyExp[] verify) where T : Entity + { + var entity = _mapper.Map(from); + + + if (entity.Id == Guid.Empty) + { + return await InsertFromDTOAsync(from, autoSave, verify); + } + else + { + return await UpdateFromDTOAsync(from, autoSave, false, verify); } }