diff --git a/IRaCIS.Core.Application/IRaCIS.Core.Application.csproj b/IRaCIS.Core.Application/IRaCIS.Core.Application.csproj index 15f4a5eb9..179a30f94 100644 --- a/IRaCIS.Core.Application/IRaCIS.Core.Application.csproj +++ b/IRaCIS.Core.Application/IRaCIS.Core.Application.csproj @@ -100,7 +100,6 @@ true - diff --git a/IRaCIS.Core.Application/Service/Common/MailService.cs b/IRaCIS.Core.Application/Service/Common/MailService.cs index 2a4e0bb2d..d821708b6 100644 --- a/IRaCIS.Core.Application/Service/Common/MailService.cs +++ b/IRaCIS.Core.Application/Service/Common/MailService.cs @@ -6,7 +6,6 @@ using Microsoft.AspNetCore.Hosting; using IRaCIS.Core.Application.Auth; using AutoMapper; using IRaCIS.Application.Contracts; -using Nito.AsyncEx; using Microsoft.Extensions.Options; namespace IRaCIS.Application.Services @@ -55,7 +54,6 @@ namespace IRaCIS.Application.Services - private readonly AsyncLock _mutex = new AsyncLock(); private readonly SystemEmailSendConfig _systemEmailConfig; diff --git a/IRaCIS.Core.Application/Service/ImageAndDoc/DicomArchiveService.cs b/IRaCIS.Core.Application/Service/ImageAndDoc/DicomArchiveService.cs index f797c8ca4..9b990c306 100644 --- a/IRaCIS.Core.Application/Service/ImageAndDoc/DicomArchiveService.cs +++ b/IRaCIS.Core.Application/Service/ImageAndDoc/DicomArchiveService.cs @@ -8,10 +8,11 @@ using IRaCIS.Core.Application.Contracts; using IRaCIS.Core.Application.Helper; using Microsoft.AspNetCore.Hosting; using IRaCIS.Core.Infrastructure; +using Medallion.Threading; namespace IRaCIS.Core.Application.Services { - public class DicomArchiveService :BaseService, IDicomArchiveService + public class DicomArchiveService : BaseService, IDicomArchiveService { private readonly IRepository _studyRepository; private readonly IRepository _seriesRepository; @@ -21,7 +22,7 @@ namespace IRaCIS.Core.Application.Services private readonly IWebHostEnvironment _hostEnvironment; - private static object lockCodeGenerate = new object(); + private readonly IDistributedLockProvider _distributedLockProvider; private List _instanceIdList = new List(); @@ -31,8 +32,9 @@ namespace IRaCIS.Core.Application.Services IRepository instanceRepository, IWebHostEnvironment hostEnvironment, IRepository dictionaryRepository, - IEasyCachingProvider provider) + IEasyCachingProvider provider, IDistributedLockProvider distributedLockProvider) { + _distributedLockProvider = distributedLockProvider; _hostEnvironment = hostEnvironment; _studyRepository = studyRepository; @@ -50,7 +52,7 @@ namespace IRaCIS.Core.Application.Services return success; } - + public async Task<(Guid StudyId, string StudyCode)> ArchiveDicomStreamAsync(Stream dicomStream, @@ -129,7 +131,7 @@ namespace IRaCIS.Core.Application.Services DicomStudy dicomStudy = CreateDicomStudy(dataset, addtionalInfo, out bool isStudyNeedAdd); DicomSeries dicomSeries = CreateDicomSeries(dataset, dicomStudy, out bool isSeriesNeedAdd); - DicomInstance dicomInstance = CreateDicomInstance(dataset, dicomStudy, dicomSeries,out bool isInstanceNeedAdd); + DicomInstance dicomInstance = CreateDicomInstance(dataset, dicomStudy, dicomSeries, out bool isInstanceNeedAdd); dicomSeries.DicomStudy = dicomStudy; @@ -183,7 +185,7 @@ namespace IRaCIS.Core.Application.Services //正常保存 不做处理 await dicomFile.SaveAsync(physicalPath); } - else + else { //RLELossless 保存 await dicomFile.Clone(DicomTransferSyntax.RLELossless).SaveAsync(physicalPath); //RLELossless @@ -235,7 +237,7 @@ namespace IRaCIS.Core.Application.Services { modalityForEdit = "PET"; } - if(modality== "PT、CT") + if (modality == "PT、CT") { modalityForEdit = "PET-CT"; } @@ -282,9 +284,10 @@ namespace IRaCIS.Core.Application.Services dicomStudy.PatientBirthDate = $"{dicomStudy.PatientBirthDate[0]}{dicomStudy.PatientBirthDate[1]}{dicomStudy.PatientBirthDate[2]}{dicomStudy.PatientBirthDate[3]}-{dicomStudy.PatientBirthDate[4]}{dicomStudy.PatientBirthDate[5]}-{dicomStudy.PatientBirthDate[6]}{dicomStudy.PatientBirthDate[7]}"; } - lock (lockCodeGenerate) - { + var @lock = _distributedLockProvider.CreateLock($"StudyCode"); + using (@lock.Acquire()) + { //查询数据库获取最大的Code 没有记录则为0 var dbStudyCodeIntMax = _studyRepository.Where(s => s.TrialId == addtionalInfo.TrialId).Select(t => t.Code).DefaultIfEmpty().Max(); @@ -298,9 +301,9 @@ namespace IRaCIS.Core.Application.Services dicomStudy.StudyCode = AppSettings.GetCodeStr(currentNextCodeInt, nameof(DicomStudy)); _provider.Set($"{addtionalInfo.TrialId}_{StaticData.CacheKey.StudyMaxCode}", dicomStudy.Code, TimeSpan.FromMinutes(30)); - } + #region Setting Code old //var studyCode = _studyRepository.Where(s => s.TrialId == addtionalInfo.TrialId).Select(t => t.StudyCode).OrderByDescending(c => c).FirstOrDefault(); @@ -468,7 +471,7 @@ namespace IRaCIS.Core.Application.Services _instanceIdList.Add(instanceId); } - + return dicomInstance; } diff --git a/IRaCIS.Core.Application/Service/ImageAndDoc/StudyService.cs b/IRaCIS.Core.Application/Service/ImageAndDoc/StudyService.cs index 173c643f1..adb1f224a 100644 --- a/IRaCIS.Core.Application/Service/ImageAndDoc/StudyService.cs +++ b/IRaCIS.Core.Application/Service/ImageAndDoc/StudyService.cs @@ -14,16 +14,13 @@ using IRaCIS.Core.Application.MediatR.Handlers; using Microsoft.AspNetCore.Http; using Newtonsoft.Json; using System.Threading; -using Nito.AsyncEx; +using Medallion.Threading; namespace IRaCIS.Core.Application.Service.ImageAndDoc { [ApiExplorerSettings(GroupName = "Image")] public class StudyService : BaseService, IStudyService { - private static object lockObj = new object(); - private static readonly AsyncLock _mutex = new AsyncLock(); - private static readonly AsyncLock _mutex2 = new AsyncLock(); private readonly IEasyCachingProvider _provider; @@ -35,12 +32,12 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc private readonly IRepository _dictionaryRepository; private readonly IRepository _studyMonitorRepository; - + private readonly IDistributedLockProvider _distributedLockProvider; public StudyService(IEasyCachingProvider provider , IRepository subjectVisitRepository, IRepository dicomInstanceRepository, - IRepository dicomSeriesRepository, IRepository dicomstudyRepository, IRepository dictionaryRepository, IRepository studyMonitorRepository) + IRepository dicomSeriesRepository, IRepository dicomstudyRepository, IRepository dictionaryRepository, IRepository studyMonitorRepository, IDistributedLockProvider distributedLockProvider) { _provider = provider; _subjectVisitRepository = subjectVisitRepository; @@ -49,6 +46,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc _dicomstudyRepository = dicomstudyRepository; _dictionaryRepository = dictionaryRepository; _studyMonitorRepository = studyMonitorRepository; + _distributedLockProvider = distributedLockProvider; } @@ -160,7 +158,9 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc { var study = _mapper.Map(incommand.Study); - using (await _mutex.LockAsync()) + var @lock = _distributedLockProvider.CreateLock($"StudyCode"); + + using (await @lock.AcquireAsync()) { //查询数据库获取最大的Code 没有记录则为0 var dbStudyCodeIntMax = _dicomstudyRepository.Where(s => s.TrialId == trialId).Select(t => t.Code).DefaultIfEmpty().Max(); @@ -306,11 +306,11 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc } - using (await _mutex2.LockAsync()) + var @lock2 = _distributedLockProvider.CreateLock($"StudyCommit"); + + using (await @lock2.AcquireAsync()) { await _dicomInstanceRepository.SaveChangesAsync(); - - } } catch (Exception ex) @@ -765,7 +765,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc if (_provider.Exists($"StudyUid_{trialId}_{studyInstanceUid}")) { - + result.AllowUpload = false; result.AllowReUpload = false; @@ -826,22 +826,22 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc } result.StudyInstanceUid = studyInstanceUid; + var @lock = _distributedLockProvider.CreateLock($"StudyUpload"); - if (result.AllowReUpload || result.AllowUpload) + using (@lock.Acquire()) { - lock (lockObj) + if (result.AllowReUpload || result.AllowUpload) { _provider.Set($"StudyUid_{trialId}_{studyInstanceUid}", _userInfo.Id, TimeSpan.FromSeconds(30)); } - } - else - { - lock (lockObj) + else { _provider.Remove($"StudyUid_{trialId}_{studyInstanceUid}"); } } + + return result; } diff --git a/IRaCIS.Core.Application/Service/Institution/SiteService.cs b/IRaCIS.Core.Application/Service/Institution/SiteService.cs index 137d4ffd0..b65b2379f 100644 --- a/IRaCIS.Core.Application/Service/Institution/SiteService.cs +++ b/IRaCIS.Core.Application/Service/Institution/SiteService.cs @@ -3,7 +3,7 @@ using IRaCIS.Application.Contracts; using IRaCIS.Core.Infra.EFCore; using Microsoft.AspNetCore.Mvc; using IRaCIS.Core.Domain.Share; -using Nito.AsyncEx; +using Medallion.Threading; namespace IRaCIS.Application.Services { @@ -12,13 +12,13 @@ namespace IRaCIS.Application.Services { private readonly IRepository _siteRepository; private readonly IRepository _trialSiteUserRepository; + private readonly IDistributedLockProvider _distributedLockProvider; - private readonly AsyncLock _mutex = new AsyncLock(); - - public SiteService(IRepository siteRepository, IRepository trialSiteUserRepository) + public SiteService(IRepository siteRepository, IRepository trialSiteUserRepository, IDistributedLockProvider distributedLockProvider) { _siteRepository = siteRepository; - this._trialSiteUserRepository = trialSiteUserRepository; + _trialSiteUserRepository = trialSiteUserRepository; + _distributedLockProvider = distributedLockProvider; } /// 分页获取研究中心列表 @@ -27,7 +27,7 @@ namespace IRaCIS.Application.Services { var siteQueryable = _siteRepository - .WhereIf(!string.IsNullOrWhiteSpace(searchModel.SiteName), t => t.SiteName.Contains(searchModel.SiteName)||t.SiteNameCN.Contains(searchModel.SiteName)) + .WhereIf(!string.IsNullOrWhiteSpace(searchModel.SiteName), t => t.SiteName.Contains(searchModel.SiteName) || t.SiteNameCN.Contains(searchModel.SiteName)) .WhereIf(!string.IsNullOrWhiteSpace(searchModel.AliasName), t => t.AliasName.Contains(searchModel.AliasName)) .WhereIf(!string.IsNullOrWhiteSpace(searchModel.City), t => t.City.Contains(searchModel.City)) .WhereIf(!string.IsNullOrWhiteSpace(searchModel.Country), t => t.Country.Contains(searchModel.Country)) @@ -58,7 +58,9 @@ namespace IRaCIS.Application.Services VerifyMsg = _localizer["Site_DupName"] }; - using (await _mutex.LockAsync()) + var @lock = _distributedLockProvider.CreateLock($"SiteAdd"); + + using (await @lock.AcquireAsync()) { if (siteCommand.Id == null) { diff --git a/IRaCIS.Core.Application/Service/Management/UserService.cs b/IRaCIS.Core.Application/Service/Management/UserService.cs index 32df5fa15..b36859015 100644 --- a/IRaCIS.Core.Application/Service/Management/UserService.cs +++ b/IRaCIS.Core.Application/Service/Management/UserService.cs @@ -12,6 +12,7 @@ using IRaCIS.Core.Infra.Common.Cache; using Microsoft.Identity.Client; using static IRaCIS.Core.Domain.Share.StaticData; using IRaCIS.Core.Application.ViewModel; +using Medallion.Threading; namespace IRaCIS.Application.Services { @@ -24,7 +25,7 @@ namespace IRaCIS.Application.Services private readonly IRepository _userTrialRepository; private readonly IRepository _userLogRepository; - + private readonly IDistributedLockProvider _distributedLockProvider; private readonly IMemoryCache _cache; private readonly IOptionsMonitor _verifyConfig; @@ -38,7 +39,8 @@ namespace IRaCIS.Application.Services IRepository userTrialRepository, IOptionsMonitor verifyConfig, IRepository userLogRepository - ) +, + IDistributedLockProvider distributedLockProvider) { _userLogRepository = userLogRepository; @@ -47,9 +49,10 @@ namespace IRaCIS.Application.Services _userRepository = userRepository; _mailVerificationService = mailVerificationService; _verificationCodeRepository = verificationCodeRepository; - + _userTrialRepository = userTrialRepository; _userLogRepository = userLogRepository; + _distributedLockProvider = distributedLockProvider; } @@ -502,29 +505,32 @@ namespace IRaCIS.Application.Services var saveItem = _mapper.Map(userAddModel); - saveItem.Code = await _userRepository.Select(t => t.Code).DefaultIfEmpty().MaxAsync() + 1; + var @lock = _distributedLockProvider.CreateLock($"UserAccount"); - saveItem.UserCode = AppSettings.GetCodeStr(saveItem.Code, nameof(User)); - - if (saveItem.IsZhiZhun) + using (await @lock.AcquireAsync()) { - saveItem.OrganizationName = AppSettings.DefaultInternalOrganizationName; + saveItem.Code = await _userRepository.Select(t => t.Code).DefaultIfEmpty().MaxAsync() + 1; + + saveItem.UserCode = AppSettings.GetCodeStr(saveItem.Code, nameof(User)); + + if (saveItem.IsZhiZhun) + { + saveItem.OrganizationName = AppSettings.DefaultInternalOrganizationName; + } + + + saveItem.Password = MD5Helper.Md5("123456"); + + await _userRepository.AddAsync(saveItem); + + var success = await _userRepository.SaveChangesAsync(); } - - saveItem.Password = MD5Helper.Md5("123456"); - - await _userRepository.AddAsync(saveItem); - - var success = await _userRepository.SaveChangesAsync(); - - + await _mailVerificationService.AddUserSendEmailAsync(saveItem.Id, userAddModel.BaseUrl, userAddModel.RouteUrl); - - - return ResponseOutput.Result(success, new UserAddedReturnDTO { Id = saveItem.Id, UserCode = saveItem.UserCode }); + return ResponseOutput.Ok( new UserAddedReturnDTO { Id = saveItem.Id, UserCode = saveItem.UserCode }); } diff --git a/IRaCIS.Core.Application/Service/QC/NoneDicomStudyService.cs b/IRaCIS.Core.Application/Service/QC/NoneDicomStudyService.cs index fa912838f..e6a40c3bf 100644 --- a/IRaCIS.Core.Application/Service/QC/NoneDicomStudyService.cs +++ b/IRaCIS.Core.Application/Service/QC/NoneDicomStudyService.cs @@ -5,10 +5,10 @@ //-------------------------------------------------------------------- using Microsoft.AspNetCore.Mvc; using IRaCIS.Core.Application.Filter; -using Nito.AsyncEx; using System.ComponentModel.DataAnnotations; using IRaCIS.Core.Application.Service; using IRaCIS.Core.Domain.Share; +using Medallion.Threading; namespace IRaCIS.Core.Application.Contracts { @@ -20,19 +20,19 @@ namespace IRaCIS.Core.Application.Contracts { private readonly IRepository _noneDicomStudyRepository; private readonly IRepository _noneDicomStudyFileRepository; - private readonly AsyncLock _mutex = new AsyncLock(); + private readonly IDistributedLockProvider _distributedLockProvider; private readonly QCCommon _qCCommon; public NoneDicomStudyService(IRepository noneDicomStudyRepository, QCCommon qCCommon, - IRepository noneDicomStudyFileRepository) + IRepository noneDicomStudyFileRepository, IDistributedLockProvider distributedLockProvider) { _qCCommon = qCCommon; _noneDicomStudyRepository = noneDicomStudyRepository; _noneDicomStudyFileRepository = noneDicomStudyFileRepository; - + _distributedLockProvider = distributedLockProvider; } @@ -62,7 +62,9 @@ namespace IRaCIS.Core.Application.Contracts } NoneDicomStudy? optEntity = null; - using (await _mutex.LockAsync()) + var @lock = _distributedLockProvider.CreateLock($"NoneDicomCode"); + + using (await @lock.AcquireAsync()) { if (addOrEditNoneDicomStudy.Id == Guid.Empty || addOrEditNoneDicomStudy.Id == null) { diff --git a/IRaCIS.Core.Application/Service/QC/QCOperationService.cs b/IRaCIS.Core.Application/Service/QC/QCOperationService.cs index 0e905e2f8..5f8e7e621 100644 --- a/IRaCIS.Core.Application/Service/QC/QCOperationService.cs +++ b/IRaCIS.Core.Application/Service/QC/QCOperationService.cs @@ -10,13 +10,13 @@ using WinSCP; using Newtonsoft.Json; using IRaCIS.Core.Infrastructure; using IRaCIS.Core.Application.Service.Inspection.DTO; -using Nito.AsyncEx; using System.ComponentModel.DataAnnotations; using IRaCIS.Core.Application.Auth; using IRaCIS.Core.Application.Helper; using IRaCIS.Core.Application.ViewModel; using IRaCIS.Core.Domain.Models; using IRaCIS.Core.Application.Service; +using Medallion.Threading; namespace IRaCIS.Core.Application.Image.QA { @@ -35,8 +35,7 @@ namespace IRaCIS.Core.Application.Image.QA private readonly IRepository _trialRepository; private readonly IRepository _visitTaskRepository; private readonly IVisitTaskHelpeService _IVisitTaskHelpeService; - - private readonly AsyncLock _mutex = new AsyncLock(); + private readonly IDistributedLockProvider _distributedLockProvider; public QCOperationService(IRepository subjectVisitRepository, IRepository qcChallengeRepository, @@ -48,7 +47,8 @@ namespace IRaCIS.Core.Application.Image.QA IRepository readingClinicalDataRepository, IRepository qCChallengeDialogrepository, IRepository checkChallengeDialogrepository, - IVisitTaskHelpeService visitTaskHelpeService + IVisitTaskHelpeService visitTaskHelpeService, + IDistributedLockProvider distributedLockProvider ) { _subjectVisitRepository = subjectVisitRepository; @@ -62,6 +62,7 @@ namespace IRaCIS.Core.Application.Image.QA _trialRepository = trialRepository; this._visitTaskRepository = visitTaskRepository; _IVisitTaskHelpeService = visitTaskHelpeService; + _distributedLockProvider = distributedLockProvider; } #region QC质疑 以及回复 关闭 @@ -108,9 +109,9 @@ namespace IRaCIS.Core.Application.Image.QA var trialConfig = (await _trialRepository.Where(t => t.Id == trialId).Select(t => new { TrialId = t.Id, t.QCProcessEnum, t.IsImageConsistencyVerification }).FirstOrDefaultAsync()).IfNullThrowException(); + var @lock = _distributedLockProvider.CreateLock($"QCChallengeCode"); - - using (await _mutex.LockAsync()) + using (await @lock.AcquireAsync()) { //获取编号 var code = _qcChallengeRepository.Where(t => t.TrialId == trialId).Select(t => t.Code).DefaultIfEmpty().Max(); diff --git a/IRaCIS.Core.Application/Service/SiteSurvey/TrialSiteSurveyService.cs b/IRaCIS.Core.Application/Service/SiteSurvey/TrialSiteSurveyService.cs index 0984a186b..523db6363 100644 --- a/IRaCIS.Core.Application/Service/SiteSurvey/TrialSiteSurveyService.cs +++ b/IRaCIS.Core.Application/Service/SiteSurvey/TrialSiteSurveyService.cs @@ -21,6 +21,7 @@ using DocumentFormat.OpenXml.Spreadsheet; using IRaCIS.Core.Domain.Models; using IRaCIS.Core.Application.ViewModel; using Dicom; +using Medallion.Threading; namespace IRaCIS.Core.Application.Contracts { @@ -36,13 +37,14 @@ namespace IRaCIS.Core.Application.Contracts private readonly IRepository _trialSiteRepository; private readonly IRepository _trialUserRepository; private readonly IRepository _trialSiteUserRepository; + private readonly IDistributedLockProvider _distributedLockProvider; private readonly ITokenService _tokenService; private readonly IMailVerificationService _mailVerificationService; public TrialSiteSurveyService(IRepository trialSiteSurveyRepository, IRepository trialUserRepository, IRepository trialSiteUserSurveyRepository, IRepository userRepository, IRepository trialSiteRepository, ITokenService tokenService, - IMailVerificationService mailVerificationService, IRepository trialSiteUserRepository) + IMailVerificationService mailVerificationService, IRepository trialSiteUserRepository, IDistributedLockProvider distributedLockProvider) { _trialSiteSurveyRepository = trialSiteSurveyRepository; _trialSiteUserSurveyRepository = trialSiteUserSurveyRepository; @@ -52,9 +54,9 @@ namespace IRaCIS.Core.Application.Contracts _tokenService = tokenService; _mailVerificationService = mailVerificationService; _trialSiteUserRepository = trialSiteUserRepository; + _distributedLockProvider = distributedLockProvider; } - private object lockObj { get; set; } = new object(); /// /// 发送验证码 @@ -792,7 +794,9 @@ namespace IRaCIS.Core.Application.Contracts if (sysUserInfo == null) { - lock (lockObj) + var @lock = _distributedLockProvider.CreateLock($"UserCode"); + + using (await @lock.AcquireAsync()) { var saveItem = _mapper.Map(item); @@ -972,7 +976,9 @@ namespace IRaCIS.Core.Application.Contracts if (sysUserInfo == null) { - lock (lockObj) + var @lock = _distributedLockProvider.CreateLock($"UserCode"); + + using (await @lock.AcquireAsync()) { var saveItem = _mapper.Map(item); diff --git a/IRaCIS.Core.Application/Service/TrialSiteUser/TrialExternalUserService.cs b/IRaCIS.Core.Application/Service/TrialSiteUser/TrialExternalUserService.cs index 6bf00a16e..96704f954 100644 --- a/IRaCIS.Core.Application/Service/TrialSiteUser/TrialExternalUserService.cs +++ b/IRaCIS.Core.Application/Service/TrialSiteUser/TrialExternalUserService.cs @@ -16,6 +16,7 @@ using Panda.DynamicWebApi.Attributes; using IRaCIS.Core.Application.Auth; using IRaCIS.Application.Services; using IRaCIS.Core.Application.Filter; +using Medallion.Threading; namespace IRaCIS.Core.Application.Service { @@ -31,10 +32,11 @@ namespace IRaCIS.Core.Application.Service private readonly IRepository _trialSiteSurveyUserRepository; private readonly IRepository _trialSiteUserRepository; private readonly IMailVerificationService _mailVerificationService; + private readonly IDistributedLockProvider _distributedLockProvider; public TrialExternalUserService(IRepository trialExternalUseRepository, IRepository userRepository, IRepository trialUserRepository, IRepository trialSiteSurveyUserRepository, IRepository trialSiteUserRepository, - IMailVerificationService mailVerificationService) + IMailVerificationService mailVerificationService, IDistributedLockProvider distributedLockProvider) { _trialExternalUseRepository = trialExternalUseRepository; _userRepository = userRepository; @@ -43,6 +45,7 @@ namespace IRaCIS.Core.Application.Service _trialSiteUserRepository = trialSiteUserRepository; _mailVerificationService = mailVerificationService; + _distributedLockProvider = distributedLockProvider; } @@ -75,121 +78,125 @@ namespace IRaCIS.Core.Application.Service if (addOrEditTrialExternalUser.Id == null) { - var existSysUser = await _userRepository.FirstOrDefaultAsync(t => t.EMail == addOrEditTrialExternalUser.Email && t.UserTypeId == addOrEditTrialExternalUser.UserTypeId); + var @lock = _distributedLockProvider.CreateLock($"UserCode"); - if (existSysUser != null) + using (await @lock.AcquireAsync()) { - if (existSysUser.LastName != addOrEditTrialExternalUser.LastName || existSysUser.FirstName != addOrEditTrialExternalUser.FirstName) + var existSysUser = await _userRepository.FirstOrDefaultAsync(t => t.EMail == addOrEditTrialExternalUser.Email && t.UserTypeId == addOrEditTrialExternalUser.UserTypeId); + + if (existSysUser != null) { - //$"该用户在系统中的用户名为:{existSysUser.LastName + " / " + existSysUser.FirstName} 电话:{existSysUser.Phone},与填写信息存在不一致项, 请将界面信息修改为与系统一致,再进行保存", - return ResponseOutput.NotOk(_localizer["TrialExternalUser_Inconsistency", existSysUser.LastName + " / " + existSysUser.FirstName, existSysUser.Phone], new { existSysUser.LastName, existSysUser.FirstName, existSysUser.Phone, existSysUser.IsZhiZhun, existSysUser.IsTestUser }, ApiResponseCodeEnum.NeedTips); + if (existSysUser.LastName != addOrEditTrialExternalUser.LastName || existSysUser.FirstName != addOrEditTrialExternalUser.FirstName) + { + //$"该用户在系统中的用户名为:{existSysUser.LastName + " / " + existSysUser.FirstName} 电话:{existSysUser.Phone},与填写信息存在不一致项, 请将界面信息修改为与系统一致,再进行保存", + return ResponseOutput.NotOk(_localizer["TrialExternalUser_Inconsistency", existSysUser.LastName + " / " + existSysUser.FirstName, existSysUser.Phone], new { existSysUser.LastName, existSysUser.FirstName, existSysUser.Phone, existSysUser.IsZhiZhun, existSysUser.IsTestUser }, ApiResponseCodeEnum.NeedTips); + } + } - } + //处理 生成账户 - //处理 生成账户 - - if (await _trialExternalUseRepository.AnyAsync(t => - t.Email == addOrEditTrialExternalUser.Email && - t.UserTypeId == addOrEditTrialExternalUser.UserTypeId && t.TrialId == addOrEditTrialExternalUser.TrialId)) - { - //---系统已经存在与列表中填写的邮箱和用户类型相同的账户,请确认。 - return ResponseOutput.NotOk(_localizer["TrialExternalUser_EmailTypeDuplicate"]); - } + if (await _trialExternalUseRepository.AnyAsync(t => + t.Email == addOrEditTrialExternalUser.Email && + t.UserTypeId == addOrEditTrialExternalUser.UserTypeId && t.TrialId == addOrEditTrialExternalUser.TrialId)) + { + //---系统已经存在与列表中填写的邮箱和用户类型相同的账户,请确认。 + return ResponseOutput.NotOk(_localizer["TrialExternalUser_EmailTypeDuplicate"]); + } - var addEntity = _mapper.Map(addOrEditTrialExternalUser); + var addEntity = _mapper.Map(addOrEditTrialExternalUser); - await _trialExternalUseRepository.AddAsync(addEntity); + await _trialExternalUseRepository.AddAsync(addEntity); - var existUser = await _userRepository.FirstOrDefaultAsync(t => t.EMail == addOrEditTrialExternalUser.Email && t.UserTypeId == addOrEditTrialExternalUser.UserTypeId); - var trialType = await _repository.Where(t => t.Id == addOrEditTrialExternalUser.TrialId).Select(t => t.TrialType).FirstOrDefaultAsync(); + var existUser = await _userRepository.FirstOrDefaultAsync(t => t.EMail == addOrEditTrialExternalUser.Email && t.UserTypeId == addOrEditTrialExternalUser.UserTypeId); + var trialType = await _repository.Where(t => t.Id == addOrEditTrialExternalUser.TrialId).Select(t => t.TrialType).FirstOrDefaultAsync(); - if (existUser != null) - { - addEntity.IsSystemUser = true; - addEntity.SystemUserId = existUser.Id; + if (existUser != null) + { + addEntity.IsSystemUser = true; + addEntity.SystemUserId = existUser.Id; - } - else - { + } + else + { - //生成账户 并插入 + //生成账户 并插入 - var generateUser = _mapper.Map(addOrEditTrialExternalUser); + var generateUser = _mapper.Map(addOrEditTrialExternalUser); + + if (trialType == TrialType.NoneOfficial) + { + generateUser.IsTestUser = true; + } + + // 外部人员生成账号 都是外部的 + generateUser.IsZhiZhun = false; + + generateUser.Code = _userRepository.Select(t => t.Code).DefaultIfEmpty().Max() + 1; + + + generateUser.UserCode = AppSettings.GetCodeStr(generateUser.Code, nameof(User)); + + generateUser.UserName = generateUser.UserCode; + + generateUser.UserTypeEnum = _repository.Where(t => t.Id == generateUser.UserTypeId).Select(t => t.UserTypeEnum).First(); + + generateUser.Password = MD5Helper.Md5("123456"); + + generateUser.Status = UserStateEnum.Disable; + + var newAddUser = await _repository.AddAsync(generateUser); + + + addEntity.IsSystemUser = false; + addEntity.SystemUserId = newAddUser.Id; + + + existUser = newAddUser; + + } + + #region 验证用户 能否加入 + + if (trialType == TrialType.OfficialTrial || trialType == TrialType.Training) + { + + if (existUser.IsTestUser) + { + //---正式类型 、培训类型的项目 不允许加入测试用户 + throw new BusinessValidationFailedException(_localizer["TrialExternalUser_TestUserNotAllowed"]); + + } + } if (trialType == TrialType.NoneOfficial) { - generateUser.IsTestUser = true; + + if (existUser.IsTestUser == false) + { + //---测试项目 不允许加入正式用户 + throw new BusinessValidationFailedException(_localizer["TrialExternalUser_FormalUserNotAllowed"]); + } } - // 外部人员生成账号 都是外部的 - generateUser.IsZhiZhun = false; - - generateUser.Code = _userRepository.Select(t => t.Code).DefaultIfEmpty().Max() + 1; + #endregion - generateUser.UserCode = AppSettings.GetCodeStr(generateUser.Code, nameof(User)); - - generateUser.UserName = generateUser.UserCode; - - generateUser.UserTypeEnum = _repository.Where(t => t.Id == generateUser.UserTypeId).Select(t => t.UserTypeEnum).First(); - - generateUser.Password = MD5Helper.Md5("123456"); - - generateUser.Status = UserStateEnum.Disable; - - var newAddUser = await _repository.AddAsync(generateUser); + await _trialExternalUseRepository.SaveChangesAsync(); - addEntity.IsSystemUser = false; - addEntity.SystemUserId = newAddUser.Id; - - - existUser = newAddUser; - - } - - #region 验证用户 能否加入 - - if (trialType == TrialType.OfficialTrial || trialType == TrialType.Training) - { - - if (existUser.IsTestUser) + //添加的时候就发邮件 现在省略 + if (addOrEditTrialExternalUser.IsSendEmail) { - //---正式类型 、培训类型的项目 不允许加入测试用户 - throw new BusinessValidationFailedException(_localizer["TrialExternalUser_TestUserNotAllowed"]); - - } - } - - if (trialType == TrialType.NoneOfficial) - { - - if (existUser.IsTestUser == false ) - { - //---测试项目 不允许加入正式用户 - throw new BusinessValidationFailedException(_localizer["TrialExternalUser_FormalUserNotAllowed"]); - } - } - - #endregion - - - await _trialExternalUseRepository.SaveChangesAsync(); - - - //添加的时候就发邮件 现在省略 - if (addOrEditTrialExternalUser.IsSendEmail) - { - await SendExternalUserJoinEmail(new TrialExternalUserSendEmail() - { - BaseUrl = addOrEditTrialExternalUser.BaseUrl, - RouteUrl = addOrEditTrialExternalUser.RouteUrl, - TrialId = addOrEditTrialExternalUser.TrialId, - SendUsers = new List() + await SendExternalUserJoinEmail(new TrialExternalUserSendEmail() + { + BaseUrl = addOrEditTrialExternalUser.BaseUrl, + RouteUrl = addOrEditTrialExternalUser.RouteUrl, + TrialId = addOrEditTrialExternalUser.TrialId, + SendUsers = new List() { new UserEmail() { @@ -199,12 +206,13 @@ namespace IRaCIS.Core.Application.Service SystemUserId=addEntity.SystemUserId } } - }); + }); + } + + + return ResponseOutput.Ok(addEntity.Id.ToString()); } - - return ResponseOutput.Ok(addEntity.Id.ToString()); - } else {