在asp-net核心身份中使用与DI模式的异步

时间:2018-06-16 13:33:04

标签: .net dependency-injection core user-management

我在.net核心中的userManager有问题,当我在userManager中调用异步方法后使用DI模式进行用户管理和角色管理时,userManager从内存中处理,我无法访问它?!!

你认为我们不能使用依赖注入的异步方法吗?

public interface IUserService
{
    IEnumerable<UserViewModel> Read();

    Task Update(UserViewModel user);
}

public class UserService : BaseUserService, IUserService
{
    private Microsoft.AspNetCore.Http.ISession _session;
    private readonly UserManager<ApplicationUser> userManager;
    private readonly RoleManager<ApplicationRole> roleManager;
    private ApplicationDbContext _context;

    public UserService(IHttpContextAccessor httpContextAccessor, ApplicationDbContext context, UserManager<Data.ApplicationUser> userManager, RoleManager<ApplicationRole> roleManager)
    {
        _session = httpContextAccessor.HttpContext.Session;
        this.roleManager = roleManager;
        this.userManager = userManager;
        _context = context;
    }

    public async Task Update(UserViewModel user)
    {
        var target = await userManager.FindByIdAsync(user.Id);
        if (target != null)
        {
            target.Name = user.Name;
            target.UserName = user.UserName;
            target.Email = user.Email;

            var result = await userManager.UpdateAsync(target); // in this line  userManager disposed
            if (result.Succeeded)
            {

            }

            await ChangePassword(user);
        }
    }

}

2 个答案:

答案 0 :(得分:0)

  

你认为我们不能使用依赖注入的异步方法吗?

DI和async是互斥的。 DI主要是通过将依赖注入到消费类的构造函数中来实现的。但是,构造函数永远不会是异步的。这迫使对象图的创建也是同步的。此外,在对象构造期间进行任何I / O都是considered to be a bad practice,所以即使你可以,也不应该这样做。

在您使用依赖项的代码中,没有DI正在进行。此时,对象图已经构建了很长时间(使用DI)。这意味着对已创建的类的方法调用可以是异步的。

但是,每当您忘记await操作时,此操作将在后台线程上运行,请求线程将继续其操作。由于I / O操作通常很慢,这可能意味着请求在后台线程继续之前完成。在那个时间点,您的DI容器将处理任何请求范围的服务,这可能会破坏您在后台运行的操作。这很可能是你所看到的问题。

始终await异步操作非常重要,以防止多线程问题和服务从您那里获得处置。

答案 1 :(得分:0)

我使用以下代码解决了这个问题,该代码用于startup.cs中的transient

services.AddTransient<IUserService, UserService>();

我将其更改为作用域:

services.AddScoped<IUserService, UserService>();