Как отключить каскадное удаление для таблиц ссылок в коде EF-first?
сначала я хочу отключить каскадное удаление для таблицы ссылок с кодом Entity framework. Например, если у многих пользователей есть много ролей, и я пытаюсь удалить роль, я хочу, чтобы это удаление было заблокировано если в настоящее время нет пользователей, связанных с этой ролью. Я уже удаляю соглашение о каскадном удалении в моем 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, генерирующий этот каскад удаления?
3 ответа:
Я получил ответ. :- ) Эти каскадные удаления были созданы из-за
ManyToManyCascadeDeleteConvention
. Вам нужно удалить это соглашение, чтобы предотвратить его создание каскадных удалений для таблиц ссылок:modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();
Я согласен с Эбрамом Халилом, что выключение его для одного стола является хорошим вариантом. Однако мне нравится придерживаться как можно ближе к автоматически построенным миграциям, поэтому я бы настроил его в 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 году.
Я считаю, что отключение
ManyToManyCascadeDeleteConvention
глобально это не мудрый вариант. Вместо этого, лучше отключить его только для заинтересованных таблица.Это может быть достигнуто путем редактирования созданного файла миграции, для свойства
cascadeDelete
. Например:
AddForeignKey("dbo.UsersRoles", "UserId", "dbo.User", "UserId", cascadeDelete: false);