2009-05-05 10 views
61

L'oggetto contesto Entity Framework implementa un metodo Dispose() che "Libera le risorse utilizzate dal contesto dell'oggetto". Cosa fa veramente? Potrebbe essere una brutta cosa metterlo sempre in una frase using {}? L'ho visto usato sia con che senza l'istruzione using.Il contesto di Entity Framework deve essere inserito nell'istruzione?

Sto specificatamente intenzione di utilizzare il contesto EF all'interno di un metodo di servizio WCF, creare il contesto, fare un po 'di linq e restituire la risposta.

EDIT: Sembra che io non sono l'unico a chiedersi su questo. Un'altra domanda è cosa sta realmente accadendo all'interno del metodo Dispose(). Alcuni dicono che chiude le connessioni e alcuni articoli non dicono. Qual è l'accordo?

risposta

32

Se si crea un contesto, è necessario smaltirlo in seguito. Se si deve usare l'istruzione using dipende dalla durata del contesto.

  1. Se si crea il contesto in un metodo e utilizzarlo solo all'interno di questo metodo, si dovrebbe davvero utilizzare l'istruzione using perché ti dà la gestione delle eccezioni, senza alcun codice aggiuntivo.

  2. Se si utilizza il contesto per un periodo più lungo - che è il tempo di vita non è vincolata da tempo di esecuzione di un metodo - non è possibile utilizzare l'istruzione using e devi chiamare Dispose() se stessi e fare in modo che hai sempre chiamalo.

Cosa fa Dispose() per un contesto di oggetto?

Non ho guardato il codice, ma almeno lo spiego per chiudere la connessione al database con i suoi socket sottostanti o qualsiasi altra risorsa utilizzata dal meccanismo di trasporto.

1

Sempre, se si istanzia una classe che implementa IDisposable, allora si è responsabili di chiamare Dispose su di esso. In tutti i casi tranne uno, questo significa un utilizzando il blocco.

+2

Vero, ma la domanda è ciò che il metodo Dispose() relly fa per il contesto EF . Sembra che non sia veramente importante da quello che posso trovare sull'argomento! –

+1

"Responsible" ... Non è solo per codice non gestito? – ullmark

+3

Grazie per aver chiesto questa domanda. Come risultato, ho scoperto che tutte le chiamate di Dispose che temo di dimenticare nella nostra applicazione potrebbero non essere così critiche come temevo (leggendo http://lee.hdgreetings.com/2008/06/linq-datacontex. html). – BlueMonkMN

4

Dal momento che non si sa quando il garbage collector dispone di un elemento, è sempre bene per avvolgere gli oggetti che implementano IDisposable in un utilizzando blocco se si sa quando hai finito con esso.

1

Quando si smaltisce, ObjectContext dispone di altri oggetti di proprietà.

Includere elementi come EntityConnection che avvolge la connessione al database effettivo, ovvero un SqlConnection.

Quindi, se "SqlConnection è aperto, verrà chiuso quando si smaltisce ObjectContext.

4

Per Progamming Entity Framework: "È possibile disporre in modo esplicito dell'oggetto ObjectContext o attendere che il garbage collector esegua il lavoro."

Quindi, in breve, mentre l'istruzione using non è richiesta, è consigliabile se si è a conoscenza dell'utilizzo di ObjectContext poiché la risorsa viene liberata immediatamente anziché attendere la garbage collection.

+0

GC è stato creato per ** non ** smaltire le cose in modo esplicito. È necessario (se possibile) disporre di oggetti che fanno riferimento a risorse non gestite. Quindi la vera domanda qui - il contesto EF fa riferimento a una risorsa non gestita? Se no, non dovresti smaltirlo ... –

0

ho notato (anche se in una sola applicazione) che lo smaltimento esplicito stava causando filo abortire eccezioni in mscorlib che vengono catturati prima che il codice dell'applicazione, ma almeno nel mio caso con un conseguente calo di prestazioni evidente. Non ho fatto alcuna ricerca significativa sulla questione, ma probabilmente qualcosa che vale la pena prendere in considerazione se lo fai. Guarda il tuo output DEBUG per vedere se stai ottenendo lo stesso risultato.

0

Se Dispose chiude la connessione a DB, è una cattiva idea chiamarlo. Ad esempio, le connessioni ADO.NET sono nel pool di connessioni e non vengono mai chiuse prima del timeout o del pool di applicazioni.

1

ho davvero provato questa cosa sia ADO.net e EF v.6 e guardato le connessioni nella tabella SQL

select * from sys.dm_exec_connections 

metodi da testare si presentava così:

1) ADO.net con utilizzando

