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

时间:2019-02-21 10:47:44

标签: c# asp.net-core dbcontext asp.net-core-middleware

我有一个定制的中间件,其目的是订阅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类的Confiure方法中使用中间件的方式:

options.UseDbContextActivityTracker<ApplicationDbContext>();

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

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

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

1 个答案:

答案 0 :(得分: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>();
}

,现在可以保存了。 我仍然不确定这是否是正确的方法。如果有人可以指出如何正确执行此操作,请这样做,我将删除我的答案并将您的答案标记为正确的答案。