2012-04-26 1 views
8

Utilizzando Entity Framework codice In primo luogo, ho qualcosa di simile:Perché l'impostazione di EntityState su Detached svuota una proprietà di tipo List <T>?

public class Foo 
{ 
    public int Id { get; set; } 

    public List<Bar> Bars { get; set; } 
}  

Foo foo = (from f in ctx.Foos.Include("Bars") where f.Id == 42 select f).Single(); 

// At this point foo.Bars is populated 

ctx.Entry(foo).State = EntityState.Detached; 

// At this point foo.Bars is an empty List 

Perché staccando un oggetto perché è di proprietà public List<string> Bars, che è stato esplicitamente e con successo incluso, per essere svuotato?

Qual è la procedura corretta per staccare un oggetto che può avere molte proprietà?

risposta

9

Il motivo per cui la lista viene svuotata è una combinazione di due regole in Entity Framework:

  1. quando si scollega un oggetto unico questo oggetto stesso si stacca senza gli oggetti tutte le proprietà di navigazione si veda.

  2. Il ObjectContext/DbContext non consente di tenere un oggetto grafico parzialmente collegato al contesto e parzialmente staccato. Anche se questo può accadere come uno stato temporaneo quando si utilizza POCO EF risolverà sempre questo stato temporaneo collegando automaticamente oggetti distaccati nel grafico all'interno di vari metodi (come Add, Attach, impostando lo stato di un'entità, ecc.) O più tardi quando SaveChanges è chiamato.

Ciò significa che quando si scollega l'oggetto principale dal contesto, EF cancella la lista dei figli perché: a) i figli restano attaccati (regola 1) e b) un mix di oggetti unifamiliari e allegati in il grafico non è consentito (regola 2).

Per quanto posso dire, non c'è modo di staccare un grafico oggetto dal contesto mantenendo la struttura ad albero originale. Puoi staccare il genitore e poi i figli uno dopo l'altro. Di conseguenza hai rimosso tutti gli oggetti dell'albero dal contesto ma l'albero è stato distrutto contemporaneamente - ogni proprietà di navigazione è annullata.

Lo scopo principale di separare manualmente le entità è di rilasciarle per la garbage collection in situazioni in cui si hanno limitazioni di risorse di memoria e non si desidera e devono contenere una quantità enorme di oggetti nel contesto. A questo scopo non ha importanza che la struttura del grafico sia distrutta.

Non so perché è necessario staccare gli oggetti dal contesto. Tuttavia, tieni presente che esiste anche l'opzione per caricare entità dal database senza collegarle al contesto, ad esempio utilizzando AsNoTracking().

Un'altra risposta circa il problema con alcuni riferimenti a documentazione MSDN è qui: https://stackoverflow.com/a/7693732/270591

+0

Il DbContext esce dallo scope molto tempo prima che il mio scopo è mai smaltito. Il caricamento del mio oggetto con 'AsNoTracking()' permetterà a DbContext di essere raccolto, o il mio oggetto manterrà ancora un riferimento ad esso? Questa è la mia principale preoccupazione. –

+0

@EricJ .: Stai utilizzando il codice EF per primo, quindi le tue entità sono POCO. Se non si utilizza il caricamento lazy (e sembra che non lo si faccia perché 'Foo.Bars' non è' virtual'), le entità non sono proxy e non hanno alcun riferimento al contesto. Quindi, la risposta è sì, il contesto sarà garbage collection anche se si detiene ancora un riferimento alla propria entità. – Slauma

+0

Se le entità sono proxy, il contesto non sarà eliminato prima che le entità siano state eliminate? –