我有一个类,它引用自己作为"等效版本"链;但是一旦设置,我就无法清除此引用。
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 生成的外键列也不会更新为显示 null。它甚至不会抛出错误,只是不更新。
请注意,在这种情况下,我实际上不想从数据库中删除任何这些 Foos。所有应该发生的是正在更新的 Foo 现在应该有一个引用任何EquivalentFoos
的空键。
根据文档,将State
设置为Modified
应该将所有属性(包括阴影)也设置为修改。
但是,正如您已经观察到的那样,具有 null 值的影子 FK 属性(以及相应的参考导航属性同时为 null)似乎具有特殊处理,特别是未标记为由上述操作修改(如果您使用Update
方法,则相同)。
因此,您需要强制 EF Core 更新 FK 属性,方法是使用Reference
方法返回的ReferenceEntry
手动将其标记为已修改,例如
//...
var entry = _context.Entry(foo);
entry.State = EntityState.Modified;
entry.Reference(e => e.EquivalentFoo).IsModified = true; // <--
//...
注意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; }
}