En fait, il ne doit pas nécessairement s'agir d'un IDataReader
.Fermeture d'un IDataReader après que le retour de rendement est terminé
J'ai eu une fonction quelque chose comme ceci:
public IEnumerable<MyClass> GetObjects()
{
IDataReader dr = GetSomeDataReader();
while (dr.Read())
{
yield return new MyClass(dr);
}
CloseDBConnections();
}
Ce fonctionnait très bien jusqu'à ce que je refactorisé comme si:
public IEnumerable<MyClass> GetObjects()
{
IDataReader dr = GetSomeDataReader();
try
{
return ProcessReader(dr);
} finally {
CloseDBConnections();
}
}
public IEnumerable<MyClass> ProcessReader(IDataReader dr)
{
while (dr.Read())
{
yield return new MyClass(dr);
}
}
Cela ne fonctionne pas parce que lorsque le CloseDBConnections()
est exécuté l'énumération n'a pas encore été traité.
Appel .ToList()
sur le retour de GetObjects
est ce qui exécute en fait l'énumération, mais alors la connexion a déjà été détruite et l'IDataReader
échoue.
Dans mon exemple CloseDBConnections
ne peut pas être appelé à partir de la nouvelle fonction ProcessReader
parce que le IDataReader
aurait pu venir d'une autre source (le point entier de refactoring en l'occurrence)
est-il une solution raisonnable pour ce ou dois-je dupliquer le code d'énumération?
J'ai essayé de mettre l'appel à ProcessReader
comme yield return
au lieu de return
, mais cela ne fonctionne pas parce que C# (compréhensible) pense que je suis en train d'ajouter un IEnumerable
au IEnumerable
!
Vous devez exécuter le rappel dans un 'finally'. Sans cela, il ne sera pas exécuté si l'itération se termine tôt (par exemple 'GetObjects(). First()'). – svick
@svick Bon point. – sloth
@DominicKexel Je l'aime. C'est comme ça que je finis par faire beaucoup de choses en Javascript – DJL