在同一上下文中添加父实体和子实体,并调用SaveChanges

编程语言 2026-07-10

我有一个查找项和一个父实体,我想在同一个事务中将它们一起添加。

举例来说,我使用以下代码:

foreach (ParentDto parentdto in ParentList)
{
    Parent newParent = new Parent();

    if (parentdto.itemid == 0)
    {
        var currentItem = await (from k in _context.LookupItems where k.Keyword.ToLower() == keyword.KeywordData.ToLower() select k).FirstOrDefaultAsync();

        if (currentItem == null)
        {
            LookupItem item = new TLookupItem();
            item.name = parentdto.itemName;
            newParent.Item = item;
        }
    }

    newParent.Id = Guid.CreateVersion7();
    newParent.Name = parentdto.Name;

    _context.Parents.Add(newParent);
}

await _context.SaveChangesAsync();

然而这会产生一个异常:

插入语句与外键约束冲突 "FK_Parents_LookupItems"。冲突发生在数据库 "ProjectDb",表 "dbo.LookupItems",列 'Id'。该语句已终止。

我该怎么办?

LookupItems 表具有主键列 IdParents 表有一个 LookupItemId 列,它是外键,引用 LookupItems 表的 Id 列。

解决方案

我在这里做出了一些假设——它们确实覆盖了大量场景,可能也包括你们的情况。如果这些假设是错误的,你需要根据你的具体设置进行调整。

  • 你在 Parent 类中有一个导航属性,用于保存子对象
  • 数据库使用SQL Server
  • 在你的表中使用 IDENTITY 主键

在这种情况下:通过以下代码向数据库添加新条目

var entry = _context.LookupItems.Add(item);

并不会创建一个新的 Id 值——你并没有真正把记录添加到数据库中,只是添加到了你的上下文(内存中)。

处理方式是:

  • 创建新的父对象
  • 创建新的子对象,并把它分配给一个导航属性
  • 一次性保存完整的对象图,让EF Core处理在将行插入数据库表时修正 Id 值所需的所有细节。

试试这段代码:

// Create new parent object - as is 
Parent newParent = new Parent();
newParent.Name = "myName";

// Create new child object
LookupItem item = new LookupItem();
item.data= "test";

// Assign new child object to parent
newParent.lookup = item;

// Now save complete object graph to context 
_context.Parents.Add(newParent);

// Persist changes made to database
await _context.SaveChangesAsync();
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章