2012-04-12 7 views
13

Utilizzo dell'approccio Code-First di Entity Framework.In quale modo le eliminazioni a cascata avvengono in una relazione uno-a-molti?

Supponiamo che io ho due classi di entità:

[Table("Objects")] 
public class DbObject : IValidatableObject 
{ 
    public long Id { get; set; } 

    public string Name { get; set; } 
    public string Description { get; set; } 

    public virtual ICollection<DbObjectProperty> Properties { get; set; } 
} 

[Table("ObjectProperties")] 
public class DbObjectProperty 
{ 
    public long Id { get; set; } 

    public string Name { get; set; } 
    public string Value { get; set; } 

    [Display(Name = "Object"), UIHint("Object")] 
    public long ObjectId { get; set; } 
    public virtual DbObject Object { get; set; } 
} 

punti da notare qui:

  • DbObject ha solo una proprietà di navigazione, ma nessuna colonna con una chiave esterna
  • DbObjectProperty ha una navigazione Proprietà e una colonna corrispondente con una chiave esterna
  • I t dovrebbe essere ovvio che se elimino un oggetto, voglio che le sue proprietà vadano con esso, ma se elimino una singola proprietà, non voglio che l'intero oggetto scompaia.

Nel metodo OnModelCreating per il contesto DB, fino ad ora ho avuto la seguente per definire la relazione:

modelBuilder.Entity<DbObjectProperty>() 
    .HasRequired(op => op.Object) 
    .WithMany(obj => obj.Properties) 
    .HasForeignKey(op => op.ObjectId) 
    .WillCascadeOnDelete(false); 

Naturalmente, questo significa che non si verifichino le eliminazioni in cascata. La mia domanda è: se cambio questo a true, fa quello che voglio? Ricorda che se elimino un oggetto, voglio che le sue proprietà vadano con esso, ma se elimino una singola proprietà, non voglio che l'intero oggetto scompaia.

Il codice di migrazione generato automaticamente a questo cambiamento (da false a true) è questo:

DropForeignKey("ObjectProperties", "ObjectId", "Objects"); 
DropIndex("ObjectProperties", new[] { "ObjectId" }); 
AddForeignKey("ObjectProperties", "ObjectId", "Objects", "Id", cascadeDelete: true); 
CreateIndex("ObjectProperties", "ObjectId"); 

Sono preoccupato che questo sembra implicare che l'eliminazione di un immobile cancellerà il suo oggetto associato. Sara?

risposta

13

La direzione di eliminazione in cascata di una relazione nel database è definita da quale è il principal (tabella della chiave primaria/unica) e qual è la dipendente (tabella della chiave esterna) di questa relazione.

Quindi, se si elimina il principal, vengono eliminati anche tutti i dipendenti che hanno un valore di chiave esterna corrispondente al valore chiave principale/univoco di quell'entità. Non c'è eliminazione a cascata nella direzione da dipendente a principale.

Nel tuo caso il principale è DbObject e il dipendente è DbObjectProperty perché è l'entità/tabella con la chiave esterna.

Sarebbe raramente senso avere una cascata elimina il contrario - soprattutto in x-a-molti: se si elimina un dipendente (DbObjectProperty) e il principale (DbObject) verrebbero eliminati automaticamente, una chiave esterna il vincolo verrebbe violato se c'è un altro dipendente che si riferisce al principio che verrà cancellato.

Non devi preoccuparti.

+0

[Grazie!] (Http://meta.stackexchange.com/questions/700/) – Timwi

+0

La regola empirica è, con eliminazione a cascata, se l'eliminazione di un record interrompe la chiave esterna da un altro record, quel record dipendente viene eliminato pure. – orad

+0

Quindi 'modelBuilder.Entity () .HasMany (p => p.Children) .WithOne (c => c.Parent)' è lo stesso di 'modelBuilder.Entity () .HasOne (c => c.Parent) .WithMany (p => p.Children) '(specificano la stessa relazione)? –