2016-06-28 74 views
0

在我的一個應用程序中,我重寫了Asp Core Identity UserManager的CreateAsync,除了在UserStore中創建新用戶之外 - 在單獨的統計表中創建一個新行不同的dbcontext)。問題是,我希望這些操作都在事務內部被觸發,這樣如果一個操作失敗 - 另一個操作不會提交。下面的代碼:與ASP.NET Core 1.0 Identity UserManager交易

public override async Task<IdentityResult> CreateAsync(TUser user, string password) 
    { 
     // We need to use transactions here.    
      var result = await base.CreateAsync(user, password); 

      if (result.Succeeded) 
      { 
       var appUser = user as IdentityUser; 

       if (appUser != null) 
       { 
        // create user stats. 
        var userStats = new UserStats() 
        { 
         ActionsCount = 0, 
         EventsCount = 0, 
         FollowersCount = 0, 
         ProjectsCount = 0, 
         UserId = appUser.Id 
        }; 

        _ctx.UserStats.Add(userStats); 
        await _ctx.SaveChangesAsync(); 
       } 
      }  
      return result; 
    } 

事情是,我不知道如何建立這樣一個交易,因爲它似乎TransactionScope的是不是對.NET核心的一部分,但和獲得目前選擇的DbContext爲基數(?)。 CreateAsync()與HttpContext.GetOwinContext()不起作用,因爲HttpContext似乎缺少這種方法(引用Microsoft.Owin.Host.SystemWeb或Microsoft.AspNet.WebApi.Owin作爲暗示在其他堆棧溢出答案不會做 - 兩者都不兼容.netcore)。任何幫助?

回答

2

首先你需要設置你使用的是有身份的DbContext與範圍的一生:

 services.AddDbContext<MyDbContext>(ServiceLifetime.Scoped); // this is the important bit 

     services.AddIdentity<User, Role>(options => 
     { 
     }) 
     .AddEntityFrameworkStores<MyDbContext, int>() 
     .AddDefaultTokenProviders(); 

然後,當你需要創建你做的交易如下:

 using (var transaction = await _myDbContext.Database.BeginTransactionAsync()) 
     { 
      var result = await _userManager.CreateAsync(newUser, password); 

      try 
      { 
       if (result.Succeeded) 
       { 
        DBItem newItem = new DBItem(); 
        _myDbContext.Add(newItem); 

        await _myDbContext.SaveChangesAsync(); 
        transaction.Commit(); 
       } 
      } 
      catch (Exception e) 
      { 
       transaction.Rollback(); 
      } 
     } 
+0

偉大的東西!感謝你這個方向,似乎它可能是一條路,如果我只能配置Scoped生命週期,似乎在EF 1.0.0-rc2-final中,AddDbContext沒有采用ServiceLifetime的方法,也沒有允許您爲DbContext設置Transient/Scoped生命週期,並且我無法升級到1.0.0,因爲它會中斷我的應用程序,因此必須等待以查看它是否有效。 – RRob

+0

我已經註冊了兩個上下文,例如: – RRob

+0

我已經註冊了兩個上下文,例如: \t services.AddScoped (); services.AddScoped (); 但仍然,等待base.CreateAsync(用戶,密碼);不關心交易範圍。 – RRob

0

我相信下面的是一個正確的方向:

using (var transaction = _context.Database.BeginTransaction()) 
{ 

} 
+0

這將是一個很好的方向,但我該如何獲得cur租用上下文使用UserManager內的Base.CreateAsync(用戶,密碼)在第一位? – RRob

+0

我目前看到的唯一解決方案是檢索當前作用域(由DI注入)DbContext,註冊爲services.AddIdentity ... AddEntityFrameworkStores through HttpContext.GetOwinContext()。獲取()如下所示:http:// stackoverflow.com/questions/32858014/how-to-create-transaction-with-asp-net-identity,但是無法找到一種方法來使HttpContext有GetOwinContext()方法在Asp Core 1 – RRob