我有一个ASP.NET MVC 6应用程序。当用户在Angular中进入客户端时,我会对ASP.NET的Async API进行一些调用。在某些地方,我会将Api调用3-4次来获取其他资源。
我还在我的数据库中保留了一个User表,与EF 6连接。当我输入的用户(使用Windows Auth)尚未存在并添加'Public'角色时,我创建了一个新的User行对他来说。
但是,当用户首次进入调用Api 3-4次的页面时,用户会被创建3-4次,因为“创建”没有锁定表格,从而创建了3次用户。
如何锁定表(我的情况下的存储库)以使下一个调用等待锁被删除,然后执行'GetAsync'来检查用户是否存在?
被调用3次的代码:
var currentUserName = User.Identity.Name;
var currentUser = await _userRepository.GetAsync(u => u.UserName == currentUserName);
// Create user that does not yet exist
if (currentUser != null) return HttpBadRequest();
var user = new User(currentUserName);
using(new CreatedBySystemProvider(_userRepository))
{
_userRepository.Add(user);
await _userRepository.SaveChangesAsync();
await user.AddRoleAsync(AppSumRoles.Authenticated);
/* Temporary add SysAdmin role */
if(string.Equals(currentUserName, @"BIJTJES\NilsG", StringComparison.CurrentCultureIgnoreCase))
{
using(new CreatedBySystemProvider(_userRoleRepository))
{
await user.AddRoleAsync(AppSumRoles.SysAdmin);
}
}
currentUser = await _userRepository.GetAsync(u => u.Id == user.Id);
}
return Ok(currentUser);
答案 0 :(得分:0)
考虑将CreateUser
代码移到单独的API中。用户创建应该是一个单独的用例,而不是每个其他用例的隐含部分。不要混淆顾虑。
答案 1 :(得分:0)
您应该考虑重构您的用户创建过程。但只是为了你的问题,你可以做这样的事情
(有关详情,请参阅http://blogs.msdn.com/b/pfxteam/archive/2012/02/12/10266988.aspx)
private static readonly AsyncLock asyncLocker = new AsyncLock();
var currentUserName = User.Identity.Name;
using(var releaser = await asyncLocker.LockAsync())
{
var currentUser = await _userRepository.GetAsync(u => u.UserName == currentUserName);
// Create user that does not yet exist
if (currentUser != null) return HttpBadRequest();
var user = new User(currentUserName);
using(new CreatedBySystemProvider(_userRepository))
{
_userRepository.Add(user);
await _userRepository.SaveChangesAsync();
await user.AddRoleAsync(AppSumRoles.Authenticated);
/* Temporary add SysAdmin role */
if(string.Equals(currentUserName, @"BIJTJES\NilsG", StringComparison.CurrentCultureIgnoreCase))
{
using(new CreatedBySystemProvider(_userRoleRepository))
{
await user.AddRoleAsync(AppSumRoles.SysAdmin);
}
}
currentUser = await _userRepository.GetAsync(u => u.Id == user.Id);
}
}
return Ok(currentUser);