メソッドの最後に、これが問題だと思います:
this.connectionPool.Putback(sqlConnection);
あなたは取っている イテレータからの2つの要素-したがって、while
を完了することはありません リーダーから返される値が実際に1つだけでない限り、ループします。現在、LINQを使用しています。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));
}
}
書かれているように-読者が2つの値を見つけるだけで状況をモデル化する-出力は次のとおりです:
Take from the pool
DummyReader.Dispose()
0,1
リーダーは破棄されますが、プールから何かを返すことはできません。 Main
を変更した場合 次のように、リーダーの値が1つしかない状況をモデル化するには:
var data = FindValues(1).Take(2).ToArray();
次に、while
を最後まで実行します。 ループするため、出力が変化します:
Take from the pool
DummyReader.Dispose()
Put back in the pool
0
私のプログラムをコピーして試してみることをお勧めします。何が起こっているかについてすべてを理解していることを確認してください...それからあなたはそれをあなた自身のコードに適用することができます。 イテレータブロックの実装の詳細 に関する私の記事を読むことをお勧めします。