使用ASP.NET身份的UserManager交易 [英] Transactions with ASP.NET Identity UserManager

查看:370
本文介绍了使用ASP.NET身份的UserManager交易的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想更新的用户。

  AppUserManager appUserManager = HttpContext.GetOwinContext()GetUserManager< AppUserManager>();APPUSER成员=等待appUserManager.FindByIdAsync(User.Identity.GetUserId());member.HasScheduledChanges = TRUE;IdentityResult identityResult = appUserManager.Update(会员);

如果一个Web API的后续调用失败,我需要回滚到用户的任何变化。我知道交易是这样的:

 使用(VAR上下文= HttpContext.GetOwinContext()获取< EFDbContext>())
 {
    使用(VAR dbContextTransaction = context.Database.BeginTransaction())
    {
        尝试
        {
            // 变化            member.HasScheduledChanges = TRUE;            //这会是事务性的?
            IdentityResult identityResult = appUserManager.Update(会员);            context.SaveChanges();            dbContextTransaction.Commit();
        }
        抓//(异常前)
        {            // dbContextTransaction.Rollback();无需手动调用它。
        }
    }
}

但将与AppUserManager做try块内的操作是事务性的?此外,他们使用EFDbContext的同一个实例?换句话说,我不知道,如果在第二code例子开始VAR方面将由appUserManager更新的方法在try块调用中使用。

此外,AppUserManager是这样创建:

 公共静态AppUserManager创建(IdentityFactoryOptions< AppUserManager>选项,IOwinContext上下文)
{    EFDbContext DB = context.Get< EFDbContext>();    AppUserManager经理=新AppUserManager(新UserStore<&APPUSER GT;(DB));    //等等。    返回经理;
}


解决方案

EFDbContext 在你的例子是相同的 - 在这两种情况下,你从OWIN背景下解决这些问题,所以这是不是一个问题。然而,身份被写入存储不可知方式,这意味着存储机构可以由非SQL Server的被替换。这就要求缺乏交易的内部 AppUserManager 。所以,你需要创建自己的。

我经常使用 VAR范围=新的TransactionScope(TransactionScopeAsyncFlowOption.Enabled)在我的生产应用程序(仅适用于多一点的体系结构):

 使用(VAR范围=新的TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
{
    尝试
    {
        。AppUserManager appUserManager = HttpContext.GetOwinContext()GetUserManager< AppUserManager>();        APPUSER成员=等待appUserManager.FindByIdAsync(User.Identity.GetUserId());        member.HasScheduledChanges = TRUE;        IdentityResult identityResult = appUserManager.Update(会员);
        scope.Complete();
    }
    赶上(异常前)
    {
        scope.Dispose();
        扔;
    }
}

I'm trying to update a user.

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

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

member.HasScheduledChanges = true;

IdentityResult identityResult = appUserManager.Update(member);

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

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.

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 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.

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身份的UserManager交易的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