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

使用EntityFrameworkCore保存数据时触发DbUpdateException异常求助

EF Core保存数据时主键重复异常排查与解决

异常信息

Microsoft.EntityFrameworkCore.DbUpdateException
HResult=0x80131500
Message=保存实体变更时出错,请查看内部异常获取详细信息。
Source=Microsoft.EntityFrameworkCore.Relational

Inner Exception 1:
MySqlException: 主键 '08dad56f-8499-4b4f-81b7-53c3ca5c06eb' 重复输入

问题代码

Account? account=null;

using (AppDbContext context = new())
{
   account = context.Set<Account>()
             .Include(e=>e.AccountCategory)
             .First()
}

if (account == null) return;

var inv= new Invoice()
{
     Name=str,
     Account = account,
     InvoiceItems = GetInvoiceItems()
};

var _context=new AppDbContext();
_context.Set<Invoice>().Add(inv);
_context.SaveChanges();

原因分析

你使用了两个独立的DbContext实例:第一个上下文在using块结束后被释放,查询到的Account实体变为脱离跟踪状态。当你将这个脱离跟踪的Account赋值给Invoice.Account,再通过第二个上下文调用Add(inv)时,EF Core会默认将整个对象图(包括Account)标记为Added状态,尝试插入一条新的Account记录,但该Account的主键已存在于数据库中,因此触发主键重复异常。

解决方案

方案1:复用同一个DbContext实例

将查询与保存逻辑放在同一个DbContext的using块内,确保Account始终处于被跟踪状态,EF Core只会插入Invoice,不会重复插入Account:

using (AppDbContext context = new())
{
    var account = context.Set<Account>()
                 .Include(e => e.AccountCategory)
                 .FirstOrDefault();

    if (account == null) return;

    var inv = new Invoice()
    {
        Name = str,
        Account = account,
        InvoiceItems = GetInvoiceItems()
    };

    context.Set<Invoice>().Add(inv);
    context.SaveChanges();
}

方案2:手动附加Account到新上下文并设置状态为Unchanged

若必须使用不同上下文,需将Account附加到新上下文,并明确标记为Unchanged,告知EF Core该实体已存在于数据库:

Account? account = null;

using (AppDbContext context = new())
{
    account = context.Set<Account>()
                 .Include(e => e.AccountCategory)
                 .FirstOrDefault();
}

if (account == null) return;

var inv = new Invoice()
{
    Name = str,
    Account = account,
    InvoiceItems = GetInvoiceItems()
};

using (var _context = new AppDbContext())
{
    _context.Attach(account).State = EntityState.Unchanged;
    _context.Set<Invoice>().Add(inv);
    _context.SaveChanges();
}

方案3:直接设置外键属性(推荐)

如果Invoice实体有对应的外键属性(如AccountId),直接设置外键而非整个Account实体,避免EF Core处理对象图时的误操作:

Account? account = null;

using (AppDbContext context = new())
{
    account = context.Set<Account>()
                 .FirstOrDefault();
}

if (account == null) return;

var inv = new Invoice()
{
    Name = str,
    AccountId = account.Id,
    InvoiceItems = GetInvoiceItems()
};

using (var _context = new AppDbContext())
{
    _context.Set<Invoice>().Add(inv);
    _context.SaveChanges();
}

内容的提问来源于stack exchange,提问作者eng_hr.ye

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 03:15:51