Jeg formoder, at dette er problemet i slutningen af metoden:
this.connectionPool.Putback(sqlConnection);
Du tager kun to elementer fra iteratoren - så du fuldfører aldrig while
loop, medmindre der faktisk kun er én værdi returneret fra læseren. Nu bruger du LINQ, som automatisk kalder Dispose()
på iteratoren, så du using
erklæringen vil stadig bortskaffe læseren - men du sætter ikke forbindelsen tilbage i puljen. Hvis du gør det i en finally
blokerer, jeg tror, du bliver okay:
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);
}
Eller ideelt set, hvis din forbindelsespulje er din egen implementering, lav Take
returnere noget, der implementerer IDisposable
og returnerer forbindelsen tilbage til poolen, når den er færdig.
Her er et kort, men komplet program til at demonstrere, hvad der foregår, uden egentlige databaser involveret:
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));
}
}
Som skrevet - modellering af situationen med læseren kun at finde to værdier - outputtet er:
Take from the pool
DummyReader.Dispose()
0,1
Bemærk at læseren er disponeret, men vi kommer aldrig så langt som at returnere noget fra poolen. Hvis du ændrer Main
at modellere situationen, hvor læseren kun har én værdi, som denne:
var data = FindValues(1).Take(2).ToArray();
Så kommer vi hele vejen igennem while
loop, så output ændres:
Take from the pool
DummyReader.Dispose()
Put back in the pool
0
Jeg foreslår, at du kopierer mit program og eksperimenterer med det. Sørg for at du forstår alt om, hvad der foregår... så kan du anvende det på din egen kode. Du vil måske læse min artikel om detaljer for implementering af iteratorblok også.