向用户添加角色,获得 SQL 超时
Adding role to user, getting a SQL timeout
在我的应用程序中(MVC/WebAPI,使用 Owin)我使用 localDB 设置了集成测试。在我的一项测试中,我似乎能够从 UserManager 查询数据,但我无法更新任何数据。
ApplicationUserManager 设置:
public class ApplicationUserManager : UserManager<ApplicationUser>
{
public ApplicationUserManager(IUserStore<ApplicationUser> store) : base(store)
{
UserValidator = new UserValidator<ApplicationUser>(this)
{
AllowOnlyAlphanumericUserNames = false,
RequireUniqueEmail = true
};
PasswordValidator = new PasswordValidator
{
RequiredLength = 6,
RequireNonLetterOrDigit = true,
RequireDigit = true,
RequireLowercase = true,
RequireUppercase = true,
};
UserLockoutEnabledByDefault = true;
DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5);
MaxFailedAccessAttemptsBeforeLockout = 5;
}
}
Unity 设置:
container
.RegisterType<DbContext, ApplicationDbContext>()
.RegisterType<IUserStore<ApplicationUser>, UserStore<ApplicationUser>>()
.RegisterType<IAuthenticationManager>(new InjectionFactory(o => HttpContext.Current.GetOwinContext().Authentication))
.RegisterType<IRoleStore<IdentityRole, string>, RoleStore<IdentityRole, string, IdentityUserRole>>()
.RegisterType<ApplicationUserManager>()
.RegisterType<ApplicationSignInManager>()
.RegisterType<ApplicationRoleManager>()
正在测试的代码:
//Working
var user = await _applicationUserManager.FindByIdAsync(userId);
//SQL timeout
identityResult = await _applicationUserManager.AddToRoleAsync(user.Id, Roles.User);
我尝试了其他更新(例如更新用户名),但 none 似乎有效。当我在使用网站时(或在使用 Postman 的 API 调用中)调用相同的功能时,一切正常。
有什么建议吗?
更新 1:
当我将 sql 超时设置提高到 180 秒时,我能够通过第一个 usermanager 更新(等待大约 60 秒后)。对数据库的任何后续调用都会失败,并且提供程序打开时失败。
更新二:
我用同样的方法测试了 localdb 的性能:
for (int i = 0; i < 1000; i++)
{
_test.LogError(new System.Exception(), Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), Guid.NewGuid().ToString());
}
此操作(1000 次不同数据的插入)大约需要 1 秒才能完成。
更新 3:
当我更新用户后暂停测试时,我无法再访问 SSMS 中的数据库。好像是锁定状态。
更新四:
出于测试目的,我自己在用户管理器中编写了更新代码。我不再超时,但它似乎保持连接或事务打开。虽然 运行 以下代码我似乎无法 select SSMS 中用户 table 的任何内容。
var userToUpgrade = _context.Users.Single(user => user.Id == userId);
foreach (var role in userToUpgrade.Roles.ToList())
{
userToUpgrade.Roles.Remove(role);
}
userToUpgrade.Roles.Add(new IdentityUserRole
{
UserId = userId,
RoleId = _context.Roles.Single(role => role.Name == Roles.TestUser).Id
});
_context.Entry(userToUpgrade).State = EntityState.Modified;
_context.SaveChanges();
嗯,那是愚蠢的。
更改了以下代码:
internal void StartTestScope()
{
_transactionScope = new TransactionScope();
}
收件人:
internal void StartTestScope()
{
TransactionOptions options = new TransactionOptions();
options.IsolationLevel = IsolationLevel.ReadUncommitted;
_transactionScope = new TransactionScope(TransactionScopeOption.RequiresNew, options);
}
在开始我的集成测试之前,我开始一个新的 scope/transaction。 运行 测试后,我把它拆了。 usermanager 内部启动了它自己的事务,导致我无法读取更改。
感谢您的建议,帮助我找到了正确的方向!
在我的应用程序中(MVC/WebAPI,使用 Owin)我使用 localDB 设置了集成测试。在我的一项测试中,我似乎能够从 UserManager 查询数据,但我无法更新任何数据。
ApplicationUserManager 设置:
public class ApplicationUserManager : UserManager<ApplicationUser>
{
public ApplicationUserManager(IUserStore<ApplicationUser> store) : base(store)
{
UserValidator = new UserValidator<ApplicationUser>(this)
{
AllowOnlyAlphanumericUserNames = false,
RequireUniqueEmail = true
};
PasswordValidator = new PasswordValidator
{
RequiredLength = 6,
RequireNonLetterOrDigit = true,
RequireDigit = true,
RequireLowercase = true,
RequireUppercase = true,
};
UserLockoutEnabledByDefault = true;
DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5);
MaxFailedAccessAttemptsBeforeLockout = 5;
}
}
Unity 设置:
container
.RegisterType<DbContext, ApplicationDbContext>()
.RegisterType<IUserStore<ApplicationUser>, UserStore<ApplicationUser>>()
.RegisterType<IAuthenticationManager>(new InjectionFactory(o => HttpContext.Current.GetOwinContext().Authentication))
.RegisterType<IRoleStore<IdentityRole, string>, RoleStore<IdentityRole, string, IdentityUserRole>>()
.RegisterType<ApplicationUserManager>()
.RegisterType<ApplicationSignInManager>()
.RegisterType<ApplicationRoleManager>()
正在测试的代码:
//Working
var user = await _applicationUserManager.FindByIdAsync(userId);
//SQL timeout
identityResult = await _applicationUserManager.AddToRoleAsync(user.Id, Roles.User);
我尝试了其他更新(例如更新用户名),但 none 似乎有效。当我在使用网站时(或在使用 Postman 的 API 调用中)调用相同的功能时,一切正常。
有什么建议吗?
更新 1:
当我将 sql 超时设置提高到 180 秒时,我能够通过第一个 usermanager 更新(等待大约 60 秒后)。对数据库的任何后续调用都会失败,并且提供程序打开时失败。
更新二:
我用同样的方法测试了 localdb 的性能:
for (int i = 0; i < 1000; i++)
{
_test.LogError(new System.Exception(), Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), Guid.NewGuid().ToString());
}
此操作(1000 次不同数据的插入)大约需要 1 秒才能完成。
更新 3:
当我更新用户后暂停测试时,我无法再访问 SSMS 中的数据库。好像是锁定状态。
更新四:
出于测试目的,我自己在用户管理器中编写了更新代码。我不再超时,但它似乎保持连接或事务打开。虽然 运行 以下代码我似乎无法 select SSMS 中用户 table 的任何内容。
var userToUpgrade = _context.Users.Single(user => user.Id == userId);
foreach (var role in userToUpgrade.Roles.ToList())
{
userToUpgrade.Roles.Remove(role);
}
userToUpgrade.Roles.Add(new IdentityUserRole
{
UserId = userId,
RoleId = _context.Roles.Single(role => role.Name == Roles.TestUser).Id
});
_context.Entry(userToUpgrade).State = EntityState.Modified;
_context.SaveChanges();
嗯,那是愚蠢的。
更改了以下代码:
internal void StartTestScope()
{
_transactionScope = new TransactionScope();
}
收件人:
internal void StartTestScope()
{
TransactionOptions options = new TransactionOptions();
options.IsolationLevel = IsolationLevel.ReadUncommitted;
_transactionScope = new TransactionScope(TransactionScopeOption.RequiresNew, options);
}
在开始我的集成测试之前,我开始一个新的 scope/transaction。 运行 测试后,我把它拆了。 usermanager 内部启动了它自己的事务,导致我无法读取更改。
感谢您的建议,帮助我找到了正确的方向!