EF Core - 代码优先 - 多个级联路径

时间:2018-02-23 12:32:00

标签: sql-server entity-framework foreign-keys entity-framework-core cascading-deletes

我知道很多关于这个主题的文章,所以我先说一下我在Google about this topic上仔细阅读前2页。

许多人建议放DeleteBehavior.Restrict,而dotnet ef database update不再抱怨。在您尝试删除记录之前问题已解决。

我遇到与this SO question完全相同的问题,该问题与this one重复。第二个链接中提出的解决方案是:

  

你应该打破这个循环。你可以通过关闭来做到这一点   级联删除(通过包含WillCascadeOnDelete(false))   对于至少一个的相应关系配置)   关系客户 - >付款或客户 - > billingCenters。

这是我到目前为止研究的内容 现在让我们再次解决问题。我有钻石关系: Schema

所有ForeignKeys必须为not null。因此,设置一个外键以允许null不是一种选择。我还希望该用户可以删除:

  • 参数 - 值 - 部件 - >这里没问题
  • 参数值 - >这里没问题 OnDelete(DeleteBehavior.Cascade)
  • 参数 - 部件 - >这里没问题 OnDelete(DeleteBehavior.Cascade)
  • 参数 - >大问题

要关注answer on this SO question,我可以使用Parameter-PartsParameter-Value-PartsOnDelete(DeleteBehavior.Restrict)之间打破周期。
这样我就可以删除Parameter,但现在我无法删除Parameter-Parts

我可以在删除Parameter-Value-Parts之前手动删除所有Parameter-Parts,但我希望避免手动删除。这可能吗?

我还在SO上读到,在应用程序中应该避免所有cascade delete,并且开发人员应该在删除行之前手动处理删除依赖表行。什么是最佳实践?
删除级联似乎很容易解决,但我不是在寻找一个简单的解决方案,而是正确的解决方案。在大型应用程序中可以轻松扩展到大型数据模型的那个。

1 个答案:

答案 0 :(得分:2)

我希望我能正确理解你的要求。

如果你想要一个真正的钻石形状,那么ParameterValueParts需要引用ParameterValuesParameterParts来引用同一个Parameter。这将由SQL中的复合键建模:

class Parameter
{
    public int ParameterId { get; set; }
}

class ParameterValue
{
    // composite key of ParameterId, ValueId with ParameterId also being a foreign key
    public int ParameterId { get; set; }
    public int ValueId { get; set; }
}

class ParameterPart
{
    // composite key of ParameterId, PartId with ParameterId also being a foreign key
    public int ParameterId { get; set; }
    public int PartId { get; set; }
}

class ParameterValueParts
{
    // key
    public int Id { get; set; }

    // three foreign keys:
    // ParameterId as foreign key to Parameter
    // ParameterId, ValueId are the composite foreign key to ParameterValue
    // ParameterId, PartId are the composite foreign key to ParameterPart
    public int ParameterId { get; set; }
    public int ValueId { get; set; }
    public int PartId { get; set; }
}

这样,您可以拥有ParameterValueParameterPart的多种组合,但每种组合都必须属于特定的Parameter。有了这个基本设计,我的项目中从未遇到任何级联问题。

附注:您可以在各自的类中将ValueIdPartId配置为DatabaseGeneratedOption.Identity,以便不手动处理ID值。 (至少在EF6中,我希望EF Core在这方面的工作方式类似)