为什么SQL Server不能处理指向同一个表的两个外键的级联删除?

时间:2011-05-11 01:40:47

标签: sql-server entity-framework sql-server-ce ef-code-first entity-framework-4.1

我正在使用实体框架 - 代码优先,我遇到了一个问题,我必须禁用特定外键的级联删除。

这是我的实体类:

public class ChallengeMatch
{
    public int Id { get; set; }
    public int ChallengerClubMemberId { get; set; }
    public int ChallengeeClubMemberId { get; set; }
    public bool ChallengerWon { get; set; }
    public string Score { get; set; }

    public virtual ClubMember ChallengerClubMember { get; set; }
    public virtual ClubMember ChallengeeClubMember { get; set; }
}

如果我允许Code First使用所有默认设置(包括级联删除)为该表生成数据库,则在尝试生成数据库对象时会抛出异常。

如果我将以下代码添加到DbContext类,我不会再出现异常,但现在级联删除只会有点工作:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<ChallengeMatch>()
        .HasRequired(cm => cm.ChallengeeClubMember)
        .WithMany()
        .HasForeignKey(cm => cm.ChallengeeClubMemberId)
        .WillCascadeOnDelete(false);
}

因此,我必须手工编写代码。具体来说,如果我要删除ClubMember 13,我必须删除ChallengeeClubMemberId为13的ChallengeMatch。

我不明白为什么任何这些都是必要的。为什么SQL Server不能处理级联删除,即使有两个外键指向同一个表?我想不出有什么理由会失败。

这应该是一个简单的三步过程(伪代码):

  1. 删除ChallengerClubMemberId == 13
  2. 的所有挑战赛
  3. 删除ChallengeeClubMemberId == 13
  4. 所有挑战赛
  5. 删除Id = 13的俱乐部会员。
  6. 为什么SQL Server不能这样做或为什么不选择?

1 个答案:

答案 0 :(得分:2)

问题是您的配置允许多个级联删除路径。如果您的属性都指向相同的ClubMember,则会发生这种情况。 SQL Server不允许这样做。它更多地是关于SQL服务器的内部实现,更多细节可以在this answer中找到。我认为这个检查是简单而安全的解决方案,以避免在删除并行级联期间的某些竞争条件。