2013-07-25 2 views
22

Quando sto cercando di cancellare una collezione (chiamando .Clear) ottengo la seguente eccezione:Una relazione è in stato cancellato

Si è verificato un errore durante il salvataggio entità che non espongono le proprietà di chiave esterna per i loro rapporti . La proprietà EntityEntries restituirà null poiché una singola entità non può essere identificata come origine dell'eccezione. La gestione delle eccezioni durante il salvataggio può essere semplificata esponendo le proprietà delle chiavi esterne nei tipi di entità. Vedi l'InnerException per i dettagli.

L'eccezione interna è:

una relazione nelle 'User_Availability' AssociationSet è nello stato 'eliminata'. Dati i vincoli di molteplicità, anche "User_Availability_Target" corrispondente deve essere nello stato "Eliminato".

utente è simile al seguente:

.... 
ICollection<Availability> Availability { get; set; } 

disponibilità assomiglia a questo:

int ID { get; set; } 
User User { get; set; } 
DateTime Start { get; set; 
DateTime End { get; set; } 

configurazione è la seguente:

HasMany(x => x.Availability).WithRequired(x => x.User); 
HasRequired(x => x.User).WithMany(x => x.Availability); 

Il codice che causa il problema è:

user.Availability.Clear(); 

Ho esaminato altre alternative come utilizzare DbSet per rimuovere gli elementi, ma non credo che il mio codice sarà altrettanto pulito. C'è un modo per ottenere ciò cancellando la collezione?

risposta

22

L'unico modo per cui sono a conoscenza di farlo funzionare è definire la relazione come identifying relationship. Sarebbe necessario introdurre la chiave esterna da Availability a User come chiave esterna nel modello ...

public int ID { get; set; } 
public int UserID { get; set; } 
public User User { get; set; } 

... e renderlo parte della chiave primaria:

modelBuilder.Entity<User>() 
    .HasKey(u => new { u.ID, u.UserID }); 

Puoi estendere la mappatura di includere questa chiave esterna (solo per essere esplicito, non è necessario perché EF lo riconoscerà per convenzione):

modelBuilder.Entity<User>() 
    .HasRequired(x => x.User) 
    .WithMany(x => x.Availability) 
    .HasForeignKey(x => x.UserID); 

(BTW: è necessario config ure la relazione solo da un lato. Non è necessario avere entrambi questi mapping nella domanda.)

Ora è possibile cancellare la raccolta con user.Availability.Clear(); e le entità Availability verranno eliminate dal database.

+1

Grazie Slauma, ho risolto il mio problema. – Sam

+0

Grazie per aver postato questo! Quando eseguo un aggiornamento sull'oggetto figlio, sto ricevendo più istruzioni SET sulla stessa colonna, a causa della proprietà FK e della proprietà di navigazione. C'è un trucco per generare solo una istruzione SET? – Thomas

+0

@Thomas: non ne ho idea. La generazione SQL è praticamente nella mano di EF e difficile da controllare. Sono davvero sorpreso che tu abbia due espressioni SET per la stessa colonna FK. EF dovrebbe sapere che la proprietà FK e il nav. la proprietà rappresenta la stessa colonna e relazione FK. – Slauma

0

C'è un trucco. È possibile eliminare le entità senza utilizzare DbSet speciale:

(this.dataContext as IObjectContextAdapter).ObjectContext.DeleteObject(entity); 

esegue questo per ogni elemento nella collezione disponibilità prima di cancellarlo. Non hai bisogno di "identificare le relazioni" per questo modo.