Quand faut-il appeler DbContext.dispose()
avec un cadre d'entité?
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;
}
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;
}
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;
}
En fait, c’est deux questions en une:
Dispose()
d'un contexte?Réponses:
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) Dispose
sans danger .
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.
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.
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é.
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;
}
}