2016-04-15 13 views
3

我在嘗試更新用戶。與ASP.NET身份用戶管理器的交易

AppUserManager appUserManager = HttpContext.GetOwinContext().GetUserManager<AppUserManager>(); 

AppUser member = await appUserManager.FindByIdAsync(User.Identity.GetUserId()); 

member.HasScheduledChanges = true; 

IdentityResult identityResult = appUserManager.Update(member); 

如果後續對Web API的調用失敗,我需要將任何更改回滾到用戶。我知道有關交易,如下所示:

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 context是否會被try塊中的appUserManager「Update」方法調用使用。

此外,AppUserManager創建這樣的:

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; 
} 

回答

5

EFDbContext在你的例子是相同的 - 在這兩種情況下,你從OWIN背景下解決這些問題,所以這不是一個問題。但是,Identity是以與存儲無關的方式編寫的,這意味着存儲機制可以被非SQL Server替代。這要求AppUserManager內部缺少交易。所以你需要創建自己的。

我經常用我的生產應用程序(僅適用於多一點架構)var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)

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; 
    } 
} 
+0

謝謝!我的第一個想法是直接使用支持事務的dbContext操作AspNetUsers表,但我認爲這是不可能的。我認爲必須使用UserManager來更新身份系統中的用戶,是否沒有其他方法? – nmit026

+2

是的,你可以通過'dbContext'直接操作用戶記錄。這就是'AppUserManager'所做的事情,只是增加了一些驗證 – trailmax

+0

你是Owin和Identity的專家,也許你可以看看這個:http://stackoverflow.com/questions/43037450/usermanager-updateuser-method- isnt線程安全 – nmit026

2

使用asp.net身份的UserManager

var appDbContext = HttpContext.GetOwinContext().Get<ApplicationDbContext>(); 
using (var identitydbContextTransaction = appDbContext.Database.BeginTransaction()) 
{ 
    try 
    { 
     var result = await UserManager.CreateAsync(user, "password"); 
     if (result.Succeeded) 
     { 
     var userinfo = await UserManager.FindByNameAsync("Email"); 
     var userId = user.Id; 
     await UserManager.AddToRoleAsync(userId, "rolename"); 

     identitydbContextTransaction.Commit(); 
     } 
    } 
    catch (Exception) 
    { 
     identitydbContextTransaction.Rollback(); 
    } 
} 
事務的完整解決方案提交/回滾

它可以幫助你,使用asp.net身份UserManager進行交易。但它的工作,如果在事務中發生任何錯誤,它將回滾所有事務。

+0

這個答案解決了我的問題,我不想使用「交易範圍」,我不得不添加引用OWIN「使用Microsoft.AspNet.Identity.Owin;」 –

+0

但是在控制器上做是正確的方式嗎?控制器與交易? –

+0

有趣的是,做這個而不是使用接受的答案有什麼好處。我期待着做幾乎相同的事情。 – span