UserManager.Update(用户)方法不是线程安全的

时间:2017-03-27 03:22:57

标签: c# asp.net-mvc entity-framework asp.net-identity owin

我试图在控制器中使用UserManager更新用户。在我更新用户之前,对外部服务的调用会触发尝试更新同一用户的webhook,也使用UserManager。但这是一个不同的请求和应用程序的不同部分(" webhook控制器")。

这是我在控制器中调试时遇到的异常:

  

System.Data.Entity.Core.EntityException。 "在提供程序连接上启动事务时发生错误。有关详细信息,请参阅内部异常。"不允许新事务,因为会话中还有其他线程在运行。

这里是代码,在控制器和" webhook控制器"中是相同的,除了设置了不同的属性:

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

AppUser member = appUserManager.FindById(User.Identity.GetUserId());

member.Email = newEmail;

IdentityResult identityResult = appUserManager.Update(member);

AppUserManager的创建方式如下:

public static AppUserManager Create(IdentityFactoryOptions<AppUserManager> options, IOwinContext owinContext)
{           

    EFDbContext db = owinContext.Get<EFDbContext>();

    AppUserManager manager = new AppUserManager(new UserStore<AppUser>(db));

    // etc.

    return manager;
}

我对这里发生的事情感到有些困惑。我是否收到此错误,因为AppUserManager的两个实例都从OwinContext获取EFDbContext?我甚至不确定它是如何工作的。

替换

会有帮助吗?
EFDbContext db = owinContext.Get<EFDbContext>();

 EFDbContext db = new EFDbContext();

但根据这个:https://blogs.msdn.microsoft.com/webdev/2014/02/12/per-request-lifetime-management-for-usermanager-class-in-asp-net-identity/

这不是一个好主意,因为:

  

&#34;在当前的方法中,如果请求中有两个UserManager实例在同一个用户上工作,那么它们将使用两个不同的用户对象实例。这方面的一个示例是使用类属性中的一个,并在执行中的方法中本地实例化一个。在这种情况下,其中任何一个所做的更改都不会反映另一个所做的更改。因此,将这些更改持久保存回数据库会导致对用户对象进行不正确的更改。&#34;

我是否需要将更新包装在某种事务中或使用块?我不明白我是如何得到这个错误的。

以下是配置:

public void Configuration(IAppBuilder app)
{
    DataProtectionProvider = app.GetDataProtectionProvider(); 

    app.CreatePerOwinContext<EFDbContext>(EFDbContext.Create);

    app.CreatePerOwinContext<AppUserManager>(AppUserManager.Create);

    app.CreatePerOwinContext<AppRoleManager>(AppRoleManager.Create); 
}

0 个答案:

没有答案