我有一个定制的中间件,其目的是订阅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。如预期的那样,我收到错误消息“连接已关闭”。 在请求完成后,将我的实体保存到数据库的正确位置是什么?
答案 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>();
}
,现在可以保存了。 我仍然不确定这是否是正确的方法。如果有人可以指出如何正确执行此操作,请这样做,我将删除我的答案并将您的答案标记为正确的答案。