2013-03-27 16 views
42

Quando si dovrebbe chiamare DbContext.dispose() con l'entity framework?Entity Framework e context dispose

  1. È questo metodo immaginario male?

    public static string GetName(string userId) 
    { 
        var context = new DomainDbContext(); 
        var userName = context.UserNameItems.FirstOrDefault(x => x.UserId == userId); 
        context.Dispose(); 
        return userName; 
    } 
    
  2. è meglio?

    public static string GetName(string userId) 
    { 
        string userName; 
        using(var context = new DomainDbContext()) { 
         userName = context.UserNameItems.FirstOrDefault(x => x.UserId == userId); 
         context.Dispose(); 
        } 
        return userName; 
    } 
    
  3. È questo ancora migliore, cioè, si dovrebbe chiamare NON context.Dispose() Quando si utilizzava()?

    public static string GetName(string userId) 
    { 
        string userName; 
        using(var context = new DomainDbContext()) { 
         userName = context.UserNameItems.FirstOrDefault(x => x.UserId == userId); 
        } 
        return userName; 
    } 
    
+12

_should one NOT call context.Dispose() quando si utilizza using() _ è sempre true. È ridondante. –

+0

Grazie per il tuo commento. Quindi context.Dispose() è ridondante, rimuoverlo non avrà alcun effetto? – Sindre

+1

'using' è un implicito' Dispose() ' –

risposta

74

In realtà questo è due domande in una:

  1. Quando dovrei usare Dispose() di un contesto?
  2. Quale dovrebbe essere la durata di vita del mio contesto?

Risposte:

  1. Mai . using è un Dispose() implicito in un blocco try-finally. Un'istruzione separata Dispose può essere persa quando si verifica un'eccezione in precedenza. Inoltre, nella maggior parte dei casi, non chiamare il numero Dispose (implicitamente o esplicitamente) isn't harmful.

  2. Vedere ad es. Entity Framework 4 - lifespan/scope of context in a winform application. In breve: la durata della vita dovrebbe essere "breve", il contesto statico è negativo.


Come alcune persone hanno commentato, un'eccezione a questa regola è quando un contesto fa parte di un componente che implementa IDisposable se stessa e condivide il suo ciclo di vita. In tal caso, chiamare il context.Dispose() nel metodo Dispose del componente.

+0

Questa è la risposta corretta e tutto ciò che devi sapere davvero. Votandolo –

+0

Grazie, Gert Arnold. Leggerò sul modello dell'Unità di lavoro! – Sindre

+1

Hmmm, "Mai" si applica ancora se non stai utilizzando l'istruzione "using" per avvolgere il tuo contesto (riferendosi al caso 1)? – gitsitgo

0

vorrei utilizzare l'opzione 3; utilizzando using() verrà automaticamente distribuito il contesto per voi. L'opzione 2 è cattiva. L'opzione 1 potrebbe anche essere ok ma l'opzione 3 sembra più leggibile.

26

Ho seguito alcuni buoni tutorial per utilizzare EF e non dispongano del contesto.

Ero un po 'curioso e ho notato che anche i ben rispettati Microsoft VIP non dispongono del contesto. Ho trovato che non è necessario disporre il dbContext in condizioni normali.

Se si desiderano ulteriori informazioni, è possibile leggere this blog post che riassume il motivo.

10

Meglio ancora:

public static string GetName(string userId) 
{ 
    using (var context = new DomainDbContext()) { 
     return context.UserNameItems.FirstOrDefault(x => x.UserId == userId); 
    } 
} 

Non c'è bisogno di restituire il risultato al di fuori della portata using; restituiscilo immediatamente e otterrai comunque il comportamento di smaltimento desiderato.

1

È possibile definire il contesto del database come campo di classe e implementare IDisposable. Qualcosa come sotto:

public class MyCoolDBManager : IDisposable 
{ 
    // Define the context here. 
    private DomainDbContext _db; 

    // Constructor. 
    public MyCoolDBManager() 
    { 
     // Create a new instance of the context. 
     _db = new DomainDbContext(); 
    } 

    // Your method. 
    public string GetName(string userId) 
    {   
     string userName = context.UserNameItems.FirstOrDefault(x => x.UserId == userId); 

     return userName; 
    } 

    // Implement dispose method. 
    // NOTE: It is better to follow the Dispose pattern. 
    public void Dispose() 
    { 
     _db.dispose(); 
     _db = null; 
    } 
}