You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET Core WebAPI启动执行Excel导入及每周定时任务问题

.NET Core WebAPI Excel导入SQLite:启动执行与定时任务解决方案

1. 启动时调用Excel导入方法

有两种规范的实现方式:

方式一:Program.cs中手动触发(简单直接)

在Host构建完成后,创建服务作用域并调用业务方法:

var builder = WebApplication.CreateBuilder(args);
// 确保接口与实现已正确注册
builder.Services.AddScoped<IDataSourceService, DqcDataService>();

// 其他服务、中间件注册逻辑...

var app = builder.Build();

// 启动时执行Excel导入
using (var scope = app.Services.CreateScope())
{
    var dataSourceService = scope.ServiceProvider.GetRequiredService<IDataSourceService>();
    await dataSourceService.ReadFromExcelAsync();
}

// 启动WebAPI
app.Run();

方式二:使用IHostedService(符合托管服务规范)

创建专门的启动任务服务:

public class StartupImportService : IHostedService
{
    private readonly IServiceProvider _serviceProvider;

    public StartupImportService(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    public async Task StartAsync(CancellationToken cancellationToken)
    {
        using (var scope = _serviceProvider.CreateScope())
        {
            var dataSourceService = scope.ServiceProvider.GetRequiredService<IDataSourceService>();
            await dataSourceService.ReadFromExcelAsync();
        }
    }

    public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
}

然后在Program.cs中注册该托管服务:

builder.Services.AddHostedService<StartupImportService>();

2. 服务无法解析的原因与正确注册方式

直接注册DqcDataService虽能临时解决问题,但会丢失依赖注入的解耦优势。之前解析失败通常是以下原因:

  • 时机错误:在builder.Build()完成前就尝试解析服务(此时服务容器尚未初始化完成)
  • 生命周期不匹配:若DqcDataService依赖Scoped/Transient类型服务,直接通过根服务提供者获取会报错(根提供者仅支持解析Singleton服务)
  • 注册遗漏:未添加builder.Services.AddScoped<IDataSourceService, DqcDataService>()或存在拼写错误

正确做法是保留接口与实现的注册,在需要调用时通过服务作用域获取(如问题1中的两种方式),而非直接注册具体类。

3. 定时任务的正确实现(避免重复代码)

托管服务默认是Singleton生命周期,不能直接注入Scoped类型的IDataSourceService,需在任务执行时动态创建服务作用域。以下是每周定时任务的示例:

实现定时托管服务

public class WeeklyImportService : IHostedService, IDisposable
{
    private readonly IServiceProvider _serviceProvider;
    private Timer _timer;

    public WeeklyImportService(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    public Task StartAsync(CancellationToken cancellationToken)
    {
        // 设置每周日凌晨2点执行(可根据需求调整时间)
        var now = DateTime.Now;
        var nextRun = now.AddDays((7 - now.DayOfWeek + DayOfWeek.Sunday) % 7).Date.AddHours(2);
        if (nextRun <= now) nextRun = nextRun.AddDays(7);
        var initialDelay = nextRun - now;

        // 初始化定时器,每周执行一次
        _timer = new Timer(ExecuteImport, null, initialDelay, TimeSpan.FromDays(7));
        return Task.CompletedTask;
    }

    private async void ExecuteImport(object state)
    {
        using (var scope = _serviceProvider.CreateScope())
        {
            var dataSourceService = scope.ServiceProvider.GetRequiredService<IDataSourceService>();
            await dataSourceService.ReadFromExcelAsync();
        }
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        _timer?.Change(Timeout.Infinite, 0);
        return Task.CompletedTask;
    }

    public void Dispose()
    {
        _timer?.Dispose();
    }
}

注册定时服务

在Program.cs中添加:

builder.Services.AddHostedService<WeeklyImportService>();

如果使用第三方定时任务库(如Quartz),核心逻辑一致:在任务执行方法内创建服务作用域,获取IDataSourceService并调用已有方法,完全复用业务代码,无需重复编写。

内容的提问来源于stack exchange,提问作者AoLiGei

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 19:33:35