如何解决Autofac 在 MediatR 处理程序完成工作之前处理我的 DbContext
我有一个 MediatR 通知处理程序。当用户发出请求时会调用此通知,因此我想在后台处理该事件。从 MediatR wiki 中,我采用了一个类来并行调用处理程序,而无需等待它们的完成。见here。
需要延迟一秒钟才能完成请求并演示我的问题。没有延迟,它随机发生。
存储库是通过注入传输的,一切都很好。但是来自 EFCore 的 DbContext 在用户请求完成后被标记为已处理。因此,无法保存结果。
我只想在后台完成这项工作。
Mediator 和 Repository 的代码注入:
builder.RegisterGeneric(typeof(EfRepository<>))
.As(typeof(IRepository<>))
.As(typeof(IReadRepository<>))
.InstancePerLifetimeScope();
builder
.RegisterType<CustomMediator>()
.As<IMediator>()
.InstancePerLifetimeScope();
builder.Register<ServiceFactory>(context =>
{
var c = context.Resolve<IComponentContext>();
return t => c.Resolve(t);
});
var mediatrOpenTypes = new[]
{
typeof(IRequestHandler<,>),typeof(IRequestExceptionHandler<,typeof(IRequestExceptionAction<,typeof(INotificationHandler<>),};
foreach (var mediatrOpenType in mediatrOpenTypes)
{
builder
.RegisterassemblyTypes(_assemblies.ToArray())
.AsClosedTypesOf(mediatrOpenType)
.AsImplementedInterfaces();
}
DbContext 的代码注入:
public static void AddDbContext(this IServiceCollection services,string connectionString) =>
services.AddDbContext<AppDbContext>(options =>
options.Usesqlite(connectionString)); // will be created in web project root
来自我的 CustomMediator 的方法 PublishCore 的代码:
protected override Task PublishCore(IEnumerable<Func<INotification,CancellationToken,Task>> allHandlers,INotification notification,CancellationToken cancellationToken)
{
foreach (var handler in allHandlers)
{
_ = Task.Run(() => handler(notification,cancellationToken));
}
return Task.CompletedTask;
}
来自我的 INotificationHandler 的方法代码
public async Task Handle(NewCaptchaAddedEvent domainEvent,CancellationToken cancellationToken)
{
Guard.Against.Null(domainEvent,nameof(domainEvent));
var captcha = domainEvent.Captcha;
await Task.Delay(1000);
var solution = await _vkCaptchaSolver.solveCaptcha(captcha.CaptchaUri);
captcha.MarkSolved(solution);
await _repository.UpdateAsync(captcha);
return;
}
更新 1 我找到了这种行为的原因。重点是在LifetimeScope中,MediatR在创建时使用当前的,这是web请求的范围,所以所有的子节点都被销毁了。我做了一个小黑客。它很脏。当中介想要接收服务时,只需在根作用域中创建一个新作用域:
builder.Register<ServiceFactory>(context =>
{
var c = context.Resolve<ILifetimeScope>();
var newl = (c as LifetimeScope).RootLifetimeScope.BeginLifetimeScope();
return t => newl.Resolve(t);
});
但这只是一个临时解决方案,问题仍然存在,如何正确创建范围或不将其销毁?
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。