2012-12-04 13 views
54

Voglio disabilitare le eliminazioni a cascata per una tabella di collegamento con il codice dell'entità del codice prima. Ad esempio, se molti utenti hanno molti ruoli e io cerco di eliminare un ruolo, voglio che quell'eliminazione sia bloccata a meno che non ci siano utenti attualmente associati a quel ruolo. Ho già rimuovere la cascata eliminare convenzione nel mio OnModelCreating:Come disabilitare la cancellazione a cascata per le tabelle di collegamento in codice EF prima?

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

E poi ho creato la tabella di collegamento utente-ruolo:

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

Eppure, quando EF crea il database, si crea una cascata di cancellazione per le relazioni con le chiavi estranee, ad es.

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 

Come posso interrompere EF che genera questa eliminazione in cascata?

risposta

93

Ho la risposta. :-) Queste eliminazioni a cascata venivano create a causa di ManyToManyCascadeDeleteConvention. È necessario rimuovere questa convenzione per evitare che la creazione di cascata eliminazioni per le tabelle di collegamento:

modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>(); 
+0

Grazie mi ha aiutato un sacco. Curioso, hai finito per rimuovere ENTRAMBI le convenzioni o solo la convenzione Many to Many? – kmehta

+7

In realtà, ho appena finito di rimuovere la convenzione uno-a-molti e di riattivarla selettivamente per una o due entità. Le mie note a riguardo lo dicono, perché (a differenza di uno a molti) non puoi usare l'API Fluent per riattivare l'eliminazione a cascata per molti a molti usando '.WillCascadeOnDelete (true)', * all * le tabelle many-to-many devono essere a cascata, o non a cascata. Consideravo averli * tutti * cascade come il minore dei mali, perché la maggior parte delle volte, se elimino qualcosa collegato usando una tabella di collegamenti molti-a-molti, voglio che anche le cose a cui è collegato vengano eliminate. – Jez

+1

Questo non sembra funzionare. Il mio problema è quando ho due proprietà di un oggetto dello stesso tipo (creato da questo utente e modificato da questo utente.) Speravo che questo avrebbe rimosso l'errore "può causare il ciclo o più percorsi a cascata" che sto ottenendo, ma non ha funzionato Suggerimenti? – Rogala

0

credo che disattivando ManyToManyCascadeDeleteConvention a livello globale non è una scelta saggia. Invece, è meglio disattivarlo solo per la tabella in questione.

Ciò può essere ottenuto attraverso la modifica del file di migrazione generato, per la proprietà cascadeDelete. Per esempio:

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

0

Sono d'accordo con Ebram Khalil che spegnerlo per una singola tabella è una buona opzione. Mi piace attaccare il più vicino alle migrazioni costruite automaticamente come posso, però, quindi vorrei configurarlo in 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); 

Credo che questo conserva l'eliminare andando nella direzione opposta, quindi, se sia necessario per essere bloccato (ha senso in questo esempio) una chiamata simile dovrebbe essere fatta a partire da Entity<User>(Role)

Naturalmente, questo arriva dopo che la domanda è stata posta. Quindi potrebbe non essere stato valido nel 2012.

Problemi correlati