【问题标题】:Deleting principal and dependents for independent association (one-to-many)删除独立关联的委托人和受抚养人(一对多)
【发布时间】:2016-09-07 23:41:53
【问题描述】:

使用带有 Designer 的 Entity Framework 6,我们所有的实体都有一个 independent association。所以我们模型的属性中没有定义外键。

具有以下具有一对多关系的实体:

public class Parent
{
    public Guid Id { get; set; }
    public virtual ICollection<Child> Children { get; set; }
}
public class Child
{
    public Guid Id { get; set; }
    public virtual Parent Parent { get; set; }
}

映射到以下 SQL 表:

CREATE TABLE Parent (
    Id uniqueidentifier NOT NULL,
    CONSTRAINT PK_Parent PRIMARY KEY CLUSTERED (Id)
)

CREATE TABLE Child (
    Id uniqueidentifier NOT NULL,
    FkParent uniqueidentifier NOT NULL,
    CONSTRAINT PK_Child PRIMARY KEY CLUSTERED (Id)
)

ALTER TABLE Child WITH CHECK
ADD CONSTRAINT FK_Child_Parent FOREIGN KEY(FkParent) REFERENCES Parent ([Id])

ALTER TABLE Child CHECK CONSTRAINT FK_Child_Parent

如您所见,我们没有使用CASCADE ON DELETE,因为我的团队反对使用它。

所以问题是,删除父级及其依赖子级的正确方法是什么?仅给出父级的Id
delete,我的意思是在调用.SaveChanges()之后应该删除两个表中的SQL记录(导致DELETE SQL语句)。

【问题讨论】:

  • 听起来您正在寻找删除命令上的数据库trigger,但我不喜欢触发器中的“隐藏”功能,这就像删除功能上的级联。也许只是将它构建到您的(存储库?)删除处理程序的业务逻辑中。
  • @JaredStroeb,没错。我和我的团队也不喜欢这些最终将它们隐藏在应用程序中的业务逻辑之外的数据库功能。但是,这种讨论倾向于设计选择。

标签: c# sql entity-framework


【解决方案1】:

所以我想出如何实现这一点的唯一方法是显式将子代加载到内存中并在实际删除父代之前将它们一一删除。

using (var context = new MyDbContext())
{
    var parent = context.Parents.Find(parentId);
    //or use LINQ if you prefer:
    var alternative = context.Parents.Single(p => p.Id == parentId)

    foreach(var child in parent.Children.ToList())
    {
        context.Children.Remove(child);
    }

    context.Parents.Remove(parent);

    context.SaveChanges();
}

注意Children 上的.ToList()(或.ToArray(),如果您愿意),这是重要,如this answer 中所述。

就性能而言,这并不理想,因为您必须从数据库中查询每个子记录并将其加载到内存中(我想对于小型应用程序来说,这无关紧要)。但是如果不使用CASCADE ON DELETE,我找不到更好的方法,即使我不确定这是否真的会胜过这种情况。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多