¿Cómo deshabilitar la eliminación en cascada para las tablas de enlaces en el código EF primero?

Quiero deshabilitar las eliminaciones en cascada para una tabla de enlaces con el código de entidad primero. Por ejemplo, si muchos usuarios tienen muchos roles e bash eliminar un rol, quiero que esa eliminación se bloquee a menos que no haya usuarios actualmente asociados con ese rol. Ya OnModelCreating convención de eliminación en cascada en mi OnModelCreating :

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

Y luego configuré la tabla de enlace de rol de usuario:

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

Sin embargo, cuando EF crea la base de datos, crea una cascada de eliminación para las relaciones de clave externa, por ej.

 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 

¿Cómo puedo evitar que EF genere esta cascada de eliminación?

Tengo la respuesta. 🙂 Esas eliminaciones en cascada se estaban creando debido a ManyToManyCascadeDeleteConvention . Debe eliminar esta convención para evitar que cree eliminaciones en cascada para tablas de enlaces:

 modelBuilder.Conventions.Remove(); 

Estoy de acuerdo con Ebram Khalil en que apagarla para una sola mesa es una buena opción. Sin embargo, me gusta mantenerme lo más cerca posible de las migraciones construidas automáticamente, así que lo configuré en OnModelCreating:

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

Creo que esto conserva la eliminación yendo en la otra dirección, por lo que si ambos necesitan ser bloqueados (tiene sentido en este ejemplo) una llamada similar tendría que hacerse a partir de Entity(Role)

Por supuesto, esto viene años después de que se hizo la pregunta. Por lo tanto, puede no haber sido válido en 2012.

Creo que desactivar ManyToManyCascadeDeleteConvention globalmente no es una buena opción. En cambio, es mejor desactivarlo solo para la tabla correspondiente .

Esto se puede lograr editando el archivo de migración generado, para la propiedad cascadeDelete . Por ejemplo:

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