【问题标题】:How to send a dbcontext/unit of work to a Hangfire job filter如何将 dbcontext/工作单元发送到 Hangfire 作业过滤器
【发布时间】:2019-04-28 05:47:53
【问题描述】:

我们将 Hangfire 用于一些夜间和长时间运行的作业,并且我们正在单独的数据库中跟踪每个作业的其他相关详细信息/元数据,以避免将来出现 Hangfire 升级问题。 作业过滤器 (https://docs.hangfire.io/en/latest/extensibility/using-job-filters.html) 可以帮助我们更轻松地跟踪每个作业的状态,但我找不到如何将依赖项发送到作业过滤器的示例。

我们正在使用依赖注入 (DI) 和存储库 + 工作单元模式运行 ASP.NET Core。

我如何能够从作业过滤器中访问数据库上下文(或工作单元,或任何其他可通过 DI 获得的项目)?

谢谢

编辑 我创建了一个包含一个小示例项目的存储库,其中概述了我在这里尝试做的事情: https://github.com/joelpereira/hfjobfilter/tree/master/HFJobFilter

它可以编译但行有错误: .UseFilter(new TypeFilterAttribute(typeof(LogToDbAttribute)))

【问题讨论】:

    标签: c# asp.net-core hangfire


    【解决方案1】:

    在我的脑海中,您可以尝试将 JobFilter 添加为 TypeFilter,它会自动注入依赖项(如果有)在您的 LogEverythingAttribute 的构造函数中,因此请修改您提供的链接中的示例:

    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 解决方案不像我最初建议的那样工作。

    【讨论】:

    • 获取编译器错误。 LogToDB 属性类:public class LogToDB : Microsoft.AspNetCore.Mvc.TypeFilterAttribute, IClientFilter, IServerFilter, IElectStateFilter, IApplyStateFilter { 错误在此构造函数行:public LogToDB(IUnitOfWork unitOfWork) { _unitOfWork = unitOfWork; } 错误:没有给定的参数对应于 'TypeFilterAttribute.TypeFilterAttribute(Type)' 的所需形式参数 'type' 感谢您如此迅速地响应。
    • 哦,我想我在那里犯了一个错误。应该是new TypeFilterAttribute(typeof(LogToDB))。也不确定您是否使用GlobalConfiguration 类来配置HangFire 和GlobalJobFilters 来添加过滤器或使用IServicesCollection 上的AddHangfire 扩展方法。看看我编辑的答案,看看是否有效
    • 谢谢沙赫扎德;我现在有一个要编译的示例,但尝试加载过滤器时出现运行时错误。我在这里使用示例代码创建了一个存储库:github.com/joelpereira/hfjobfilter/tree/master/HFJobFilter
    • 好的,让我看看。我会回复你的。我猜你可能需要实现一个自定义 JobActivator。
    • @ssvyper 请查看更新后的答案。我已经对其进行了测试,并且可以正常工作。我希望这会有所帮助
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-05-20
    • 2019-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-01
    • 1970-01-01
    相关资源
    最近更新 更多