web-dev-qa-db-fra.com

Entity Framework et appel à context.dispose ()

Quand faut-il appeler DbContext.dispose() avec un cadre d'entité?

  1. Est-ce que cette méthode imaginaire est mauvaise?

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

    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. Est-ce encore mieux, c’est-à-dire qu’il ne faut PAS appeler context.Dispose () lorsqu’on utilise using ()?

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

En fait, c’est deux questions en une:

  1. Quand devrais-je Dispose() d'un contexte?
  2. Quelle devrait être la durée de vie de mon contexte?

Réponses:

  1. Jamais  1. using est une Dispose() implicite dans un bloc try-finally. Une instruction séparée Dispose peut être manquée lorsqu'une exception se produit plus tôt. De plus, dans la plupart des cas courants, ne pas appeler du tout (implicitement ou explicitement) Disposesans danger .

  2. Voir par exemple Entity Framework 4 - durée de vie/étendue du contexte dans une application Winform . En bref: la durée de vie doit être "courte", le contexte statique est mauvais.


1 Comme certaines personnes l'ont commenté, une exception à cette règle est lorsqu'un contexte fait partie d'un composant qui implémente IDisposable lui-même et partage son cycle de vie. Dans ce cas, vous appelleriez context.Dispose() dans la méthode Dispose du composant.

95
Gert Arnold

J'ai suivi de bons tutoriels pour utiliser EF et ils ne disposent pas du contexte.

J'étais un peu curieux à ce sujet et j'ai remarqué que même le très respecté Microsoft VIP ne dispose pas du contexte. J'ai trouvé que vous ne possédiez pas de disposer de dbContext en situation normale.

Si vous voulez plus d'informations, vous pouvez lire cet article de blog qui résume pourquoi.

36
Daniel

Mieux encore:

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

Pas besoin de retourner le résultat de l'extérieur de la portée using; retournez-le immédiatement et vous aurez toujours le comportement d'élimination souhaité.

13
Todd Menier

Vous pouvez définir le contexte de votre base de données en tant que champ de classe et implémenter IDisposable. Quelque chose comme ci-dessous:

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 = _db.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;
    }
}
3
A-Sharabiani