使用:Asp.net Core、Entityframework Core、ABP 4.5
我有一个用户注册和初始化流程。但这需要很长时间。我想并行化这个。这是由于从同一实体进行更新,但具有不同的字段。
我的目标: 1. 端点应该尽快响应;2、长初始化在后台处理;
代码之前(为简洁起见省略了次要细节)
public async Task<ResponceDto> Rgistration(RegModel input)
{
var user = await _userRegistrationManager.RegisterAsync(input.EmailAddress, input.Password, false );
var result = await _userManager.AddToRoleAsync(user, defaultRoleName);
user.Code = GenerateCode();
await SendEmail(user.EmailAddress, user.Code);
await AddSubEntities(user);
await AddSubCollectionEntities(user);
await CurrentUnitOfWork.SaveChangesAsync();
return user.MapTo<ResponceDto>();
}
private async Task AddSubEntities(User user)
{
var newSubEntity = new newSubEntity { User = user, UserId = user.Id };
await _subEntityRepo.InsertAsync(newSubEntity);
//few another One-to-One entities...
}
private async Task AddSubEntities(User user)
{
List<AnotherEntity> collection = GetSomeCollection(user.Type);
await _anotherEntitieRepo.GetDbContext().AddRangeAsync(collection);
//few another One-to-Many collections...
}
尝试改变:
public async Task<ResponceDto> Rgistration(RegModel input)
{
var user = await _userRegistrationManager.RegisterAsync(input.EmailAddress, input.Password, false );
Task.Run(async () => {
var result = await _userManager.AddToRoleAsync(user, defaultRoleName);
});
Task.Run(async () => {
user.Code = GenerateCode();
await SendEmail(user.EmailAddress, user.Code);
});
Task.Run(async () => {
using (var unitOfWork = UnitOfWorkManager.Begin())
{//long operation. defalt unitOfWork out of scope
try
{
await AddSubEntities(user);
}
finally
{
unitOfWork.Complete();
}
}
});
Task.Run(async () => {
using (var unitOfWork = UnitOfWorkManager.Begin())
{
try
{
await AddSubCollectionEntities(user);
}
finally
{
unitOfWork.Complete();
}
}
});
await CurrentUnitOfWork.SaveChangesAsync();
return user.MapTo<ResponceDto>();
}
错误:在这里我得到了很多与竞争相关的不同错误。经常:
在前一个操作完成之前,在此上下文上开始了第二个操作。这通常是由使用相同 DbContext 实例的不同线程引起的。
在少数注册调用中:无法在具有唯一索引“YYY”的对象“XXX”中插入重复的键行。重复键值为 (70)。该语句已终止。
我在服务器上考虑了其流中的每个请求,但显然不是。
- 或者所有用户都成功注册,但他们在数据库中没有某些子实体。不注册用户比找出他在哪里初始化不正确要容易得多=(
如何保持用户实体“开放”以进行更新,同时“关闭”其他请求发起的更改?如何使此代码线程安全且快速,任何人都可以提供建议吗?