如何将Worker Service集成到abp.io解决方案(拟为Windows Service)并复用Domain数据访问?
没问题,我来一步步带你完成Worker Service和ABP.io解决方案的集成,确保你能用上Domain层的数据库能力,最后还能顺利部署成Windows Service。
首先在你的ABP解决方案里新增一个Worker Service项目,命名建议和现有项目保持一致的前缀,比如YourSolutionName.WorkerService。你可以用两种方式创建:
- 用Visual Studio的「新建项目」向导,选择「Worker Service」模板;
- 或者用dotnet命令行快速创建:
dotnet new worker -n YourSolutionName.WorkerService
创建完成后,把这个项目添加到你的ABP解决方案里,方便统一管理。
这一步是核心,要让Worker Service能使用ABP的模块系统、依赖注入和Domain层的能力:
安装必要的NuGet包
在Worker Service项目里安装ABP核心包、对应的数据库集成包(比如EF Core),还要引用你的Domain层和数据库上下文项目:
dotnet add package Volo.Abp.Core dotnet add package Volo.Abp.EntityFrameworkCore # 如果用MongoDB,替换成Volo.Abp.MongoDB dotnet add reference ../YourSolutionName.Domain/YourSolutionName.Domain.csproj dotnet add reference ../YourSolutionName.EntityFrameworkCore/YourSolutionName.EntityFrameworkCore.csproj
创建ABP模块类
新建一个继承自AbpModule的类,比如WorkerServiceModule,并声明依赖你的Domain模块和数据库模块:
[DependsOn( typeof(YourSolutionNameDomainModule), typeof(YourSolutionNameEntityFrameworkCoreModule) )] public class WorkerServiceModule : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) { var configuration = context.Services.GetConfiguration(); // 配置数据库连接,和其他ABP项目保持一致 Configure<AbpDbContextOptions>(options => { options.UseSqlServer(configuration.GetConnectionString("Default")); }); } }
修改Program.cs初始化ABP
把Worker的启动逻辑改成ABP应用的初始化方式,同时加上Windows Service支持:
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using YourSolutionName.WorkerService; var host = Host.CreateDefaultBuilder(args) .UseWindowsService() // 开启Windows Service部署支持 .ConfigureServices((hostContext, services) => { // 初始化ABP应用模块 services.AddApplication<WorkerServiceModule>(); // 注册Worker服务 services.AddHostedService<Worker>(); }) .Build(); // 初始化ABP应用(必须加这一步,否则ABP的依赖注入和模块不会生效) await host.InitializeApplicationAsync(); await host.RunAsync();
现在你可以在Worker类里注入Domain层的仓储或服务了,不过要注意生命周期问题:ABP的仓储默认是作用域(Scoped)或瞬态(Transient),而Worker是单例的,所以需要用IServiceScopeFactory创建作用域来获取服务:
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using YourSolutionName.Domain.Repositories; public class Worker : BackgroundService { private readonly ILogger<Worker> _logger; private readonly IServiceScopeFactory _serviceScopeFactory; public Worker(ILogger<Worker> logger, IServiceScopeFactory serviceScopeFactory) { _logger = logger; _serviceScopeFactory = serviceScopeFactory; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { _logger.LogInformation("Worker执行任务中,当前时间: {time}", DateTimeOffset.Now); // 创建作用域,获取Domain层的仓储 using (var scope = _serviceScopeFactory.CreateScope()) { var yourEntityRepository = scope.ServiceProvider.GetRequiredService<IYourEntityRepository>(); // 调用仓储方法操作数据库 var dataList = await yourEntityRepository.GetListAsync(); _logger.LogInformation("从数据库读取到{count}条数据", dataList.Count); } await Task.Delay(10000, stoppingToken); // 每隔10秒执行一次,可根据需求调整 } } }
把Worker项目的appsettings.json配置好,和你的其他ABP项目保持完全一致的连接字符串:
{ "ConnectionStrings": { "Default": "Server=(localdb)\\mssqllocaldb;Database=YourSolutionName;Trusted_Connection=True;MultipleActiveResultSets=true" }, "Logging": { "LogLevel": { "Default": "Information", "Microsoft.Hosting.Lifetime": "Information" } } }
开发测试完成后,就可以部署成Windows Service了:
发布项目
先把Worker Service发布成可执行文件:
dotnet publish -c Release -o D:\YourSolution\WorkerPublish
安装服务
用Windows的sc命令安装(需要管理员权限打开命令提示符):
sc create "YourSolutionWorkerService" binPath="D:\YourSolution\WorkerPublish\YourSolutionName.WorkerService.exe" DisplayName="你的解决方案Worker服务"
启动/停止服务
启动服务:
sc start "YourSolutionWorkerService"
停止服务:
sc stop "YourSolutionWorkerService"
如果需要卸载服务:
sc delete "YourSolutionWorkerService"
- 确保Worker Service的目标框架和你的ABP其他项目一致,避免版本兼容问题;
- 如果用的是非EF Core的数据库(比如MongoDB),替换对应的ABP数据库包,模块里的配置也要改成对应数据库的配置;
- 日志可以集成ABP的日志系统,或者保持默认的Microsoft Logging,根据你的需求调整;
- 可以在ABP模块里配置其他ABP功能,比如权限、本地化等,只要你的Worker需要用到。
内容的提问来源于stack exchange,提问作者nymeron

