gpt4 book ai didi

c# - UserManager.CreateAsync(user, password) 陷入无限循环

转载 作者:太空宇宙 更新时间:2023-11-03 17:52:06 25 4
gpt4 key购买 nike

我正在尝试对 IUserStore 进行非常简单的实现这本质上是:

  • 使用 NHibernate
  • 将用户保存在一个表中(无声明/登录)
  • 将角色名称存储在同一个表中的 nvarchar 列中(管道 ( '|' )如果有多个项目,则分开)。

当我运行以下方法时:

[Fact]
public void Create_A_User()
{
// _session is a valid NHibernate ISession object
using (var userStore = new SimpleUserStore<SimpleIdentityUser>(_session))
using (var userManager = new UserManager<SimpleIdentityUser>(userStore))
{
var user = new SimpleIdentityUser
{
UserName = "kenny_mccormick",
RolesStr = "admin",
};

var createTask = userManager.CreateAsync(user, "the_password");

var result = createTask.Result; // this never finishes...
}
}

最后一行永远不会执行完。

奇怪的是 UserManager从不调用我的 SimpleUserStore 中的任何函数;在此之前它会卡住。

这是我定义的组件:

用户类:

public class SimpleIdentityUser : IUser
{
public virtual Guid UserId { get; set; }
public virtual string PasswordHash { get; set; }
public virtual string SecurityStamp { get; set; }
public virtual string RolesStr { get; set; }
public virtual string UserName { get; set; }

public virtual string Id
{
get { return UserId.ToString(); }
}
}

用户存储:

public class SimpleUserStore<TUser> :
IUserPasswordStore<TUser>,
IUserRoleStore<TUser>,
IUserSecurityStampStore<TUser>
where TUser : SimpleIdentityUser
{
// ReSharper disable once StaticFieldInGenericType
private static readonly Task EmptyTask = new Task(() => { });

private readonly ISession _session;

public SimpleUserStore(ISession session)
{
_session = session;
}

public Task<TUser> FindAsync(UserLoginInfo login)
{
return Task.FromResult((TUser) null);
}

public Task CreateAsync(TUser user)
{
_session.Save(user);
return EmptyTask;
}

public Task UpdateAsync(TUser user)
{
// updates will (hopefully) be saved automatically when the current session is committed
return EmptyTask;
}

public Task DeleteAsync(TUser user)
{
_session.Delete(user);
return EmptyTask;
}

public Task<TUser> FindByIdAsync(string userId)
{
TUser user = null;
Guid guidId;

if (Guid.TryParse(userId, out guidId))
user = _session.Get<TUser>(guidId);

return Task.FromResult(user);
}

public Task<TUser> FindByNameAsync(string userName)
{
TUser user = _session.Query<TUser>().SingleOrDefault(u => u.UserName == userName);
return Task.FromResult(user);
}

public Task SetPasswordHashAsync(TUser user, string passwordHash)
{
user.PasswordHash = passwordHash;
return EmptyTask;
}

public Task<string> GetPasswordHashAsync(TUser user)
{
return Task.FromResult(user.PasswordHash);
}

public Task<bool> HasPasswordAsync(TUser user)
{
return Task.FromResult(user.PasswordHash != null);
}

public void Dispose()
{
}

public Task AddToRoleAsync(TUser user, string role)
{
new SimpleRoleManager<TUser>(user).AddRole(role);

return EmptyTask;
}

public Task RemoveFromRoleAsync(TUser user, string role)
{
new SimpleRoleManager<TUser>(user).DeleteRole(role);

return EmptyTask;
}

public Task<IList<string>> GetRolesAsync(TUser user)
{
List<string> roles = new SimpleRoleManager<TUser>(user).GetRoles().ToList();

return Task.FromResult((IList<string>) roles);
}

public Task<bool> IsInRoleAsync(TUser user, string role)
{
return Task.FromResult(new SimpleRoleManager<TUser>(user).IsInRole(role));
}

public Task SetSecurityStampAsync(TUser user, string stamp)
{
user.SecurityStamp = stamp;
return EmptyTask;
}

public Task<string> GetSecurityStampAsync(TUser user)
{
return Task.FromResult(user.SecurityStamp);
}
}

我如何管理角色

可能不是那么重要,但无论如何:

public class SimpleRoleManager<TUser> where TUser : SimpleIdentityUser
{
private const string Separator = "|";

private readonly TUser _user;

public SimpleRoleManager(TUser user)
{
_user = user;
}

public string[] GetRoles()
{
return (_user.RolesStr ?? String.Empty)
.Split(Separator.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
}

public bool IsInRole(string roleName)
{
return GetRoles().Contains(roleName);
}

public bool AddRole(string roleName)
{
var roles = GetRoles().ToList();

if (roles.Contains(roleName))
return false;

roles.Add(roleName);
SetRoles(roles);
return true;
}

public bool DeleteRole(string roleName)
{
List<string> roles = GetRoles().ToList();

if (!roles.Contains(roleName))
return false;

roles.Remove(roleName);
SetRoles(roles);
return true;
}

private void SetRoles(IEnumerable<string> roles)
{
_user.RolesStr = String.Join(Separator, roles);
}
}

我一直在检查 UserManager<TUser>使用 DotPeek 类,但没有发现导致这种奇怪行为的明显原因。

这可能是什么原因造成的?

最佳答案

目前,您的异步方法从根本上被打破了,因为您要为所有 操作返回相同的任务...并且永远不会启动它。我在这里没有看到任何“无限循环”——我只是看到你在阻止一个永远无法完成的任务。

尚不清楚您希望使用 EmptyTask 完成什么任务,但目前绝对对您没有帮助。

此外,不清楚您的代码在任何方面是否真的是异步的,除非 _session.Save (etc) 确实是异步的。

您可以通过运行额外的任务来稍微改善一些事情,例如

public Task CreateAsync(TUser user)
{
Action action = () => _session.Save(user);
return Task.Run(action);
}

...尽管您随后会立即阻塞调用代码中的任务这一事实也使它变得毫无意义。 (目前还不清楚这是如何编译的,因为 Task 没有 Result 属性……只有 Task<T> 有。)

如评论中所述,这将创建一个新任务,该任务将有效地在新线程中同步运行 - 使用比您原本需要更多的线程,并具有并行性的潜在优势。它没有实现与适当的异步数据库调用相同的目标(其中不会有 任何 线程绑定(bind)到保存调用 - 只是一个在返回相关网络响应时完成的任务).

如果你真的不关心它是异步的,你可以使用:

public Task CreateAsync(TUser user)
{
_session.Save(user);
return Task.FromResult<object>(null);
}

这将同步保存(就像您当前的代码所做的那样),然后返回一个已完成的任务(而不是根据您当前的代码永远不会完成的任务)。

关于c# - UserManager.CreateAsync(user, password) 陷入无限循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22221457/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com