EF Core 删除对自身的引用而不删除

Posted

技术标签:

【中文标题】EF Core 删除对自身的引用而不删除【英文标题】:EF Core Remove Reference to Self without deleting 【发布时间】:2021-11-30 02:21:34 【问题描述】:

我有一个类将自己引用为“等效版本”链;但是一旦设置,我就无法清除此引用。

public class Foo

   public int FooId  get; set; 
   public string Name  get; set; 
   public virtual Foo EquivalentFoo  get; set; 

   public static void RunFluent(ModelBuilder modelBuilder)
   
     EntityTypeBuilder<Foo> entity = modelBuilder.Entity<Foo>();
     entity.HasKey(f => f.FooId);
     entity.HasOne(f => f.EquivalentFoo).WithMany().IsRequired(false);
   

我的控制器有以下更新端点:

[HttpPut("id")]
public async Task<IActionResult> PutFoo(int id, Foo foo)

    ...

    _context.Entry(foo).State = EntityState.Modified;

    if (foo.EquivalantFoo != null)
    
        _context.Entry(foo.EquivalantFoo).State = EntityState.Unchanged;
    

    try
    
        await _context.SaveChangesAsync();
    
    catch (DbUpdateConcurrencyException ex)
    
        ...
    

    return NoContent();

这可以很好地添加一个新的EquivalentFoo 到一个没有@ 的@,或者将它更改为一个新的 Foo。

我正在努力通过EquivalentFoo = null 传递一个foo。即使EquivalentFoo 可以为空并且数据库可以使用空键,EF Core 生成的外键列也不会更新为显示空。它甚至不会抛出错误,只是不会更新。

请注意,在这种情况下,我实际上并不想从数据库中删除任何这些 Foo。应该发生的只是被更新的 Foo 现在应该有一个引用任何 EquivalentFoos 的空键。

【问题讨论】:

【参考方案1】:

注意“?”在 ParentFooRefno 上标记,这将允许您添加空值

    public class Foo
    
       [Key,DatabaseGenerated(DatabaseGeneratedOption.Identity)]
       public int FooId  get; set; 
       public string Name  get; set; 

       public int? ParentFooRefno  get; set; 
       
       [ForeignKey("ParentFooRefno ")]
       public virtual Foo EquivalentFoo  get; set; 
    
        
    

【讨论】:

我先试过了,C#只是说它已经可以为空了,没有任何区别。【参考方案2】:

根据文档,将State 设置为Modified 也应将所有属性(包括阴影)设置为已修改。

但是,正如您已经观察到的,具有 null 值的影子 FK 属性(以及相应的引用导航属性同时为 null)似乎有特殊处理,特别是没有被上述操作标记为已修改(如果您使用 @ 987654323@方法)。

因此,您需要强制 EF Core 更新 FK 属性,方法是使用 Reference 方法返回的 ReferenceEntry 手动将其标记为已修改,例如

//...
var entry = _context.Entry(foo);
entry.State = EntityState.Modified;
entry.Reference(e => e.EquivalentFoo).IsModified = true; // <--
//...

【讨论】:

壮观,谢谢!

以上是关于EF Core 删除对自身的引用而不删除的主要内容,如果未能解决你的问题,请参考以下文章

如何删除一列并创建一个新列而不是在 EF Core 中重命名?

从联接表中删除实体而不影响父级 - EF Core 2.2

引用计数 - 内部引用问题

删除对属于 ManagedObjectContext 的 ManagedObjects 的所有引用

关于EF Core对中间表的先删除在增加错误

Spring data JPA:如何启用级联删除而不引用父级中的子级?