Ik vermoed dat dit het probleem is, aan het einde van de methode:
this.connectionPool.Putback(sqlConnection);
Je neemt alleen twee elementen uit de iterator - dus je voltooit nooit de while
lus tenzij er eigenlijk maar één waarde wordt geretourneerd door de lezer. Nu gebruik je LINQ, dat automatisch Dispose()
. aanroept op de iterator, dus uw using
statement zal nog steeds de lezer weggooien - maar je zet de verbinding niet terug in de pool. Als je dat doet in een finally
blok, ik denk dat het wel goed komt:
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);
}
Of idealiter, als uw verbindingspool uw eigen implementatie is, maakt u Take
iets teruggeven dat IDisposable
implementeert en stuurt de verbinding terug naar de pool als het klaar is.
Hier is een kort maar compleet programma om te demonstreren wat er aan de hand is, zonder dat er daadwerkelijke databases bij betrokken zijn:
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));
}
}
Zoals geschreven - modellering van de situatie waarbij de lezer slechts twee waarden vindt - is de uitvoer:
Take from the pool
DummyReader.Dispose()
0,1
Merk op dat de lezer is weggegooid, maar we komen nooit zo ver als iets teruggeven uit het zwembad. Als u Main
wijzigt om de situatie te modelleren waarin de lezer slechts één waarde heeft, zoals dit:
var data = FindValues(1).Take(2).ToArray();
Dan komen we helemaal door de while
loop, zodat de uitvoer verandert:
Take from the pool
DummyReader.Dispose()
Put back in the pool
0
Ik stel voor dat je mijn programma kopieert en ermee experimenteert. Zorg ervoor dat je alles begrijpt over wat er aan de hand is... dan kun je het toepassen op je eigen code. Misschien wil je mijn artikel lezen over implementatiedetails van iteratorblok ook.