ASP.NET Core 3.1中如何将Web API数据通过EF Core存入SQL Server数据库
解决思路
你的问题核心是接口返回的DTO类型和EF Core数据库实体类型不匹配,无法直接传入EF的新增方法,只需要完成DTO到数据库实体的字段映射,再调用EF的保存逻辑即可。
实现步骤
1. 修正反序列化类型
你现有拉取代码里JsonConvert.DeserializeObject<Crypto>(result)的泛型类型需要调整为你定义的Root类,才能正确匹配接口返回的JSON结构。
2. 完善数据库实体设计
以下是符合EF Core规范的实体示例,你可以直接复用或根据业务调整:
// 加密货币主实体 public class CryptoCurrency { // 主键可直接用CoinMarketCap返回的币ID,也可以设置为自增主键,单独加CmcId字段存储接口返回的ID public int Id { get; set; } public string Name { get; set; } public string Symbol { get; set; } public string Slug { get; set; } public int NumMarketPairs { get; set; } public DateTime DateAdded { get; set; } // 字符串类型存储标签的JSON序列化结果 public string Tags { get; set; } public long? MaxSupply { get; set; } public double CirculatingSupply { get; set; } public double TotalSupply { get; set; } public int CmcRank { get; set; } public DateTime LastUpdated { get; set; } // 记录本次数据同步时间 public DateTime SyncTime { get; set; } = DateTime.Now; // 导航属性:关联平台信息 public PlatformEntity Platform { get; set; } // 导航属性:关联USD报价 public UsdQuote UsdQuote { get; set; } } // 平台信息实体 public class PlatformEntity { public int Id { get; set; } public int CmcPlatformId { get; set; } public string Name { get; set; } public string Symbol { get; set; } public string Slug { get; set; } public string TokenAddress { get; set; } // 外键关联加密货币 public int CryptoCurrencyId { get; set; } public CryptoCurrency CryptoCurrency { get; set; } } // USD报价实体 public class UsdQuote { public int Id { get; set; } public double Price { get; set; } public double Volume24h { get; set; } public double PercentChange1h { get; set; } public double PercentChange24h { get; set; } public double PercentChange7d { get; set; } public double PercentChange30d { get; set; } public double PercentChange60d { get; set; } public double PercentChange90d { get; set; } public double MarketCap { get; set; } public DateTime LastUpdated { get; set; } // 外键关联加密货币 public int CryptoCurrencyId { get; set; } public CryptoCurrency CryptoCurrency { get; set; } }
修改完实体后重新生成迁移更新数据库即可。
3. 编写DTO到实体的映射逻辑
可以直接手动写映射方法(不需要额外依赖,适合新手),也可以用AutoMapper等映射工具:
public static class DtoToEntityMapper { public static CryptoCurrency MapToCryptoEntity(Datum dto) { var entity = new CryptoCurrency { Id = dto.Id, Name = dto.Name, Symbol = dto.Symbol, Slug = dto.Slug, NumMarketPairs = dto.Num_market_pairs, DateAdded = dto.Date_added, Tags = JsonConvert.SerializeObject(dto.Tags), MaxSupply = dto.Max_supply, CirculatingSupply = dto.Circulating_supply, TotalSupply = dto.Total_supply, CmcRank = dto.Cmc_rank, LastUpdated = dto.Last_updated }; // 映射平台信息 if (dto.Platform != null) { entity.Platform = new PlatformEntity { CmcPlatformId = dto.Platform.Id, Name = dto.Platform.Name, Symbol = dto.Platform.Symbol, Slug = dto.Platform.Slug, TokenAddress = dto.Platform.Token_address }; } // 映射USD报价 if (dto.Quote?.USD != null) { entity.UsdQuote = new UsdQuote { Price = dto.Quote.USD.Price, Volume24h = dto.Quote.USD.Volume_24h, PercentChange1h = dto.Quote.USD.Percent_change_1h, PercentChange24h = dto.Quote.USD.Percent_change_24h, PercentChange7d = dto.Quote.USD.Percent_change_7d, PercentChange30d = dto.Quote.USD.Percent_change_30d, PercentChange60d = dto.Quote.USD.Percent_change_60d, PercentChange90d = dto.Quote.USD.Percent_change_90d, MarketCap = dto.Quote.USD.Market_cap, LastUpdated = dto.Quote.USD.Last_updated }; } return entity; } }
4. 编写保存逻辑
// 1. 拉取接口数据 var cmcClient = new MyClass(); var cmcResult = await cmcClient.GetData(); if (cmcResult?.Data == null || !cmcResult.Data.Any()) { return; } // 2. 批量转换DTO为数据库实体 var entityList = cmcResult.Data.Select(DtoToEntityMapper.MapToCryptoEntity).ToList(); // 3. 批量插入到数据库 await context.CryptoCurrencies.AddRangeAsync(entityList); await context.SaveChangesAsync();
可选优化建议
- 如果需要保留历史报价数据,每次拉取直接新增即可;如果只需要最新数据,可以先根据Cmc的币ID查询库中已有数据,存在则更新、不存在则新增。
- 不要每次请求都新建
HttpClient,建议注入IHttpClientFactory创建实例,避免端口耗尽问题。 - 数据量较大时建议分批插入,不要一次提交上千条数据。
内容的提问来源于stack exchange,提问作者CodingValue
相关产品推荐
相关产品推荐

