Подтвердить что ты не робот

Как отключить каскадное удаление для таблиц ссылок в EF-кодах?

Я хочу отключить каскадные удаления для таблицы ссылок с первым кодом сущности. Например, если у многих пользователей много ролей, и я пытаюсь удалить роль, я хочу, чтобы это удаление было заблокировано, если нет пользователей, которые в настоящее время связаны с этой ролью. Я уже удаляю соглашение об исключении каскада в моем 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 этого каскада delete?

4b9b3361

Ответ 1

Я получил ответ.:-) Эти каскадные удаления создавались из-за ManyToManyCascadeDeleteConvention. Вам нужно удалить это соглашение, чтобы предотвратить его создание каскадных удалений для таблиц ссылок:

modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();

Ответ 2

Я согласен с Эбрамом Халилом в том, что отключение его для одного стола - хороший вариант. Однако мне нравится придерживаться автоматически построенных миграций, так как я могу настроить его в 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 году.

Ответ 3

Я считаю, что отключение ManyToManyCascadeDeleteConvention во всем мире не является разумным вариантом. Вместо этого лучше отключить его только для соответствующей таблицы.

Это может быть достигнуто путем редактирования сгенерированного файла миграции для свойства cascadeDelete. Например:

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