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

EF添加子实体时父实体莫名被删除的问题排查

EF Core Code-First 一对一(零或一)关系添加数据时父对象被删除问题

我用EF Core Code-First开发已有一段时间,之前仅使用一对多关系,现在要实现一对一(零或一)关联关系。实体看似符合规范,迁移也成功完成,但添加数据时,父对象先被添加,随后添加子对象时,父对象会莫名被删除。

实体代码

[Table("Parents", Schema = "public")]
public class Parent
{
  [Key]
  [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
  public Guid Id { get; set; }

  public Child Child { get; set; }
}

[Table("Children", Schema = "public")]
public class Child
{
  [Key]
  [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
  public Guid Id { get; set; }

  public Guid? ParentId { get; set; }
  public Parent Parent { get; set; }
}

尝试的ModelBuilder配置

public void Configure(EntityTypeBuilder<Parent> builder)
{
  builder.HasOne<Child>(b => b.Child).WithOne(b => b.Parent)
    .HasForeignKey<Child>(b => b.ParentId).OnDelete(DeleteBehavior.Cascade);
}

注:试过不设置OnDelete行为,问题依旧。

仓储层代码

基础仓储的Add方法:

public virtual int Add(TEntity entity, bool persist = true)
{
    Table.Add(entity);
    return persist ? SaveChanges() : 0;
}

SaveChanges方法:

public int SaveChanges()
{
    return Context.SaveChanges();
}

服务层调用两个仓储的Add方法,所有实体共用一个数据库上下文,基础仓储在一对多场景下正常工作,推测问题出在关系配置上。


解决方案

1. 修正关系配置逻辑

EF Core中一对一关系的外键应设为非空(一对一场景下,子对象关联父对象时必须对应有效父ID),同时明确关系依赖方向,避免影子属性干扰:

// 修改Child实体的ParentId为非空
public Guid ParentId { get; set; }

// 调整ModelBuilder配置
public void Configure(EntityTypeBuilder<Parent> builder)
{
    builder.HasOne(p => p.Child)
           .WithOne(c => c.Parent)
           .HasForeignKey<Child>(c => c.ParentId)
           .OnDelete(DeleteBehavior.Restrict); // 避免级联删除误删父对象
}

2. 调整数据添加方式

不要分开调用两个仓储的Add并多次执行SaveChanges,应一次性关联父子对象后统一保存:

// 服务层示例代码
var parent = new Parent();
var child = new Child { Parent = parent };
parent.Child = child;

// 先添加对象但不立即保存
_parentRepository.Add(parent, persist: false);
_childRepository.Add(child, persist: false);
// 统一执行一次保存
_unitOfWork.SaveChanges();

更简洁的方式:EF Core会自动跟踪关联对象,仅添加父对象即可自动插入子对象:

var parent = new Parent
{
    Child = new Child()
};
_parentRepository.Add(parent); // 直接保存,EF会同时插入父子对象

3. 避免多次触发SaveChanges

多次调用SaveChanges会导致EF的实体状态跟踪异常,添加父子对象时应确保上下文能完整跟踪它们的关联关系,避免拆分保存操作。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 15:37:21