sql >> Databáze >  >> RDS >> Mysql

Již existuje otevřený DataReader ... i když není

Mám podezření, že toto je ten problém, na konci metody:

this.connectionPool.Putback(sqlConnection);

Pouze berete dva prvky z iterátoru - takže nikdy nedokončíte while smyčka, pokud ve skutečnosti není ze čtečky vrácena pouze jedna hodnota. Nyní používáte LINQ, který bude automaticky volat Dispose() na iterátoru, takže using výpis bude stále likvidovat čtečku - ale nevrátíte připojení zpět do fondu. Pokud to uděláte v finally blok, myslím, že budeš v pořádku:

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);
}

Nebo v ideálním případě, pokud je váš fond připojení vaší vlastní implementací, proveďte Take vrátit něco, co implementuje IDisposable a po dokončení vrátí připojení zpět do fondu.

Zde je krátký, ale kompletní program, který demonstruje, co se děje, bez jakýchkoli skutečných databází:

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));
    }
}

Jak je napsáno - modelování situace s tím, že čtenář najde pouze dvě hodnoty - výstup je:

Take from the pool
DummyReader.Dispose()
0,1

Všimněte si, že čtečka je zlikvidována, ale nikdy se nedostaneme tak daleko, abychom něco z bazénu vrátili. Pokud změníte Main k modelování situace, kdy má čtenář pouze jednu hodnotu, takto:

var data = FindValues(1).Take(2).ToArray();

Poté projdeme celou cestu while smyčka, takže se výstup změní:

Take from the pool
DummyReader.Dispose()
Put back in the pool
0

Doporučuji zkopírovat můj program a experimentovat s ním. Ujistěte se, že rozumíte všemu, co se děje... pak to můžete použít na svůj vlastní kód. Možná si budete chtít přečíst můj článek o podrobnostech implementace bloku iterátoru taky.



  1. Mac OS X + Python + Django + MySQL

  2. Jak používat obrázky v Android SQLite, které jsou větší než omezení CursorWindow?

  3. Sloupec doktríny nenalezen:1054 Neznámý sloupec 's.features' v 'seznamu polí''

  4. Jak vytvořit a naplnit tabulku v jediném kroku jako součást operace importu CSV?