如何在 asp.net 核心中部署作用域服务之前执行方法?
How to execute method before scoped service is disposed in asp.net core?
我有一个自定义中间件,其目的是订阅 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 方法中使用中间件的方式 class:
options.UseDbContextActivityTracker<ApplicationDbContext>();
在我的 InteractionService 的构造函数中,我通过 DI 获得了对 dbcontext 的引用并订阅了事件:
public InteractionService(TContext context)
{
this.context = context;
this.context.ChangeTracker.StateChanged += ChangeTracker_StateChanged;
}
在请求期间监听 dbContext 发生的事件时,我将相关信息存储到我自己的实体中,并且效果很好。但是,在请求结束时,我想将更改保存到数据库中。我尝试使我的 InteractionService class IDisposable 并在 Dispose 方法中,我正在调用另一个 DbContext 来保存我的实体。正如预期的那样,我得到了错误 "Connection already closed"。
请求完成后将我的实体保存到数据库的正确位置是什么?
@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>();
}
现在可以保存了。 虽然我仍然不确定这是否是正确的方法。如果有人可以告诉我应该如何正确完成此操作,请这样做,我将删除我的答案并将您的答案标记为正确。
我有一个自定义中间件,其目的是订阅 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 方法中使用中间件的方式 class:
options.UseDbContextActivityTracker<ApplicationDbContext>();
在我的 InteractionService 的构造函数中,我通过 DI 获得了对 dbcontext 的引用并订阅了事件:
public InteractionService(TContext context)
{
this.context = context;
this.context.ChangeTracker.StateChanged += ChangeTracker_StateChanged;
}
在请求期间监听 dbContext 发生的事件时,我将相关信息存储到我自己的实体中,并且效果很好。但是,在请求结束时,我想将更改保存到数据库中。我尝试使我的 InteractionService class IDisposable 并在 Dispose 方法中,我正在调用另一个 DbContext 来保存我的实体。正如预期的那样,我得到了错误 "Connection already closed"。 请求完成后将我的实体保存到数据库的正确位置是什么?
@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>();
}
现在可以保存了。 虽然我仍然不确定这是否是正确的方法。如果有人可以告诉我应该如何正确完成此操作,请这样做,我将删除我的答案并将您的答案标记为正确。