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

C# API中Operacao类Update()正常但Create()执行失败排查

Operacao类Create方法抛出DbUpdateConcurrencyException异常排查

我开发的C# API中,多表的更新与创建操作均正常,但Operacao类存在异常:Update()方法运行正常,Create()方法执行失败,抛出DbUpdateConcurrencyException。


实体类定义

Operacao实体类

public class Operacao
{
    public virtual short OperacaoID { get; set; }
    public virtual short? Codigo { get; set; }
    public virtual string Nome { get; set; }
    public virtual string? Descricao { get; set; }
    public virtual bool FlagAtivo { get; set; }
    public virtual bool FlagPadrao { get; set; }
    public virtual int DtUpdate { get; set; }
}

输入数据类OperacaoDados

public class OperacaoDados
{
    [Key]
    [JsonIgnore]
    public short OperacaoID { get; set; }
    [NotMapped]
    public virtual string Nome { get; set; }
    public virtual string? Descricao { get; set; }
}

控制器代码

[HttpPost]
[Authorize]
public async Task<ActionResult> PostOperacao(OperacaoDados operacaoDados)
{
    var operacaoExistente = await _context.Operacao
                                          .FirstOrDefaultAsync(o => o.Nome == operacaoDados.Nome);

    DateTime dateTime = DateTime.UtcNow;
    long ticks = dateTime.Ticks;
    int dataInteiro = (int)(ticks & 0xFFFFFFFF);

    if (operacaoExistente != null)
    {
        operacaoExistente.Descricao = operacaoDados.Descricao;
        operacaoExistente.FlagAtivo = true;

        try
        {
            await _operacaoRepository.Update(operacaoExistente);
            return Ok("Operação atualizada com sucesso");
        }
        catch (DbUpdateConcurrencyException)
        {
            // Handle the concurrency exception here
            return Conflict("A operação que você está tentando atualizar foi modificada por outro usuário.");
        }
    }
    else
    {
        Operacao novoOperacao = new Operacao
                 {
                     Codigo = short.Parse(operacaoDados.Nome),
                     DtUpdate = dataInteiro,
                     Nome = operacaoDados.Nome,
                     Descricao = operacaoDados.Descricao,
                     FlagAtivo = true,
                     FlagPadrao = false
                 };

        var result = await _operacaoRepository.Create(novoOperacao);

        if (result != null)
        {
            return Ok("Operação cadastrada com sucesso");
        }

        return BadRequest("Erro ao salvar Operação");
   }
}

仓库层代码

public async Task<Operacao> Create(Operacao operacao)
{
    _context.Operacao.Add(operacao);
    await _context.SaveChangesAsync();

    return operacao;
}

public async Task Update(Operacao operacao)
{
    _context.Entry(operacao).State = EntityState.Modified;
    await _context.SaveChangesAsync();
}

错误信息

Microsoft.EntityFrameworkCore.Database.Command: 信息:
已执行DbCommand (12ms) [参数=[@p0='?' (DbType = Int16), @p1='?' (Size = 4000), @p2='?' (DbType = Int32), @p3='?' (DbType = Boolean), @p4='?' (DbType = Boolean), @p5='?' (Size = 4000)],
命令类型='文本', 命令超时时间='30']
SET NOCOUNT ON;
INSERT INTO [Operacao] ([Codigo], [Descricao], [DtUpdate], [FlagAtivo], [FlagPadrao], [Nome])
VALUES (@p0, @p1, @p2, @p3, @p4, @p5);
SELECT [OperacaoID]
FROM [Operacao]
WHERE @@ROWCOUNT = 1 AND [OperacaoID] = scope_identity();

引发的异常:
'Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException' 位于 Microsoft.EntityFrameworkCore.Relational.dll 中
引发的异常:
'Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException' 位于 System.Private.CoreLib.dll 中


排查与解决方案

核心原因

创建时抛出该异常,本质是EF Core执行INSERT后,尝试读取自动生成的OperacaoID时未找到对应行,常见触发场景:

  1. OperacaoID未配置为数据库自增主键,导致插入后无自动生成的ID值
  2. 数据库表的INSERT触发器修改/删除了刚插入的行
  3. EF Core未识别OperacaoID为主键,无法正确获取生成的ID

修复步骤

  1. 确认数据库主键配置:
    检查Operacao表的OperacaoID列是否设置为IDENTITY(1,1)(SQL Server),确保数据库自动生成主键值。

  2. 显式配置实体主键:
    在Operacao类的OperacaoID属性上添加特性,明确告知EF Core这是自增主键:

    public class Operacao
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public virtual short OperacaoID { get; set; }
        // 其他属性...
    }
    

    或通过Fluent API在DbContext中配置:

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Operacao>()
            .HasKey(o => o.OperacaoID);
        modelBuilder.Entity<Operacao>()
            .Property(o => o.OperacaoID)
            .ValueGeneratedOnAdd();
    }
    
  3. 检查数据库触发器:
    查看Operacao表是否存在INSERT触发器,若触发器有删除/修改插入行的逻辑,需调整确保插入行保留且OperacaoID值正确。

  4. 验证Codigo赋值逻辑:
    控制器中Codigo = short.Parse(operacaoDados.Nome)存在格式转换风险,若Nome无法转为short会抛出异常,同时需确保该值符合数据库列的约束(如非空、唯一性)。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 05:01:01