Подозирам, че това е проблемът в края на метода:
this.connectionPool.Putback(sqlConnection);
Вие само вземате два елемента от итератора - така че никога не завършвате while
цикъл, освен ако всъщност няма само една стойност, върната от четеца. Сега използвате LINQ, който автоматично ще извика Dispose()
на итератора, така че using
изявлението все още ще изхвърля четеца - но вие не връщате връзката обратно в пула. Ако направите това в finally
блок, мисля, че ще се оправиш:
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);
}
Или в идеалния случай, ако вашият пул за връзки е ваша собствена реализация, направете Take
върне нещо, което имплементира IDisposable
и връща връзката обратно към пула, когато приключи.
Ето кратка, но пълна програма, която демонстрира какво се случва, без никакви реални бази данни:
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));
}
}
Както е написано - моделиране на ситуацията, като четецът намира само две стойности - изходът е:
Take from the pool
DummyReader.Dispose()
0,1
Имайте предвид, че четецът е на разположение, но ние никога не стигаме до връщане на нещо от пула. Ако промените Main
за моделиране на ситуацията, в която четецът има само една стойност, както следва:
var data = FindValues(1).Take(2).ToArray();
След това преминаваме през while
цикъл, така че изходът се променя:
Take from the pool
DummyReader.Dispose()
Put back in the pool
0
Предлагам ви да копирате моята програма и да експериментирате с нея. Уверете се, че разбирате всичко за това, което се случва... след това можете да го приложите към собствения си код. Може да искате да прочетете статията ми за подробности за внедряването на итераторния блок също.