web-dev-qa-db-ja.com

EFコードファーストでリンクテーブルのカスケード削除を無効にする方法は?

エンティティフレームワークのコード優先でリンクテーブルのカスケード削除を無効にしたい。たとえば、多くのユーザーが多くのロールを持っている場合、ロールを削除しようとすると、その削除をブロックする必要がありますnlessそのロールに現在関連付けられているユーザーはいません。私はすでにOnModelCreatingのカスケード削除規則を削除しています:

protected override void OnModelCreating(DbModelBuilder modelBuilder) {
    ...
    modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();

次に、ユーザーとロールのリンクテーブルを設定します。

modelBuilder.Entity<User>()
    .HasMany(usr => usr.Roles)
    .WithMany(role => role.Users)
    .Map(m => {
        m.ToTable("UsersRoles");
        m.MapLeftKey("UserId");
        m.MapRightKey("RoleId");
    });

それでも、EFはデータベースを作成するときに、外部キー関係の削除カスケードを作成します。

ALTER TABLE [dbo].[UsersRoles]  WITH CHECK ADD  CONSTRAINT [FK_dbo.UsersRoles_dbo.User_UserId] FOREIGN KEY([UserId])
REFERENCES [dbo].[User] ([UserId])
ON DELETE CASCADE
GO

ALTER TABLE [dbo].[UsersRoles]  WITH CHECK ADD  CONSTRAINT [FK_dbo.UsersRoles_dbo.Role_RoleId] FOREIGN KEY([RoleId])
REFERENCES [dbo].[Role] ([RoleId])
ON DELETE CASCADE
GO

この削除カスケードを生成するEFを停止するにはどうすればよいですか?

63
Jez

私は答えを得ました。 :-) ManyToManyCascadeDeleteConventionが原因で、これらのカスケード削除が作成されていました。リンクテーブルのカスケード削除を作成しないように、この規則を削除する必要があります。

modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();
104
Jez

Ebram Khalilに同意します。1つのテーブルでそれをオフにするのが良い選択肢です。ただし、できる限り自動構築された移行に近づけるのが好きなので、OnModelCreatingで設定します。

_modelBuilder.Entity<User>()
    .HasMany(usr => usr.Roles)
    .WithMany(role => role.Users)
    .Map(m => {
        m.ToTable("UsersRoles");
        m.MapLeftKey("UserId");
        m.MapRightKey("RoleId");
    })
    .WillCascadeOnDelete(false);
_

これは削除が他の方向に進むと保存するため、両方をブロックする必要がある場合(この例では理にかなっています)、Entity<User>(Role)で始まる同様の呼び出しを行う必要があります。

もちろん、これは質問が行われた後の年齢になります。したがって、2012年には有効ではなかった可能性があります。

5
TwainJ

ManyToManyCascadeDeleteConventionをグローバルにオフにするのは賢明なオプションではないと思います。代わりに、オフにすることをお勧めします関係者のみテーブル。

これは、プロパティcascadeDeleteの生成された移行ファイルを編集することで実現できます。例えば:

AddForeignKey("dbo.UsersRoles", "UserId", "dbo.User", "UserId", cascadeDelete: false);

2
ebram khalil