如何创建ASP.NET Core Web API项目并实现API数据自动同步至数据库
ASP.NET Core 数据同步项目实现方案与工具选型
核心功能实现步骤
1. 外部API数据获取
用ASP.NET Core内置的HttpClient封装数据获取服务,搭配Polly库处理重试、超时等异常场景,确保数据获取的可靠性:
public class ApiDataFetcher { private readonly HttpClient _httpClient; private readonly IAsyncPolicy<HttpResponseMessage> _retryPolicy; public ApiDataFetcher(HttpClient httpClient) { _httpClient = httpClient; // 配置Polly重试策略:3次重试,间隔指数递增 _retryPolicy = Policy .HandleResult<HttpResponseMessage>(r => !r.IsSuccessStatusCode) .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))); } public async Task<ApiResponseDto> FetchDataAsync() { var response = await _retryPolicy.ExecuteAsync(() => _httpClient.GetAsync("/api/data")); response.EnsureSuccessStatusCode(); return await response.Content.ReadFromJsonAsync<ApiResponseDto>(); } }
在Program.cs中注册服务:
builder.Services.AddHttpClient<ApiDataFetcher>(client => { client.BaseAddress = new Uri("https://external-api-url.com"); client.DefaultRequestHeaders.Add("Accept", "application/json"); }); builder.Services.AddHttpClient(); builder.Services.AddPolly(); // 需安装Polly.Extensions.Http包
2. 数据格式转换
推荐使用AutoMapper简化DTO到数据库实体的映射,减少手动重复代码:
- 安装
AutoMapper.Extensions.Microsoft.DependencyInjection包 - 创建映射配置:
public class MappingProfile : Profile { public MappingProfile() { CreateMap<ApiDataItemDto, DbDataEntity>() .ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.ExternalId)) .ForMember(dest => dest.LastUpdated, opt => opt.MapFrom(src => src.UpdatedAt)); } }
- 注册AutoMapper:
builder.Services.AddAutoMapper(typeof(MappingProfile));
- 执行映射:
var apiData = await _apiDataFetcher.FetchDataAsync(); var dbEntities = _mapper.Map<List<DbDataEntity>>(apiData.Items);
3. 数据持久化到数据库
使用Entity Framework Core作为ORM,实现数据的增删改同步:
- 定义数据库实体:
public class DbDataEntity { public int Id { get; set; } public string Name { get; set; } public DateTime LastUpdated { get; set; } // 其他业务字段 }
- 创建DbContext:
public class AppDbContext : DbContext { public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { } public DbSet<DbDataEntity> DataEntities { get; set; } }
- 同步逻辑(对比更新):
public async Task SyncDataAsync(List<DbDataEntity> newEntities) { var existingEntities = await _dbContext.DataEntities.ToListAsync(); var existingIds = existingEntities.Select(e => e.Id).ToHashSet(); // 新增不存在的数据 var entitiesToAdd = newEntities.Where(e => !existingIds.Contains(e.Id)).ToList(); _dbContext.DataEntities.AddRange(entitiesToAdd); // 更新已存在且有变化的数据 foreach (var newEntity in newEntities.Where(e => existingIds.Contains(e.Id))) { var existing = existingEntities.First(e => e.Id == newEntity.Id); if (existing.LastUpdated < newEntity.LastUpdated) { _dbContext.Entry(existing).CurrentValues.SetValues(newEntity); } } await _dbContext.SaveChangesAsync(); }
自动检测与同步策略
1. 定时轮询方案
适合外部API不支持WebHook的场景,用ASP.NET Core Hosted Service实现后台定时任务:
public class DataSyncHostedService : BackgroundService { private readonly IServiceScopeFactory _scopeFactory; private readonly ILogger<DataSyncHostedService> _logger; private readonly TimeSpan _syncInterval = TimeSpan.FromMinutes(30); // 30分钟同步一次 public DataSyncHostedService(IServiceScopeFactory scopeFactory, ILogger<DataSyncHostedService> logger) { _scopeFactory = scopeFactory; _logger = logger; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { _logger.LogInformation("Data sync service started"); while (!stoppingToken.IsCancellationRequested) { try { using var scope = _scopeFactory.CreateScope(); var apiFetcher = scope.ServiceProvider.GetRequiredService<ApiDataFetcher>(); var mapper = scope.ServiceProvider.GetRequiredService<IMapper>(); var syncService = scope.ServiceProvider.GetRequiredService<DataSyncService>(); var apiData = await apiFetcher.FetchDataAsync(); var dbEntities = mapper.Map<List<DbDataEntity>>(apiData.Items); await syncService.SyncDataAsync(dbEntities); _logger.LogInformation("Data sync completed successfully"); } catch (Exception ex) { _logger.LogError(ex, "Data sync failed"); } await Task.Delay(_syncInterval, stoppingToken); } _logger.LogInformation("Data sync service stopped"); } }
注册服务:
builder.Services.AddHostedService<DataSyncHostedService>();
如果需要可视化管理定时任务,可改用Hangfire,支持CRON表达式、任务监控等功能。
2. WebHook主动通知方案
如果外部API支持WebHook,当数据更新时主动调用你的服务接口,触发同步:
- 编写WebHook接收接口:
[ApiController] [Route("webhooks")] public class WebHookController : ControllerBase { private readonly IServiceScopeFactory _scopeFactory; private readonly ILogger<WebHookController> _logger; public WebHookController(IServiceScopeFactory scopeFactory, ILogger<WebHookController> logger) { _scopeFactory = scopeFactory; _logger = logger; } [HttpPost("data-updated")] public async Task<IActionResult> DataUpdated([FromBody] WebHookNotification notification) { try { // 验证WebHook签名(根据外部API要求实现) if (!ValidateSignature(Request.Headers["X-Signature"], notification)) { return Unauthorized(); } using var scope = _scopeFactory.CreateScope(); var syncService = scope.ServiceProvider.GetRequiredService<DataSyncService>(); await syncService.FetchAndSyncDataAsync(); // 调用完整同步逻辑 _logger.LogInformation("WebHook triggered data sync completed"); return Ok(); } catch (Exception ex) { _logger.LogError(ex, "WebHook data sync failed"); return StatusCode(500); } } private bool ValidateSignature(string signatureHeader, WebHookNotification notification) { // 实现签名验证逻辑,比如用HMAC加密对比 return true; } }
此方案更高效,无需定时轮询,适合实时性要求高的场景。
工具选型总结
- 数据获取:
HttpClient(内置)+ Polly(处理重试、熔断) - 数据转换:AutoMapper(简化映射)或手动编写映射类(轻量场景)
- 数据持久化:Entity Framework Core(主流ORM,支持SQL Server、MySQL等多种数据库)
- 任务调度:
- 轻量场景:ASP.NET Core Hosted Service
- 需可视化管理:Hangfire
- 日志:Serilog/NLog(记录同步过程,便于排查问题)
内容的提问来源于stack exchange,提问作者Mustafa Baş
相关产品推荐
相关产品推荐

