【问题标题】:How to set up Navigation Properties to enforce deleting related records如何设置导航属性以强制删除相关记录
【发布时间】:2014-12-17 15:12:10
【问题描述】:

我正在使用 MVC 4 和 VS2010 以及 Entity Framework 6.1.x。我正在使用 Code First 相当简单的数据库,但其中有一个稍微复杂的部分。首先,Person 和Recording 两个表有一对多的关系。

public class Person {
    public int PersonID { get; set; }
    public int GenderID { get; set; }

    // Navigation property
    public virtual List<Recording> Recordings { get; set; }
}

public class Recording {
    public int RecordingID { get; set; }
    // ...
    public int PersonID { get; set; }

    // Navigation properties
    public virtual Person Person { get; set; }
    public virtual List<Junction> Junctions { get; set; }
}

默认情况下,当我删除Person 时,Entity Framework 会删除与Person 相关的所有记录。这就是我所期望的。但是Recording 表中的记录也被放置在不同的表集中。假设我有一个名为Applicant、Application 和Junction 的表。当我通过删除Person 或Recording 删除任何记录时,我希望Junction 中与Recording 中的记录相关的所有记录也被删除。在我的项目中,如果与特定应用程序关联的记录数量为零,那将没有意义。

Junction 中有一个组合的Primary Key,即ApplicantID、ApplicationID 和RecordID,构成复杂的Key。

是否可以通过实体框架强制执行约束,或者我宁愿提供自己的自定义函数?

如何在对应表中设置导航属性:Recording和Junction,以便删除相关记录?

public class Applicant
{
    public int ApplicantID { get; set; }
    // Navigation property
    public virtual List<Junction> Junctions { get; set; }
}

public class Application {
    public int ApplicationID { get; set; }

    // Navigation property
    public virtual List<Junction> Junctions { get; set; }
}    

public class Junction
{
    public int ApplicationID { get; set; }
    public int ApplicantID { get; set; }
    public int RecordingID { get; set; }

    public virtual Application Application { get; set; }
    public virtual Applicant Applicant { get; set; }
    public virtual Recording Recording { get; set; }
}

感谢您的帮助。



编辑

@克里斯。据我了解,如果外键不可为空,则删除主表中具有相应 PrimaryID 的记录时,将删除辅助表中的记录。另一方面,如果外键可以为空,则辅助表中的记录将变为null,但不会被删除。

我制作了这个项目和两张表,并填充了数据库。在Student 类中,如果我让DepartmentID 不可为空,

public int DepartmentID { get; set; }

删除主要DepartmentID 的记录时,记录将被删除。这是我所期望的,但如果我将 DepartmentID 设为可空

public int? DepartmentID { get; set; }

然后我得到了这个错误:

DELETE 语句与 REFERENCE 约束“FK_dbo.Student_dbo.Department_DepartmentID”冲突。冲突发生在数据库“TestDB”、表“dbo.Student”、列“DepartmentID”中。
声明已终止。

在测试项目中,我制作了两张关系为 1 对多的表。

public class Department
{
    public int DepartmentID { get; set; }
    public string DepartmentName { get; set; }

    public virtual List<Student> Students { get; set; }
}

和

public partial class Student : IDisposable
{
    public int StudentID { get; set; }
    public int DepartmentID { get; set; }

    public virtual Department Department { get; set; }
}

这是我应该期待的吗?

【问题讨论】:

  • 我假设Junction 和Recording 之间的关系是多对多?
  • @IronMan84 是的,关系是多对多的

标签: c# asp.net-mvc entity-framework model-view-controller relationship


【解决方案1】:

删除级联并不是为了一时兴起删除项目。它的存在是必要的。在上面的示例中,Recording 具有到 Person 的不可为空的外键。如果删除了 Person,则必须将外键设置为 null(这不可能发生)或必须删除所有相关的 Recordings 以​​保持引用完整性。

在Junction 的第二个示例中,Record 有一个不可为空的外键。因此,如果您删除了一个Person,所有相关的Records 和所有与这些记录相关的Junctions 都应该被删除。但是,如果您删除 Junction,则不会采取进一步的行动。 Junction 本质上没有任何依赖关系,因此它的删除不会被注意到。曾经引用的任何Records 仍然有效。请记住,这一切都是为了维护参照完整性。只要完整性完好无损,就不会删除任何内容。

【讨论】:

  • 感谢您的回答。这真是很好的解释。现在很多事情对我来说都是有意义的。
  • 我已经编辑了这个问题。有一件事让我很困惑。我希望您可以对已编辑的部分发表评论。基本上,我对可为空的外键感到困惑。干杯!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-26
  • 1970-01-01
  • 1970-01-01
  • 2023-03-26
  • 1970-01-01
相关资源
最近更新 更多