using(var Connection = new SqlConnection(conString)) 
    { 
    using (var command = new SqlCommand(queryString, Connection)) 
    {  
     Connection.Open(); 
     command.ExecuteNonQueryReader(); 
     throw new Exception() // Connections were closed after unit-test had been 
     //finished. Expected behaviour 
    } 
    } 

2) ADO.net withour utilizzando

var Connection = new SqlConnection(conString); 
using (var command = new SqlCommand(queryString, Connection)) 
{ 
    Connection.Open(); 
    command.ExecuteNonQueryReader(); 
    throw new Exception() // Connections were NOT closed after unit-test had been finished 

    finished. I closed them manually via SQL. Expected behaviour 
    } 

1) EF con utilizzo.

using (var ctx = new TestDBContext()) 
    { 
     ctx.Items.Add(item); 
     ctx.SaveChanges(); 
     throw new Exception() // Connections were closed, as expected. 

    } 

2) EF senza usare

var ctx = new TestDBContext();    
ctx.Items.Add(item); 
ctx.SaveChanges(); 
throw new Exception() // Connections WERE successfully closed, as NOT expected. 

Non so perché è così, ma EF connessioni automaticamente chiuso. Inoltre, tutti i modelli di repository e UnitOfWork che utilizzano EF non utilizzano l'utilizzo. È molto strano per me, perché DBContext è di tipo Usa e getta, ma è un dato di fatto.

Forse in Microsoft hanno fatto qualcosa di nuovo per la gestione?

+0

In realtà è semplice: se non apri manualmente la connessione (come 'ctx.Database.Connection.Open();') EF6 prenditi cura di esso e gestirà l'apertura/chiusura con ogni query (vedi pool di connessioni ADO perché questa non è una cattiva idea). Ma se lo apri manualmente, EF6 considererà che sai cosa stai facendo e lascialo aperto. –

+0

Non hai risposto all'argomento del mio commento. Non esiste una connessione aperta manualmente per EF. Tutto colla nei commenti nel codice –

3

EF5 e prima versione

using { ... 
      // connecction open here. 

      ... 
      context.Blogs.Add(blog); 
      context.SaveChanges(); // query etc now opens and immediately closes 

      ... 
      context.Blogs.Add(blog); 
      context.SaveChanges(); // query etc now opens and immediately closes 
    } 

EF6 e dopo la versione

using { 
     // connecction open here. 

     ... 
     context.Blogs.Add(blog); 
     context.SaveChanges(); 

     // The underlying store connection remains open for the next operation 

     ... 
     context.Blogs.Add(blog); 
     context.SaveChanges(); 

     // The underlying store connection is still open 

    } // The context is disposed – so now the underlying store connection is closed 

Riferimento: http://msdn.microsoft.com/en-us/data/dn456849#open5

+1

Questo è sbagliato o fuorviante. L'articolo a cui si fa riferimento riguarda la gestione della connessione, circa la chiamata MANUALMENTE 'connection.Open()' (e non lo si traduce nel codice di esempio), non di 'Dispose()'. Se non chiamate 'connection.Open()' manualmente (lo lasciate alla gestione della connessione EF), la connessione è chiusa al vostro // La connessione all'archivio sottostante è ancora aperta. Niente a che vedere con la domanda OP. –

Problemi correlati