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

C# ASP.NET Entity Framework从API提取数组数据并保存的方法

嘿,我来帮你一步步搞定从API提取数据并保存到EF的事儿!结合你已经有Shift类和请求代码的情况,咱们可以这么做:

步骤1:定义API响应模型(确保反序列化正确)

首先得确保你有对应API返回结构的模型类,用来把JSON数据反序列化成C#对象。假设API返回的JSON结构大概是这样:

{
  "date": "2024-05-20",
  "shifts": [
    { "id": 1, "name": "早班", "startTime": "08:00", "endTime": "16:00", "employeeCount": 5 },
    { "id": 2, "name": "晚班", "startTime": "16:00", "endTime": "24:00", "employeeCount": 3 }
  ],
  "costs": [
    { "id": 1, "category": "人力", "amount": 1500.00, "shiftId": 1 },
    { "id": 2, "category": "物料", "amount": 800.00, "shiftId": 1 }
  ]
}

那对应的C#模型可以这么写(如果你的Shift实体和API返回的结构有差异,建议单独定义DTO来隔离API层和数据层):

// 整个API的响应模型
public class ApiResponse
{
    public DateTime Date { get; set; }
    public List<ShiftApiDto> Shifts { get; set; }
    public List<CostApiDto> Costs { get; set; }
}

// API返回的Shift数据结构(和你的EF Shift实体区分开)
public class ShiftApiDto
{
    public int Id { get; set; }
    public string Name { get; set; }
    public TimeOnly StartTime { get; set; }
    public TimeOnly EndTime { get; set; }
    // 其他API返回的字段,按需保留
}

// API返回的Cost数据结构
public class CostApiDto
{
    public int Id { get; set; }
    public string Category { get; set; }
    public decimal Amount { get; set; }
    public int ShiftId { get; set; }
}
步骤2:发起API请求并反序列化

用HttpClient发起请求,把返回的JSON反序列化成上面定义的ApiResponse对象:

// 假设这是你的服务类,通过依赖注入拿到HttpClient和EF上下文
public class DataFetchService
{
    private readonly HttpClient _httpClient;
    private readonly YourDbContext _dbContext;

    public DataFetchService(HttpClient httpClient, YourDbContext dbContext)
    {
        _httpClient = httpClient;
        _dbContext = dbContext;
    }

    public async Task FetchAndProcessDataAsync()
    {
        // 替换成你的API地址
        var apiResponse = await _httpClient.GetFromJsonAsync<ApiResponse>("https://your-api-endpoint.com/data");
        if (apiResponse == null)
        {
            throw new InvalidOperationException("API返回的数据为空,请检查请求地址或API状态");
        }

        // 下一步:提取并映射数据到EF实体
        await MapAndSaveDataAsync(apiResponse);
    }
}
步骤3:提取并映射数据到EF实体

现在从ApiResponse里提取你需要的字段,映射到EF的实体类(包括你已定义的Shift,如果还没Cost实体可以补充一个):

// 假设你的EF Shift实体已经定义,补充Cost实体(如果需要)
public class Cost
{
    public int Id { get; set; }
    public string Category { get; set; }
    public decimal Amount { get; set; }
    public int ShiftId { get; set; }
    public Shift Shift { get; set; } // 关联Shift实体
}

private async Task MapAndSaveDataAsync(ApiResponse apiResponse)
{
    var shiftsToSave = new List<Shift>();

    foreach (var shiftDto in apiResponse.Shifts)
    {
        // 提取Shift中需要的字段,创建EF Shift实体
        var shift = new Shift
        {
            Id = shiftDto.Id,
            Name = shiftDto.Name,
            StartTime = shiftDto.StartTime,
            EndTime = shiftDto.EndTime,
            Date = apiResponse.Date // 把API返回的日期关联到Shift
        };

        // 提取当前Shift对应的Costs数据,过滤并映射到Cost实体
        var relatedCosts = apiResponse.Costs
            .Where(costDto => costDto.ShiftId == shiftDto.Id)
            .Select(costDto => new Cost
            {
                Id = costDto.Id,
                Category = costDto.Category,
                Amount = costDto.Amount,
                ShiftId = shift.Id
            })
            .ToList();

        shift.Costs = relatedCosts;
        shiftsToSave.Add(shift);
    }

    // 第四步:保存到数据库
    await SaveToDatabaseAsync(shiftsToSave);
}
步骤4:保存数据到数据库

最后把映射好的实体保存到EF上下文:

private async Task SaveToDatabaseAsync(List<Shift> shifts)
{
    // 这里可以根据需求选择新增或更新:
    // 如果是全新数据,用AddRange;如果需要更新已有数据,先查询再判断
    foreach (var shift in shifts)
    {
        var existingShift = await _dbContext.Shifts.FindAsync(shift.Id);
        if (existingShift == null)
        {
            _dbContext.Shifts.Add(shift);
        }
        else
        {
            // 更新已有Shift的字段
            _dbContext.Entry(existingShift).CurrentValues.SetValues(shift);
            // 同时更新Costs(这里可以根据需求处理,比如替换或追加)
            existingShift.Costs.Clear();
            existingShift.Costs.AddRange(shift.Costs);
        }
    }

    await _dbContext.SaveChangesAsync();
}
额外注意事项
  • DTO隔离:尽量用DTO来处理API返回数据,不要直接把EF实体暴露给API层,避免业务逻辑和数据层耦合。
  • 错误处理:记得给API请求、反序列化、数据库操作添加try-catch块,处理异常情况(比如网络错误、JSON格式错误、数据库约束冲突等)。
  • 性能优化:如果API返回的数据量很大,建议分批处理和保存,避免一次性加载太多数据到内存。
  • 事务处理:如果需要保证Shift和Cost数据的一致性,可以用EF的事务:
    using var transaction = await _dbContext.Database.BeginTransactionAsync();
    try
    {
        await _dbContext.SaveChangesAsync();
        await transaction.CommitAsync();
    }
    catch
    {
        await transaction.RollbackAsync();
        throw;
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 07:57:50