DBContext更改后如何在控制器内创建新的UserManager对象

Posted

技术标签:

【中文标题】DBContext更改后如何在控制器内创建新的UserManager对象【英文标题】:How to create new UserManager object inside controller after DBContext changed 【发布时间】:2021-04-04 23:29:12 【问题描述】:

在我的DbContext 更改为Controller 内的新connectionString 后,我希望有一个刷新的UserManager 对象,我在Controller 中注入了UserManager,但很明显它将始终具有来自DI 的最后一个DbContext 引用,而不是新创建的dbcontext

我已经尝试如下。

this.DbContext = new ApplicationDbContext(Configuration, optionsBuilder.Options);
this._userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(DbContext), null, new PasswordHasher<ApplicationUser>(), null, null, null, null, null, null);

它运行良好,但缺少大部分 UserManager 功能,例如 _userManager.CheckPasswordAsync(user, loginModel.Password) 因为我将大部分参数作为空值传递。 我应该怎么做才能以最简单的方式让 UserManger 和新的 DbContext 完全正常工作?

【问题讨论】:

只是好奇你为什么要做这样的事情? 【参考方案1】:

使用依赖注入,这就是所有提到的工具的使用方式。

private DbContext DbContext  get;

private UserManager<IdentityUser> UserManager  get;  

public MyController(DbContext dbContext, UserManager<IdentityUser> userManager)

    DbContext = dbContext;
    UserManager = userManager;

https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-5.0

这是一个关于如何为 EF Core 设置依赖注入的页面:

https://docs.microsoft.com/en-us/ef/core/dbcontext-configuration/#dbcontext-in-dependency-injection-for-aspnet-core

假设您已经拥有services.AddDefaultIdentity(...)services.AddDbContext(...),注入UserManagerYourProjectDbContext 本来就应该在您的控制器中工作。

【讨论】:

【参考方案2】:

您可以尝试创建服务并在服务中使用 UserManger,然后使用 Startup.ConfigureServices 方法中的 Transient 操作配置服务。瞬态操作总是不同的,每次检索服务都会创建一个新实例。然后,您可以在控制器中使用此服务。请检查以下步骤:

创建一个 UserManagerRepository 服务(在此服务中您可以创建方法并使用 UserManager 方法):

public interface IUserManagerRepository

    void Write(string message);

public class UserManagerRepository : IUserManagerRepository, IDisposable

    private bool _disposed;
    private readonly UserManager<IdentityUser> _userManager;

    public UserManagerRepository(UserManager<IdentityUser> userManager)
    
        _userManager = userManager;
    

    public void Write(string message)
    
        // _userManager.ChangePasswordAsync()
        Console.WriteLine($"UserManagerRepository: message");
    

    public void Dispose()
    
        if (_disposed)
            return;

        Console.WriteLine("UserManagerRepository.Dispose");
        _disposed = true;
    

在 Startup.ConfigureServices 方法中使用以下代码配置服务:

 services.AddTransient<IUserManagerRepository, UserManagerRepository>();

之后,在控制器动作方法中手动调用服务。

    public IActionResult Index()
    
        var services = this.HttpContext.RequestServices;
        var log = (IUserManagerRepository)services.GetService(typeof(IUserManagerRepository));

        log.Write("Index method executing");
         
        var log2 = (IUserManagerRepository)services.GetService(typeof(IUserManagerRepository));

        log2.Write("Index method executing");
        var log3 = (IUserManagerRepository)services.GetService(typeof(IUserManagerRepository));

        log3.Write("Index method executing"); 
        return View();
    

截图如下:

参考:

Tutorial: Use dependency injection in .NET

Dependency injection guidelines

Dependency injection in ASP.NET Core

【讨论】:

所以在再次调用该服务后,userManager 将使用新创建的 AppDbContext 进行初始化? _userManager 仍然持有对旧 dbContext 的引用,新 dbContext 具有不同的连接字符串 @SabirHossain 当然,因为代码注入了身份模型提供的UserManager&lt;IdentityUser&gt;,这仍然取决于配置的DbContext(在您的应用程序启动中)。这个答案绝对不是你想要的。 我知道,@Hopeless 我该怎么做才能用新创建的 DbContext 刷新 UserManger,你可以看到我是如何做到的,但我需要一个功能齐全的 UserManager

以上是关于DBContext更改后如何在控制器内创建新的UserManager对象的主要内容,如果未能解决你的问题,请参考以下文章

我啥时候应该创建一个新的 DbContext()

如何更新在 DbContext 之外修改的实体?

使用DBContext ChangeTracker编写基于事件的SignalR Notification Service - 关注点分离

备份恢复

当dbcontext中有多个模型时,如何创建一个空模型以传递给插入更新视图?

如何更改 DbContext.SaveChanges() 的条目值