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

.NET 6控制台EF Core调用SaveChanges()后数据库未更新求助

.NET 6控制台应用EF Core批量更新数据库无变化问题排查与解决

问题描述

在.NET 6控制台应用中,通过Foreach循环更新SQL Server中约900条数据,执行完成后数据库无任何更新。调试时API调用正常,所有变量及要更新的item.Status值均正确,但调用SaveChanges()后数据库未发生变化。

相关代码如下:

主逻辑代码

Excel_DBContext context = new Excel_DBContext();
var excel = context.Sheets.Where(c => c.Status == null).ToList();
CallWebAPIAsync().Wait();

async Task CallWebAPIAsync()
{
    using (var client = new HttpClient())
    {
        client.BaseAddress = new Uri("https://jamservice.pna.co.ir/");
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

        Parameters countryList;
        string terminalId;
        string serial;
        HttpResponseMessage response;
     
        foreach (var item in excel)
        {
            terminalId = item.Terminal;
            serial = item.Serial;
            countryList = new Parameters() { TerminalID = terminalId, Serials = serial };

            response = await client.PostAsJsonAsync("services/api/RequestService/BindSerialToSwitch", countryList);

            var resultString = await response.Content.ReadAsStringAsync();

            var resultJson = JsonConvert.DeserializeObject<Excel>(resultString);

            Sheet findTerminal = context.Sheets.First(c => c.Terminal == terminalId);

            if (response.IsSuccessStatusCode)
            {
                item.Status = resultJson.StatusTitle;
                context.SaveChanges();

                Console.WriteLine("Record " + terminalId + " updated");
            }
            else
            {
                Console.WriteLine("Error");
            }
        }
    }
}

Sheet实体类

public partial class Sheet
{
    public string? Terminal { get; set; }
    public string? Serial { get; set; }
    public string? Model { get; set; }
    public string? Status { get; set; }
}

API响应对应类

public class Excel
{
    public string? Terminal { get; set; }
    public string? Serial { get; set; }
    public string? StatusTitle { get; set; }
}

问题原因分析

  1. Sheet实体缺少主键:EF Core需要主键来唯一标识实体,否则无法跟踪实体变化并生成正确的Update语句。当前Sheet类未定义主键,导致SaveChanges()无法识别要更新的记录。
  2. 异步调用方式不当:使用.Wait()阻塞异步方法可能导致上下文状态异常,影响EF Core的实体跟踪逻辑。
  3. 未捕获SaveChanges()异常:若SaveChanges()执行时抛出异常(如数据约束冲突),未被捕获会导致更新失败但无报错提示。

解决方案

1. 为Sheet实体添加主键

EF Core必须依赖主键来管理实体,可通过两种方式配置:

方式一:通过DataAnnotations特性标记

using System.ComponentModel.DataAnnotations;

public partial class Sheet
{
    [Key] // 标记Terminal为主键(需确保Terminal字段值唯一)
    public string? Terminal { get; set; }
    public string? Serial { get; set; }
    public string? Model { get; set; }
    public string? Status { get; set; }
}

方式二:通过Fluent API配置

在Excel_DBContext的OnModelCreating方法中配置主键:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Sheet>().HasKey(s => s.Terminal);
}

2. 修复异步调用方式

将控制台应用的Main方法改为异步,使用await替代.Wait(),避免上下文状态异常:

static async Task Main(string[] args)
{
    using var context = new Excel_DBContext(); // 使用using确保上下文正确释放
    var excel = context.Sheets.Where(c => c.Status == null).ToList();
    await CallWebAPIAsync(context, excel);
}

async Task CallWebAPIAsync(Excel_DBContext context, List<Sheet> excel)
{
    using (var client = new HttpClient())
    {
        client.BaseAddress = new Uri("https://jamservice.pna.co.ir/");
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

        foreach (var item in excel)
        {
            var terminalId = item.Terminal;
            var serial = item.Serial;
            var countryList = new Parameters() { TerminalID = terminalId, Serials = serial };

            var response = await client.PostAsJsonAsync("services/api/RequestService/BindSerialToSwitch", countryList);
            var resultString = await response.Content.ReadAsStringAsync();
            var resultJson = JsonConvert.DeserializeObject<Excel>(resultString);

            if (response.IsSuccessStatusCode)
            {
                item.Status = resultJson.StatusTitle;
                try
                {
                    int affectedRows = context.SaveChanges();
                    Console.WriteLine($"Record {terminalId} updated, affected rows: {affectedRows}");
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"Failed to update {terminalId}: {ex.Message}");
                }
            }
            else
            {
                Console.WriteLine($"API call failed for {terminalId}");
            }
        }
    }
}

3. 移除多余的实体查询

代码中Sheet findTerminal = context.Sheets.First(c => c.Terminal == terminalId);属于冗余代码,item已经是被上下文跟踪的实体,直接更新item.Status即可,无需重复查询。

4. 添加异常捕获

在SaveChanges()处添加异常捕获,便于排查更新失败的具体原因。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 16:54:16