4

最初に Entity-Framework コードと移行を使用してアプリケーションを開発しています。

次のクラスがあります。これは、あるユーザーが別の製品のバックアップを作成するときの 2 人のユーザー間の関係を表します。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

これは、Entity Framework ではなく SQL Server の制限です。SQL Server では、2 つの外部キーを同じテーブルにカスケード削除することはできません (UserId と BackupUserId は同じテーブルを指します)。

私は 2009 年に MS の人々にそれについて尋ねましたが、その答えは、この制限は取り除かれないというものでした。2014年になってもそれは変わらなかったので、彼らは本気だったのでしょう。

唯一のオプションは、手動で削除を管理し、カスケード オプションを削除することです。

編集:

カスケードを削除するに.WillCascadeOnDelete(false);は、リレーションごとに追加するか、モデル全体のカスケードをオフにします。

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