如何将 dbcontext/unit 的工作发送到 Hangfire 工作过滤器
How to send a dbcontext/unit of work to a Hangfire job filter
我们正在将 Hangfire 用于一些夜间和长时间的 运行 作业,并且我们正在单独的数据库中为每个作业跟踪额外的相关 details/metadata 以避免将来出现 Hangfire 升级问题。
工作过滤器 (https://docs.hangfire.io/en/latest/extensibility/using-job-filters.html) 可以帮助我们更轻松地跟踪每个工作的状态,但我找不到如何将依赖项发送到工作过滤器的示例。
我们 运行 ASP.NET 具有依赖注入 (DI) 和存储库 + 工作单元模式的核心。
我如何才能从工作过滤器中访问数据库上下文(或工作单元,或任何其他可通过 DI 获得的项目)?
谢谢
编辑
我创建了一个存储库,其中包含一个小示例项目,概述了我在这里尝试做的事情:
https://github.com/joelpereira/hfjobfilter/tree/master/HFJobFilter
编译通过了,但是有一行错误:
.UseFilter(new TypeFilterAttribute(typeof(LogToDbAttribute)))
根据我的想法,您可以尝试将 JobFilter 添加为 TypeFilter,它会自动注入依赖项(如果在 LogEverythingAttribute
的构造函数中有依赖项),因此修改示例来自您提供的link:
public class EmailService
{
[TypeFilter(typeof(LogEverything))]
public static void Send() { }
}
GlobalJobFilters.Filters.Add(new TypeFilterAttribute(typeof(LogEverythingAttribute())));
免责声明:我自己还没有测试过以上内容,所以请告诉我是否可行。
已编辑
尝试在 ConfigureServices
中像下面那样配置 Hangfire,看看是否可行
services.AddHangfire(config =>
{
config.UseFilter(new TypeFilterAttribute(typeof(LogToDbAttribute)));
// if you are using the sqlserverstorage, uncomment the line and provie
// the required prameters
// config.UseSqlServerStorage(connectionString, sqlServerStorageOptions);
});
更新的答案
请看一下我对您提供的代码所做的changes。我已经对其进行了测试并且可以正常工作。以下几点需要注意。
请查看我是如何使用利用 HttpClientFactory 和类型化客户端的 AddHttpClient 方法注册 HttpClient 的。这是使用 HttpClient 的推荐方式。您可以阅读更多相关信息 here
services.AddHttpClient<HfHttpClient>(client =>
{
client.BaseAddress = new Uri("http://localhost:44303");
// you can set other options for HttpClient as well, such as
//client.DefaultRequestHeaders;
//client.Timeout
//...
});
此外,您需要注册 LogDbAttribute
,然后在 UseFilter 调用中解析它,使用 IServiceProvider
// register the LogToDbAttribute
services.AddSingleton<LogToDbAttribute>();
// build the service provider to inject the dependencies in LogDbAttribute
var serviceProvider = services.BuildServiceProvider();
services.AddHangfire(config => config
.UseSqlServerStorage(Configuration.GetConnectionString("HangfireDBConnection"))
.UseFilter(serviceProvider.GetRequiredService<LogToDbAttribute>()));
我还注入了 ILogger 以证明它可以正常工作。出于某种原因,如果您尝试对 HttpClient 执行任何操作,它就会挂起。也许,原因是它是一个后台作业,所有 HttpClient 调用都是异步的,所以它不会返回,两个进程试图互相等待。
如果您打算注入 HttpClient,您可能需要调查一下。但是,记录器工作正常。
另外,您不需要从 TypeFilterAttribute 继承 LogDbAttribute。 TypeFilterAttribute 解决方案并不像我最初建议的那样工作。
我们正在将 Hangfire 用于一些夜间和长时间的 运行 作业,并且我们正在单独的数据库中为每个作业跟踪额外的相关 details/metadata 以避免将来出现 Hangfire 升级问题。 工作过滤器 (https://docs.hangfire.io/en/latest/extensibility/using-job-filters.html) 可以帮助我们更轻松地跟踪每个工作的状态,但我找不到如何将依赖项发送到工作过滤器的示例。
我们 运行 ASP.NET 具有依赖注入 (DI) 和存储库 + 工作单元模式的核心。
我如何才能从工作过滤器中访问数据库上下文(或工作单元,或任何其他可通过 DI 获得的项目)?
谢谢
编辑 我创建了一个存储库,其中包含一个小示例项目,概述了我在这里尝试做的事情: https://github.com/joelpereira/hfjobfilter/tree/master/HFJobFilter
编译通过了,但是有一行错误: .UseFilter(new TypeFilterAttribute(typeof(LogToDbAttribute)))
根据我的想法,您可以尝试将 JobFilter 添加为 TypeFilter,它会自动注入依赖项(如果在 LogEverythingAttribute
的构造函数中有依赖项),因此修改示例来自您提供的link:
public class EmailService
{
[TypeFilter(typeof(LogEverything))]
public static void Send() { }
}
GlobalJobFilters.Filters.Add(new TypeFilterAttribute(typeof(LogEverythingAttribute())));
免责声明:我自己还没有测试过以上内容,所以请告诉我是否可行。
已编辑
尝试在 ConfigureServices
中像下面那样配置 Hangfire,看看是否可行
services.AddHangfire(config =>
{
config.UseFilter(new TypeFilterAttribute(typeof(LogToDbAttribute)));
// if you are using the sqlserverstorage, uncomment the line and provie
// the required prameters
// config.UseSqlServerStorage(connectionString, sqlServerStorageOptions);
});
更新的答案
请看一下我对您提供的代码所做的changes。我已经对其进行了测试并且可以正常工作。以下几点需要注意。
请查看我是如何使用利用 HttpClientFactory 和类型化客户端的 AddHttpClient 方法注册 HttpClient 的。这是使用 HttpClient 的推荐方式。您可以阅读更多相关信息 here
services.AddHttpClient<HfHttpClient>(client =>
{
client.BaseAddress = new Uri("http://localhost:44303");
// you can set other options for HttpClient as well, such as
//client.DefaultRequestHeaders;
//client.Timeout
//...
});
此外,您需要注册 LogDbAttribute
,然后在 UseFilter 调用中解析它,使用 IServiceProvider
// register the LogToDbAttribute
services.AddSingleton<LogToDbAttribute>();
// build the service provider to inject the dependencies in LogDbAttribute
var serviceProvider = services.BuildServiceProvider();
services.AddHangfire(config => config
.UseSqlServerStorage(Configuration.GetConnectionString("HangfireDBConnection"))
.UseFilter(serviceProvider.GetRequiredService<LogToDbAttribute>()));
我还注入了 ILogger 以证明它可以正常工作。出于某种原因,如果您尝试对 HttpClient 执行任何操作,它就会挂起。也许,原因是它是一个后台作业,所有 HttpClient 调用都是异步的,所以它不会返回,两个进程试图互相等待。
如果您打算注入 HttpClient,您可能需要调查一下。但是,记录器工作正常。
另外,您不需要从 TypeFilterAttribute 继承 LogDbAttribute。 TypeFilterAttribute 解决方案并不像我最初建议的那样工作。