在asp.net核心中处理作用域服务之前如何执行方法?

问题描述 投票:0回答:1

我有一个自定义中间件,其目的是订阅EF Core dbcontext事件并跟踪实体发生的更改。中间件在每个请求开始时将我的InteractionService实例化为范围实例。这就是我的中间件的样子:

public static IApplicationBuilder UseDbContextActivityTracker<TContext>(this IApplicationBuilder app)
    where TContext : DbContext
{
    app.Use(async (context, next) =>
    {
        var service = context.RequestServices.GetRequiredService<InteractionService<TContext>>();
        await next.Invoke();
        service.PersistLogs();
    });

    return app;
}

这就是我在Startup类的Configure方法中使用中间件的方法:

options.UseDbContextActivityTracker<ApplicationDbContext>();

在我的InteractionService的构造函数中,我通过DI得到了dbcontext的引用,我订阅了这些事件:

public InteractionService(TContext context)
{
    this.context = context;
    this.context.ChangeTracker.StateChanged += ChangeTracker_StateChanged;
}

在请求期间收听dbContext发生的事件时,我将相关信息存储到我自己的实体中,并且效果很好。但是,在请求结束时,我想保存对数据库的更改。我尝试使我的InteractionService类IDisposable,并在Dispose方法中,我调用另一个DbContext,我在其中保存我的实体。正如所料,我收到错误“连接已关闭”。请求完成后,将实体保存到数据库的正确位置是什么?

c# asp.net-core dbcontext asp.net-core-middleware
1个回答
0
投票

@Panagiotis Kanavos向我指出了正确的方向。我的问题是如何获得一个适当的作用域DbContext来编写更改。在我的InteractionService中,而不是通过构造函数注入DbContext,我使用serviceProvider手动创建它。我改变了这个:

public CampusAxessInteractionStore(MyDbContext context)
{
    this.context = context;
}

对此:

public CampusAxessInteractionStore(IServiceProvider serviceProvider)
{
    var scopeResolver = serviceProvider.GetRequiredService<IServiceScopeFactory>().CreateScope();
    this.context = scopeResolver.ServiceProvider.GetRequiredService<CampusAxessDbContext>();
}

现在节约工作。我仍然不确定这是否是正确的方法。如果有人可以指出我应该如何正确完成这一点,我会删除我的答案,并将你的答案标记为正确。

© www.soinside.com 2019 - 2024. All rights reserved.