在ASP.NET 5中访问中间件中的DbContext

Jan*_*nen 13 c# entity-framework asp.net-core-mvc asp.net-core

我写了我添加的自定义中间件

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    //...
    app.UseAutologin();
    app.UseMvc(routes =>
    {
       //...
Run Code Online (Sandbox Code Playgroud)

所以它是Mvc发挥作用之前的最后一个中间件.

在我的中间件Invoke方法中,我想(间接)访问DbContext.

 public async Task Invoke(HttpContext context)
  {
     if (string.IsNullOrEmpty(context.User.Identity.Name))
     {
        var applicationContext = _serviceProvider.GetService<ApplicationDbContext>();
        var signInManager = _serviceProvider.GetService<SignInManager<ApplicationUser>>();
        var result = await signInManager.PasswordSignInAsync(_options.UserName, _options.Password, true, false);
     }

     await _next(context);
  }
Run Code Online (Sandbox Code Playgroud)

几乎每次我得到以下异常:

InvalidOperationException:尝试在配置上下文时使用上下文.甲DbContext实例不能被内部使用OnConfiguring,因为它仍然在此时配置.

现在这个方法明显提出了这个问题PasswordSignInAsync.但是,如何确保在执行此类操作之前创建模型?

也许我并不完全清楚:我不想使用DbContext自己 - PasswordSignInAsync在验证用户和密码时使用它.

Hen*_*ema 7

如果您注入ApplicationDbContextSignInManager<ApplicationUser>通过该Invoke方法,该怎么办:

public async Task Invoke(HttpContext context, ApplicationDbContext applicationContext, SignInManager<ApplicationUser> signInManager)
{
    if (string.IsNullOrEmpty(context.User.Identity.Name))
    {
        var result = await signInManager.PasswordSignInAsync(_options.UserName, _options.Password, true, false);
    }

    await _next(context);
}
Run Code Online (Sandbox Code Playgroud)

这样您就可以从正确的范围中解析服务.我注意到你实际上并没有使用ApplicationDbContext任何地方,只是SignInManager.你真的需要它吗?


mic*_*elb 5

这个错误很可能发生,因为任何中间件都充当单例。您必须避免在中间件中使用成员变量。随意注入到任务调用中,但不要将注入值存储到成员对象中。

参见:在中间件中保存 HttpContext 实例,在中间件调用服务

我自己解决了这个问题,方法是创建一个类,然后我可以将其传递给中间件中的其他方法:

    public async Task Invoke(HttpContext context, IMetaService metaService)
    {
            var middler = new Middler
            {
                Context = context,
                MetaService = metaService
            };

            DoSomething(middler);
    }
Run Code Online (Sandbox Code Playgroud)


小智 5

就凭这个:-

public async Task Invoke(HttpContext context)
{
    var dbContext = context.RequestServices.GetRequiredService<ClinicDbContext>();

    await _next(context);
}
Run Code Online (Sandbox Code Playgroud)