[英]Circular dependency on delete (EF core)
我的数据库中有两个相互引用的类,如下例所示。
Parent
可以有任意数量的Child
对象,我设置了一个外键约束让Child.ParentID
引用Parent.ID
; 为关系设置DeleteBehavior.Cascade
可确保在删除Parent
时也删除所有Child
对象。
问题是我还需要引用Parent
class 中的一个Child
对象,在下面的示例中称为PreferredChild
。 如果我设置DeleteBehavior.SetNull
,我期待在Parent.PreferredChildId
和Child.ID
之间创建约束会起作用,但实际发生的是,当我删除Parent
object 时,如果设置了PreferredChildID
,我会得到这个异常:
System.InvalidOperationException:'无法保存更改,因为在要保存的数据中检测到循环依赖:'Parent [Deleted] PreferredChild PreferredParent {'PreferredChildID'} <- Child [Deleted] Parent Children {'ParentID'} <- Parent [已删除]'。
有没有办法 model 这样我就可以在不先取消设置PreferredChildID
的情况下删除Parent
object ?
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
public class Parent {
public int? ID { get; set; }
public int? PreferredChildID { get; set; }
public virtual Child PreferredChild { get; set; }
public virtual ICollection<Child> Children { get; set; }
}
public class Child {
public int? ID { get; set; }
public int? ParentID { get; set; }
public virtual Parent Parent { get; set; }
public virtual Parent PreferringParent { get; set; }
}
public class TestContext : DbContext {
public DbSet<Parent> Parents { get; set; }
public DbSet<Child> Children { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder options) {
options.UseSqlite("Data Source=test.db");
}
protected override void OnModelCreating(ModelBuilder modelBuilder) {
// I would like to configure the model so that when a Parent is deleted,
// all Children are deleted. Using SetNull on PreferredChildID to avoid object
// being deleted twice
modelBuilder
.Entity<Child>()
.HasOne(c => c.PreferringParent)
.WithOne(p => p.PreferredChild)
.HasForeignKey<Parent>(p => p.PreferredChildID)
.OnDelete(DeleteBehavior.SetNull);
modelBuilder
.Entity<Child>()
.HasOne(c => c.Parent)
.WithMany(p => p.Children)
.HasForeignKey(c => c.ParentID)
.OnDelete(DeleteBehavior.Cascade);
}
}
class Program {
static void Main(string[] args) {
using (var context = new TestContext()) {
var parent = new Parent();
context.Parents.Add(parent);
context.SaveChanges();
var child1 = new Child { ParentID = parent.ID };
var child2 = new Child { ParentID = parent.ID };
context.Children.AddRange(child1, child2);
context.SaveChanges();
parent.PreferredChildID = child2.ID;
context.SaveChanges();
// This explodes
context.Parents.Remove(parent);
context.SaveChanges();
}
}
}
为什么不只做以下事情?
public class Parent { public int? ID { get; set; } public int? LastChildID => LastChild?.ID; public virtual Child LastChild => Children?.LastOrDefault(); public virtual ICollection<Child> Children { get; set; } }
编辑:在 OP 编辑了他的问题之后,他想要什么就更清楚了。
我建议像这样添加第三个表
CREATE TABLE [dbo].[PreferredChilds] (
[ParentId] INT NOT NULL,
[PreferredChild] INT NOT NULL,
PRIMARY KEY CLUSTERED ([ParentId] ASC, [PreferredChild] ASC),
FOREIGN KEY ([ParentId]) REFERENCES [dbo].[Parents] ([Id]),
FOREIGN KEY ([PreferredChild]) REFERENCES [dbo].[Children] ([Id])
);
这样你就不会对循环依赖有任何问题。 如果删除父项,则preferredchilds
和children
表中的条目也将被删除。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.