问题描述
我正在尝试更新用户.
AppUserManager appUserManager = HttpContext.GetOwinContext().GetUserManager<AppUserManager>();
AppUser member = await appUserManager.FindByIdAsync(User.Identity.GetUserId());
member.HasScheduledChanges = true;
IdentityResult identityResult = appUserManager.Update(member);
如果对 Web API 的后续调用失败,我需要回滚对用户的任何更改.我了解交易,例如:
If a subsequent call to a Web API fails, I need to roll back any changes to the user. I know about transactions, like this:
using (var context = HttpContext.GetOwinContext().Get<EFDbContext>())
{
using (var dbContextTransaction = context.Database.BeginTransaction())
{
try
{
// Changes
member.HasScheduledChanges = true;
// Would this be transactional?
IdentityResult identityResult = appUserManager.Update(member);
context.SaveChanges();
dbContextTransaction.Commit();
}
catch //(Exception ex)
{
// dbContextTransaction.Rollback(); no need to call this manually.
}
}
}
但是在 try 块中使用 AppUserManager 完成的操作是事务性的吗?另外,他们是否使用相同的 EFDbContext 实例?换句话说,我不知道第二个代码示例开头的 var 上下文是否会被 try 块中的 appUserManagerUpdate"方法调用使用.
But will operations done with AppUserManager inside the try block be transactional? Also, do they use the same instance of EFDbContext? In other words, I don't know if var context at the start of the second code example would be used by the appUserManager "Update" method call in the try block.
此外,AppUserManager 是这样创建的:
Also, AppUserManager is created like this:
public static AppUserManager Create(IdentityFactoryOptions<AppUserManager> options, IOwinContext context)
{
EFDbContext db = context.Get<EFDbContext>();
AppUserManager manager = new AppUserManager(new UserStore<AppUser>(db));
// etc.
return manager;
}
推荐答案
EFDbContext
在您的示例中是相同的 - 在这两种情况下,您都从 OWIN 上下文中解决它们,因此这不是问题.但是,Identity 是以与存储无关的方式编写的,这意味着存储机制可以由非 SQL Server 替代.这需要 AppUserManager
内部缺少事务.所以你需要创建你自己的.
EFDbContext
in your examples are the same - in both cases you resolve them from OWIN context, so this is not an issue. However, Identity is written in storage-agnostic fashion, meaning storage mechanism can be replaced by non SQL Server. This calls for lack of transactions inside of AppUserManager
. So you need to create your own.
我经常在我的生产应用程序中使用 var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)
(只有更多的架构):
I'm routinely using var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)
in my production applications (only with a bit more architecture):
using(var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
{
try
{
AppUserManager appUserManager = HttpContext.GetOwinContext().GetUserManager<AppUserManager>();
AppUser member = await appUserManager.FindByIdAsync(User.Identity.GetUserId());
member.HasScheduledChanges = true;
IdentityResult identityResult = appUserManager.Update(member);
scope.Complete();
}
catch (Exception ex)
{
scope.Dispose();
throw;
}
}
这篇关于与 ASP.NET Identity UserManager 的事务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!