与实体框架 ASP.net MVC 中多个表的可选关系

Posted

技术标签:

【中文标题】与实体框架 ASP.net MVC 中多个表的可选关系【英文标题】:Optional relationship to more than one table in Entity Framework ASP.net MVC 【发布时间】:2016-02-24 18:49:21 【问题描述】:

我正在尝试构建一个 ASP.net MVC 应用程序。我无法与数据注释建立某种关系。

我有 3 张桌子,OverhoursAccountingsVacations。每个Overhour 记录可以有1 个AccountingVacation 记录,但它是可选的。所以,它不需要有一个。这是我的Overhour 模型:

public class Overhour


    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int OverhourId  get; set; 

    ....

    public int? AccountingId  get; set; 
    public virtual Accounting Accounting  get; set; 

    public int? VacationId  get; set; 
    public virtual Vacation Vacation  get; set; 

当我删除我的Overhour 记录(如果有的话)时,我希望同时删除VacationAccounting 记录。当我这样使用它时,级联删除被禁用。

我试过这个:

public class Overhour


    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int OverhourId  get; set; 

    ....

    public virtual Accounting Accounting  get; set; 

    public virtual Vacation Vacation  get; set; 

级联删除有效,但实体框架会创建诸如“Accounting_AccountingId”之类的字段,这也是必需的。这些不应该是必需的。

我尝试的最后一件事是:

public class Overhour


    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int OverhourId  get; set; 

    ....

    public int AccountingId  get; set; 
    public virtual Accounting Accounting  get; set; 

    public int VacationId  get; set; 
    public virtual Vacation Vacation  get; set; 

但这一次它给了我这样的错误:

在表 xxx 上引入 FOREIGN KEY xxx 约束可能会导致循环或多个级联路径。指定 ON DELETE NO ACTION 或 ON UPDATE NO ACTION,或修改其他 FOREIGN KEY 约束

我很困惑,我做错了什么?

谢谢

【问题讨论】:

【参考方案1】:

DELETE CASCADE 不能这样工作。如果您删除Overhour,则不会也不应该删除任何其他内容。它以相反的方向工作。如果Accounting 是必需的依赖项,并且您删除了附加到OverhourAccounting 实例,那么Overhour 也应该被删除。如果外键可以为空,则不会发生这种情况,因为它将被设置为 DELETE SET NULL。不过,无论哪种方式,删除 Overhour 都不会对 AccountingVacation 实例产生任何影响。

更新

在这种情况下,您似乎需要创建一对一,因为关系的一侧是可选的,因此相对容易。您只需要:

public class Overhour

    ...

    public int? AccountingId  get; set;  // optional
    public virtual Accounting Accounting  get; set; 


public class Accounting

    ...

    public int OverhourId  get; set;  // required
    public virtual Overhour Overhour  get; set; 

这样,删除Overhour 将级联并删除关联的Accounting,因为它依赖于Overhour

只有当关系的双方都需要时,事情才会变得复杂。然后,您必须使用 fluent 配置将一个设置为主体,一个设置为从属,因为此时 EF 无法自行做出此决定。

【讨论】:

实际上级联删除在我的第二个示例中有效。我很混乱。那么,在我的情况下我应该怎么做?我应该自己删除相关记录吗?因为我在删除加班记录时需要删除会计和休假记录。 嗯,问题是你如何对待他们。默认情况下,这将创建一对多,即Overhour 有一个AccountingAccounting 有很多Overhour。这就是为什么它不会在这种情况下删除Accounting,因为它可能在这个Overhour 实例之外仍然具有有效用途。如果您真的希望 Accounting 绑定到特定的 Overhour 实例,那么您的关系应该是一对一的。 我迷路了,我想我需要阅读更多关于 Fluent Api 的内容。 感谢您的更新。问题是,会计也不需要有加班记录。所以,我猜双方都是可选的。也许这就是它不起作用的原因。大概没有这样的关系类型吧? 你可以有一个一对一的双方都是可选的。但是,两者都需要的相同警告适用:您必须使用流利的配置来提示 EF 哪个是依赖的,哪个是主体。也就是说,我不确定为什么您会期望在任一方向都有删除级联。如果Accounting 不依赖于特定的Overhour,那么它在逻辑上不应该仅仅因为Overhour 被删除而被删除。如果它在与Overhour 的关系之外没有价值,则应该需要Overhour

以上是关于与实体框架 ASP.net MVC 中多个表的可选关系的主要内容,如果未能解决你的问题,请参考以下文章

asp.net mvc 模型与实体框架模型

asp.net mvc实体框架代码先将外键与不同名称关联

如何在 Asp.net MVC 和实体框架中分页时应用过滤器?

asp.net mvc框架中 怎样在一个 View 内传递多个 Model,最好有代码,谢谢

如何使用代码优先实体框架在 ASP.Net MVC3 中重新加载多对多导航属性

如何在 Asp.Net 5 (MVC 6) 中使用实体框架 6.x