Podejrzewam, że to jest problem, na końcu metody:
this.connectionPool.Putback(sqlConnection);
Tylko zabierasz dwa elementy z iteratora - więc nigdy nie kończysz while
pętla, chyba że w rzeczywistości zwrócona jest tylko jedna wartość z czytnika. Teraz używasz LINQ, który automatycznie wywoła Dispose()
na iteratorze, więc Twoje using
oświadczenie nadal będzie usuwać czytnik - ale nie przywracasz połączenia z powrotem do puli. Jeśli zrobisz to w finally
blok, myślę, że wszystko będzie dobrze:
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);
}
Lub najlepiej, jeśli twoja pula połączeń jest twoją własną implementacją, wykonaj Take
zwrócić coś, co implementuje IDisposable
i po zakończeniu zwraca połączenie z powrotem do puli.
Oto krótki, ale kompletny program pokazujący, co się dzieje, bez żadnych rzeczywistych baz danych:
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));
}
}
Jak napisano - modelowanie sytuacji z czytnikiem znajdowania tylko dwóch wartości - wynik to:
Take from the pool
DummyReader.Dispose()
0,1
Zwróć uwagę, że czytnik jest unieszkodliwiony, ale nigdy nie dochodzimy do zwrócenia czegokolwiek z puli. Jeśli zmienisz Main
do modelowania sytuacji, w której czytnik ma tylko jedną wartość, na przykład:
var data = FindValues(1).Take(2).ToArray();
Następnie przechodzimy przez cały while
pętla, więc wyjście się zmienia:
Take from the pool
DummyReader.Dispose()
Put back in the pool
0
Proponuję skopiować mój program i poeksperymentować z nim. Upewnij się, że rozumiesz wszystko o tym, co się dzieje... wtedy możesz zastosować to do własnego kodu. Możesz przeczytać mój artykuł o szczegółach implementacji bloku iteratorów też.