Mysql
 sql >> база данни >  >> RDS >> Mysql

Вече има отворен DataReader... въпреки че не е

Подозирам, че това е проблемът в края на метода:

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

Предлагам ви да копирате моята програма и да експериментирате с нея. Уверете се, че разбирате всичко за това, което се случва... след това можете да го приложите към собствения си код. Може да искате да прочетете статията ми за подробности за внедряването на итераторния блок също.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. SQL за проверка дали базата данни е празна (няма таблици)

  2. Преоформете таблицата в MySQL или R

  3. Връщане на резултати от заявка въз основа на днешна дата в SQL (MySQL), част 2

  4. изтичане на памет в php скрипт

  5. Топ 5 инструмента за наблюдение на MySQL