Je soupçonne que c'est le problème, à la fin de la méthode :
this.connectionPool.Putback(sqlConnection);
Vous ne faites que prendre deux éléments de l'itérateur - vous ne complétez donc jamais le while
boucle à moins qu'il n'y ait en fait qu'une seule valeur renvoyée par le lecteur. Vous utilisez maintenant LINQ, qui appellera automatiquement Dispose()
sur l'itérateur, donc votre using
l'instruction disposera toujours du lecteur - mais vous ne remettez pas la connexion dans le pool. Si vous faites cela dans un finally
bloquer, je pense que tout ira bien :
var sqlConnection = this.connectionPool.Take();
try
{
// Other stuff here...
using (var reader = this.selectWithSourceVectorCommand.ExecuteReader())
{
while (reader.Read())
{
yield return ReaderToVectorTransition(reader);
}
}
}
finally
{
this.connectionPool.Putback(sqlConnection);
}
Ou idéalement, si votre pool de connexions est votre propre implémentation, faites Take
renvoie quelque chose qui implémente IDisposable
et renvoie la connexion au pool quand c'est fait.
Voici un programme court mais complet pour montrer ce qui se passe, sans aucune base de données réelle :
using System;
using System.Collections.Generic;
using System.Linq;
class DummyReader : IDisposable
{
private readonly int limit;
private int count = -1;
public int Count { get { return count; } }
public DummyReader(int limit)
{
this.limit = limit;
}
public bool Read()
{
count++;
return count < limit;
}
public void Dispose()
{
Console.WriteLine("DummyReader.Dispose()");
}
}
class Test
{
static IEnumerable<int> FindValues(int valuesInReader)
{
Console.WriteLine("Take from the pool");
using (var reader = new DummyReader(valuesInReader))
{
while (reader.Read())
{
yield return reader.Count;
}
}
Console.WriteLine("Put back in the pool");
}
static void Main()
{
var data = FindValues(2).Take(2).ToArray();
Console.WriteLine(string.Join(",", data));
}
}
Comme écrit - modélisant la situation avec le lecteur ne trouvant que deux valeurs - la sortie est :
Take from the pool
DummyReader.Dispose()
0,1
Notez que le lecteur est disposé, mais nous n'allons jamais jusqu'à retourner quoi que ce soit de la piscine. Si vous modifiez Main
pour modéliser la situation où le lecteur n'a qu'une seule valeur, comme ceci :
var data = FindValues(1).Take(2).ToArray();
Ensuite, nous parcourons le while
boucle, donc la sortie change :
Take from the pool
DummyReader.Dispose()
Put back in the pool
0
Je vous suggère de copier mon programme et de l'expérimenter. Assurez-vous de tout comprendre de ce qui se passe... vous pourrez ensuite l'appliquer à votre propre code. Vous voudrez peut-être lire mon article sur détails sur l'implémentation du bloc itérateur aussi.