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



我正在使用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(标识、角色)。我不知道如何检查这一点,并有条件地将用户添加到所有并行和异步的角色。

我看过提到的ContinueWith方法,它似乎可能在某种程度上适用,但我不知道如何实现。比如:

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

有办法做到这一点吗?

假设:您正在使用标准的EF实现asp.net Identity

您必须使用以下代码:

foreach(var role in roles)
{
   var isInRole = await UserManager.IsInRoleAsync(userid, role)
   if(!isInRole)
   {
      await UserManager.AddToRoleAsync(userid, role);
   }
}
这个底层ORM(实体框架)的原因是不支持在并行线程中执行sql查询。如果您尝试这样做,您将得到EF的异常,表示如下:

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

这个主题有一个很好的例子。

另外,我怀疑在您的系统中向角色添加用户是不是一个非常流行的操作。为什么要费尽心思去优化那些不会经常被击中的东西呢?

您不需要检查IsUserInRole。无论如何,身份框架都会为你做这件事。这是反编译的Identity框架的一部分:

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

相关内容

  • 没有找到相关文章

最新更新