Entity Framework 6: Code First Cascade delete

Quindi ci sono diverse domande simili su questo, ma sto ancora avendo problemi a determinare cosa esattamente mi manca nel mio scenario semplificato.

Diciamo che ho le seguenti tabelle, abilmente intitolate a me stesso:

'JohnsParentTable' (Id, Description) 'JohnsChildTable' (Id, JohnsParentTableId, Description) 

Con le classi risultanti sembra così

 public class JohnsParentTable { public int Id { get; set; } public string Description { get; set; } public virtual ICollection JohnsChildTable { get; set; } public JohnsParentTable() { JohnsChildTable = new List(); } } internal class JohnsParentTableConfiguration : EntityTypeConfiguration { public JohnsParentTableConfiguration() { ToTable("dbo.JohnsParentTable"); HasKey(x => x.Id); Property(x => x.Id).HasColumnName("Id").IsRequired().HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); Property(x => x.Description).HasColumnName("Description").IsRequired().HasMaxLength(50); } } public class JohnsChildTable { public int Id { get; set; } public string Description { get; set; } public int JohnsParentTableId { get; set; } public JohnsParentTable JohnsParentTable { get; set; } } internal class JohnsChildTableConfiguration : EntityTypeConfiguration { public JohnsChildTableConfiguration() { ToTable("dbo.JohnsChildTable"); HasKey(x => x.Id); Property(x => x.Id).HasColumnName("Id").IsRequired().HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); Property(x => x.Description).HasColumnName("Description").IsRequired().HasMaxLength(50); HasRequired(a => a.JohnsParentTable).WithMany(c => c.JohnsChildTable).HasForeignKey(a => a.JohnsParentTableId); } } 

Nel database ho una riga nella tabella padre con un ID di 1 insieme a due righe nella tabella figlio legate a questo genitore. Se faccio questo:

 var parent = db.JohnsParentTable.FirstOrDefault(a => a.Id == 1) 

L’object è popolato correttamente. Tuttavia, se provo a cancellare questa riga:

 var parent = new Data.Models.JohnsParentTable() { Id = 1 }; db.JohnsParentTable.Attach(parent); db.JohnsParentTable.Remove(parent); db.SaveChanges(); 

Il framework Entity tenta di eseguire quanto segue:

 DELETE [dbo].[JohnsParentTable] WHERE ([Id] = @0) -- @0: '1' (Type = Int32) -- Executing at 1/23/2014 10:34:01 AM -06:00 -- Failed in 103 ms with error: The DELETE statement conflicted with the REFERENCE constraint "FK_JohnsChildTable_JohnsParentTable". The conflict occurred in database "mydatabase", table "dbo.JohnsChildTable", column 'JohnsParentTableId'. The statement has been terminated. 

La mia domanda quindi è cosa mi manca esattamente per garantire che Entity Framework sappia che deve eliminare le righe “JohnsChildTable” prima di eliminare il genitore?

Dipende se si desidera che Entity Framework elimini i figli o che il database si occupi di esso.

Se vuoi che EF generi un’istruzione delete per tutti i bambini ed esegua quelli prima di eliminare il genitore, devi prima caricare tutti i bambini in memoria.

Quindi non puoi semplicemente creare un’ quadro “fittizia” con solo la chiave popolata e aspettarti che i bambini vengano cancellati.

Affinché funzioni, devi lasciare che il database gestisca la cancellazione.

La chiave esterna sulla tabella figlio dovrebbe tuttavia abilitare le eliminazioni a cascata. In questo caso, Entity Framework crea semplicemente un’istruzione delete per il genitore e il database sa anche di eliminare i figli.

Entity Framework crea una chiave esterna con eliminazioni a cascata abilitate di default, se la relazione è richiesta, come nel tuo caso. (La chiave esterna non può essere nulla).

Se hai creato il database da solo, devi ricordarti di abilitarlo.

Penso che sia meglio ignorare il metodo OnModelCreating e aggiungere questo codice.

 protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity() .HasRequired(t=>t.JohnsParentTable) .WithMany(t=>t.JohnsChildTables) .HasForeignKey(d=>d.JohnsParentTableId) .WillCascadeOnDelete(true); base.OnModelCreating(modelBuilder); } 

Ho impostato su true WillCascadeOnDelete (true)

In Visual Studio, apri il file del modello. Fare clic con il tasto destro sulla relazione Parent-Child e selezionare Proprietà.

Nella proprietà End1 OnDelete il valore sarà probabilmente None. L’altra opzione è Cascade; impostalo su quello Ora l’eliminazione di un genitore ridurrà in cascata le eliminazioni ai suoi figli.

inserisci la descrizione dell'immagine qui

Saluti –