提问人:Emre Bener 提问时间:11/9/2023 最后编辑:Emre Bener 更新时间:11/9/2023 访问量:37
ASP.NET Core Identity:如何使用 EF Core 事务?
ASP.NET Core Identity: How to Use EF Core Transactions?
问:
我在项目中使用 EF Core,并且希望在使用内置 Identity 方法(例如 或)时实现原子性。这是我的用例:CreateAsync
AddClaimsAsync
#region CREATE USER & SET ROLE
var newUser = new ApplicationUser
{
// set user properties here...
};
var result1 = await userManager.CreateAsync(newUser);
var result2 = await userManager.AddClaimsAsync(newUser, new Claim[]{
new Claim("asSuperUser", "asSuperUser")
});
#endregion
#region SEND ACCOUNT INITIALIZATION EMAIL
if (result1.Succeeded && result2.Succeeded)
{
// continue if everything went fine...
当然,如果一切顺利,没有问题,但是如果 Identity 无法向添加的用户添加声明(方法失败)怎么办?这将是个坏消息,因为整个项目都围绕着CBAC(基于声明的访问控制)展开,因此确保原子性在这里至关重要。我的问题是:在使用 Identity 的内置方法(例如 or )时,有没有办法利用 EF Core 事务,其中我不是通过 DI 直接使用 DbContext,而是使用各种 Identity 服务(例如)从而间接访问 DbContext?AddClaimsAsync
CreateAsync
AddClaimsAsync
userManager
如果我使用多个 Identity 服务(例如组合 和 ,其中每个作用域服务实例可能会创建自己的 DbContext 实例),事情会变得更加复杂。SignInManager
UserManager
答:
0赞
Emre Bener
11/9/2023
#1
事实证明,EF Core 事务可以使用标识服务方法。例:
using var transaction = await context.Database.BeginTransactionAsync();
// CREATE USER
var result1 = await userManager.CreateAsync(superUser);
if (!result1.Succeeded)
{
await transaction.RollbackAsync();
var errors1 = result1.Errors.Select(error => error.Description);
return Json(new { success = false, error = string.Join(", ", errors1) });
}
// ASSIGN RELEVANT ROLE
var result2 = await userManager.AddClaimsAsync(superUser, new Claim[]{
new Claim("asSuperUser", "asSuperUser")
});
if (!result2.Succeeded)
{
await transaction.RollbackAsync();
var errors2 = result2.Errors.Select(error => error.Description);
return Json(new { success = false, error = string.Join(", ", errors2) });
}
// await context.SaveChangesAsync(); you would only need this if you relied on change tracker, which is not the case here
await transaction.CommitAsync();
return Json(new { success = true });
评论
1赞
Panagiotis Kanavos
11/9/2023
这是我不想发布的“肮脏”方式。可以使用 TransactionScope,而不是尝试显式访问作用域的 DbContext。您也不需要任何调用,只需退出事务范围即可。释放 DbTransaction 会导致回滚。DbTransacion 和 DbContext 在此处使用相同的模式 - 除非显式提交,否则所有内容都将被丢弃RollBack
1赞
Panagiotis Kanavos
11/9/2023
你也不需要最终的,除非你自己做了任何修改。您发布此问题的真正原因是,并在内部致电。SaveChanges
CreateUserAsync
AddClaimsAsync
SaveChanges
评论
SaveChanges
SaveChanges