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
相关产品推荐
相关产品推荐

