需要帮助检查并将用户添加到多个角色异步

时间:2014-08-15 14:27:53

标签: c# asp.net asp.net-mvc asynchronous asp.net-identity

我正在使用ASP.Net MVC 5并且正在创建一个控制器以允许管理员将用户添加到角色。这就是控制器的非异步版本:

public JsonResult UerRoles(string userid, string[] roles)
{
   foreach(var role in roles)
   {
      if(!UserManager.IsInRole(userid, role))
      {
         UserManager.AddToRole(userid, role);
      }
    }

    ...
 }

我想使用UserManager.IsInRoleAsync和UserManager.AddToRoleAsync方法,并希望并行运行这些方法,然后暂停执行线程,直到完成所有操作。我之前没有做异步线程,但看起来我可以这样做:

public async Task<JsonResult> UserRoles(string userid, string[] roles)
{
   IList<Task<IdentityResult>> tasks = new List<Task<bool>>();
   foreach(var role in roles)
   {
      tasks.Add(UserManager.AddToRoleAsync(userid, role));
   }

   await Task.WhenAll(tasks);

   ...
 }

但是,我不知何故需要考虑检查用户是否已经在角色中的条件逻辑 - 即UserManager.IsInRoleAsycn(userid,role)。我不确定如何检查并有条件地将用户并行和异步地添加到角色。

我已经看到了提到的ContinueWith方法,似乎可能会以某种方式适用,但我无法弄清楚如何实现。类似的东西:

UserManager.IsInRoleAsync(userid, role).ContinueWith(t => if(t.Result) { UserManager.AddToRole(userid, role)} ;);

有没有办法实现这个目标?

1 个答案:

答案 0 :(得分:2)

假设:您正在使用AspNet Identity的标准EF实现

您必须使用此代码:

foreach(var role in roles)
{
   var isInRole = await UserManager.IsInRoleAsync(userid, role)
   if(!isInRole)
   {
      await UserManager.AddToRoleAsync(userid, role);
   }
}

此基础ORM(实体框架)的原因不支持在并行线程中执行sql查询。如果您尝试这样做,您将获得EF的例外说法:

  

在上一次异步之前,在此上下文中启动了第二个操作   操作完成。使用'await'确保任何异步操作   在此上下文中调用另一个方法之前已完成。任何实例   成员不保证是线程安全的。

This topic有一个很好的例子。

此外,我怀疑将用户添加到角色是您系统中非常流行的操作。为什么要不顾一切地优化那些经常不会被击中的东西?

<强>更新

您无需检查IsUserInRole。身份框架无论如何都会为您做到。这是反编译身份框架的一部分:

public virtual async Task<IdentityResult> AddToRoleAsync(TKey userId, string role)
{
    // sanity checks... 

    IList<string> userRoles = await userRoleStore.GetRolesAsync(user).ConfigureAwait(false);
    IdentityResult identityResult;
    if (userRoles.Contains(role))
    {
      identityResult = new IdentityResult(new string[1]
      {
        Resources.UserAlreadyInRole
      });
    }
    else
    {
    // actually add user to role
    }
    return identityResult;
}