4

我首先使用实体​​框架代码和迁移来开发应用程序。

我有以下类,表示当一个用户为某个产品备份另一个用户时两个用户之间的关系。User 和 Product 类没有对 UserBackup 的任何引用。此关系应映射到 dbo.UserBackup 表。用户可以为多个产品拥有多个备份用户。所以基本上只有 ProductId、BackupUserId 和 UserId 的组合在表中是唯一的。

public class UserBackup
{
    public int Id { get; set; }

    public User User { get; set; }

    public User BackupUser { get; set; }

    public Product Product { get; set; }
}

我在上下文类中覆盖 OnModelCreating 方法,如下所示:

private static void CreateUserBackupTable(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<UserBackup>().ToTable("UserBackup");
    modelBuilder.Entity<UserBackup>().HasKey(e => e.Id);
    modelBuilder.Entity<UserBackup>().HasRequired<User>(e => e.User).WithMany().Map(x => x.MapKey("UserId"));
    modelBuilder.Entity<UserBackup>().HasRequired<User>(e => e.BackupUser).WithMany().Map(x => x.MapKey("BackupUserId"));
    modelBuilder.Entity<UserBackup>().HasRequired<Product>(e => e.Product).WithMany().Map(x => x.MapKey("ProductId"));
}

应用“Add-Migration”命令后生成的迁移文件包含以下代码。

CreateTable(
    "dbo.UserBackup",
    c => new
    {
        Id = c.Int(nullable: false, identity: true),
        UserId = c.Int(nullable: false),
        BackupUserId = c.Int(nullable: false),
        ProductId = c.Int(nullable: false)
    })
    .PrimaryKey(t => t.Id)
    .ForeignKey("dbo.User", t => t.UserId, cascadeDelete: true)
    .ForeignKey("dbo.User", t => t.BackupUserId, cascadeDelete: true)
    .ForeignKey("dbo.Product", t => t.ProductId, cascadeDelete: true)
    .Index(t => t.UserId)
    .Index(t => t.BackupUserId)
    .Index(t => t.ProductId);

但是,当我运行应用程序时,出现以下异常:

在表“UsersBackup”上引入 FOREIGN KEY 约束“FK_dbo.UserBackup_dbo.User_BackupUserId”可能会导致循环或多个级联路径。

指定 ON DELETE NO ACTION 或 ON UPDATE NO ACTION,或修改其他 FOREIGN KEY 约束。

无法创建约束。请参阅以前的错误。

如果我删除外键约束,我不会收到错误消息。或者至少指定“ cascadeDelete: false”。但是我需要从 UserBackup 表中删除记录,以防备份用户被删除。

4

1 回答 1

8

这是 SQL Server 而非实体框架的限制。在 SQL Server 中,您不能将 2 个外键级联删除到同一个表(UserId 和 BackupUserId 指向同一个表)。

我在 2009 年向 MS 的人询问过这个问题,答案是这个限制不会被删除。现在在 2014 年它没有改变,所以我猜他们是认真的。

您唯一的选择是手动管理删除和删除级联选项。

编辑:

要删除级联,只需.WillCascadeOnDelete(false);为每个关系添加或关闭整个模型的级联:

modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
于 2014-11-07T10:23:30.590 回答