2015-06-09 18 views
13

Qui è la mia situazione:Entity Framework: Perché il metodo WillCascadeOnDelete() viene ignorato?

public abstract class Article 
{ 
    [key] 
    public Guid Guid { get; set;} 

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

public class Download : Article 
{ 
    ... 
} 

public abstract class Category : Article 
{ 
    ... 
} 

public class DownloadCategory : Category 
{ 
    .... 
} 

E poi dovrei avere una relazione molti-a-molti relazione tra Scaricare e DownloadCategory come questo:

public class DownloadInCategory 
{ 
    [Key, Column(Order = 1), Required] 
    [ForeignKey("Download")] 
    Public Guid DownloadGuid { get; set; } 

    Public Download Download { get; set; } 

    [Key, Column(Order = 2), Required] 
    [ForeignKey("Category")] 
    Public Guid CategoryGuid { get; set; } 

    Public DownloadCategory Category { get; set; } 
} 

Quando chiamo Add-Migration la migrazione creata per DownloadInCategory entità è:

CreateTable("dbo.DownloadInCategories", 
c => new 
{ 
    CategoryGuid = c.Guid(nullable: false), 
    DownloadGuid = c.Guid(nullable: false), 
}) 
.PrimaryKey(t => new { t.CategoryGuid, t.DownloadGuid }) 
.ForeignKey("dbo.DownloadCategories", t => t.CategoryGuid) 
.ForeignKey("dbo.Downloads", t => t.DownloadGuid, cascadeDelete: true) 
.Index(t => t.CategoryGuid) 
.Index(t => t.DownloadGuid); 

Ecco la mia domanda: Come si notic e non aggiunge cascadeDelete: true a una delle chiavi esterne. PERCHÉ!!!!!!?????

Devo dire che non ho modificato nessuna delle convenzioni modelbuilder. Quindi questo schema dovrebbe aggiungere Casscade all'eliminazione nella migrazione. Le mie proprietà sono [Required].

Cosa sto sbagliando?

Grazie ragazzi ...

Aggiornamento: Si prega di notare che Article e Category classi sono abstract. Ho cambiato le classi sopra

Aggiornamento 2: Non v'è alcun problema di logica con questo schema. Se modifico la migrazione manualmente, aggiornerà il database normalmente.

Update 3: My EF Inheritance Metodologia è TPC

Update 4: Dopo alcune indagini e le prove Sembra problema è inheritanced da Category. Quando DownloadCategory è ereditato da Category, Cascade non viene distribuito. ma quando I Inherit DownloadCategory direttamente dall'articolo, viene distribuito Cascade. Ma perché ancora?

+0

Se si modifica la migrazione funziona manualmente bene, questo è più di una questione teorica sul perché a cascata di eliminazione non è deducibile? – jjj

+5

@jjj No. Questo è completamente pratico dal mio punto di vista. La modifica manuale della migrazione non è affatto una buona pratica. In progetti più grandi come quello a cui sto lavorando, una cosa del genere aggiunge ulteriori considerazioni alla manutenzione e allo sviluppo di nuove funzionalità del progetto. Penso che modificare manualmente la migrazione sia sbagliato. e la migrazione dovrebbe corrispondere allo schema dei modelli. – abzarak

+4

Suppongo che sarebbe vero in un mondo ideale in cui le convenzioni built-in erano perfette. Puoi scavare nel codice sorgente per capire perché questo è successo in questo caso, ma suppongo che sia il risultato di una scorciatoia per evitare i cicli. – jjj

risposta

3

vorrei che questo sia perché:

DownloadCategory : Category : Article 

vs

Download : Article 

La chiave è sulla classe articolo. Più Category è possibile utilizzare lo stesso Category, in modo che non si sovrapponga all'eliminazione poiché ciò potrebbe lasciare altri errori DownloadCategory corretti.

Questo è probabilmente un difetto di Entity Framework, dal momento che si utilizza TPC, questo dovrebbe essere dedotto. Dai un'occhiata a this article per soluzioni alternative.

particolare queste sezioni:

Nella maggior parte dei casi Entity Framework può inferire quale tipo è la dipendente e che è il principale in un rapporto. Tuttavia, quando sono richieste entrambe le estremità della relazione o entrambi i lati sono opzionali , Entity Framework non è in grado di identificare il dipendente e il principal. Quando sono richieste entrambe le estremità della relazione, utilizzare WithRequiredPrincipal o WithRequiredDependent dopo il metodo HasRequired. Quando entrambe le estremità della relazione sono facoltative, utilizzare WithOptionalPrincipal o WithOptionalDependent dopo il metodo HasOptional.

// Configure the primary key for the OfficeAssignment 
modelBuilder.Entity<OfficeAssignment>() 
    .HasKey(t => t.InstructorID); 

modelBuilder.Entity<Instructor>() 
    .HasRequired(t => t.OfficeAssignment) 
    .WithRequiredPrincipal(t => t.Instructor); 

È possibile configurare a cascata eliminare su un rapporto utilizzando il metodo WillCascadeOnDelete. Se una chiave esterna sull'entità dipendente non è annullabile, Code First imposta l'eliminazione a cascata sulla relazione . Se una chiave esterna sull'entità dipendente è nullable, il codice First First non imposta l'eliminazione a cascata sulla relazione e quando l'entità viene cancellata, la chiave esterna verrà impostata su null.

È possibile rimuovere questi cascata cancellare convenzioni utilizzando:

modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>() 
modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>() 

Il codice seguente configura il rapporto deve essere richiesto e poi disabilita a cascata cancellare.

modelBuilder.Entity<Course>() 
    .HasRequired(t => t.Department) 
    .WithMany(t => t.Courses) 
    .HasForeignKey(d => d.DepartmentID) 
    .WillCascadeOnDelete(false); 
+0

grazie. Le categorie di articolo e categoria sono astratte. Sto aggiornando la mia domanda menzionando che sono astratti. – abzarak

+0

Non sono sicuro di come questo faccia la differenza? –

+0

Se la classe Category è astratta, non ci saranno istanze per Category Directly. E le istanze provengono da DownloadCategory. quindi "Multiple DownloadCategories potrebbe utilizzare la stessa categoria" non ha senso qui ... – abzarak

Problemi correlati