sql >> Database teknologi >  >> RDS >> Mysql

Der er allerede en åben DataReader ... selvom den ikke er det

Jeg formoder, at dette er problemet i slutningen af ​​metoden:

this.connectionPool.Putback(sqlConnection);

Du tager kun to elementer fra iteratoren - så du fuldfører aldrig while loop, medmindre der faktisk kun er én værdi returneret fra læseren. Nu bruger du LINQ, som automatisk kalder Dispose() på iteratoren, så du using erklæringen vil stadig bortskaffe læseren - men du sætter ikke forbindelsen tilbage i puljen. Hvis du gør det i en finally blokerer, jeg tror, ​​du bliver okay:

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

Eller ideelt set, hvis din forbindelsespulje er din egen implementering, lav Take returnere noget, der implementerer IDisposable og returnerer forbindelsen tilbage til poolen, når den er færdig.

Her er et kort, men komplet program til at demonstrere, hvad der foregår, uden egentlige databaser involveret:

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

Som skrevet - modellering af situationen med læseren kun at finde to værdier - outputtet er:

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

Bemærk at læseren er disponeret, men vi kommer aldrig så langt som at returnere noget fra poolen. Hvis du ændrer Main at modellere situationen, hvor læseren kun har én værdi, som denne:

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

Så kommer vi hele vejen igennem while loop, så output ændres:

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

Jeg foreslår, at du kopierer mit program og eksperimenterer med det. Sørg for at du forstår alt om, hvad der foregår... så kan du anvende det på din egen kode. Du vil måske læse min artikel om detaljer for implementering af iteratorblok også.



  1. Sådan finder du duplikerede poster ved at bruge Group by og Having-klausulen i SQL Server - SQL Server / TSQL Tutorial Part 132

  2. Hvor mange kolonner i databasetabel er for mange?

  3. Stabil/gentagelig tilfældig sortering (MySQL, Rails)

  4. PHP mysql søg i flere tabeller ved hjælp af et nøgleord