Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

Sudah ada DataReader yang terbuka... padahal belum

Saya menduga ini masalahnya, di akhir metode:

this.connectionPool.Putback(sqlConnection);

Anda hanya mengambil dua elemen dari iterator - jadi Anda tidak pernah menyelesaikan while loop kecuali sebenarnya hanya ada satu nilai yang dikembalikan dari pembaca. Sekarang Anda menggunakan LINQ, yang secara otomatis akan memanggil Dispose() pada iterator, jadi using pernyataan akan tetap membuang pembaca - tetapi Anda tidak mengembalikan koneksi ke kumpulan. Jika Anda melakukannya dalam finally blokir, saya pikir Anda akan baik-baik saja:

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

Atau idealnya, jika kumpulan koneksi Anda adalah implementasi Anda sendiri, buat Take kembalikan sesuatu yang mengimplementasikan IDisposable dan mengembalikan koneksi kembali ke kumpulan setelah selesai.

Berikut adalah program singkat namun lengkap untuk mendemonstrasikan apa yang terjadi, tanpa melibatkan basis data aktual:

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

Seperti yang tertulis - memodelkan situasi dengan pembaca hanya menemukan dua nilai - outputnya adalah:

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

Perhatikan bahwa pembaca dibuang, tetapi kami tidak pernah sampai sejauh mengembalikan apa pun dari kumpulan. Jika Anda mengubah Main untuk memodelkan situasi di mana pembaca hanya memiliki satu nilai, seperti ini:

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

Kemudian kita mendapatkan semua jalan melalui while loop, sehingga output berubah:

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

Saya sarankan Anda menyalin program saya dan bereksperimen dengannya. Pastikan Anda memahami segala sesuatu tentang apa yang terjadi... kemudian Anda dapat menerapkannya ke kode Anda sendiri. Anda mungkin ingin membaca artikel saya di detail penerapan blok iterator juga.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. java Hibernasi kueri yang tidak perlu pada objek yang terpisah

  2. cara menggabungkan dan mengurutkan dua tabel berbeda di Mysql

  3. Koneksi MySQL tidak akan ditutup

  4. Aplikasi Laravel di Azure:Akses ditolak untuk pengguna 'azure'@'localhost'

  5. MySQL memilih baris di mana tanggal bukan di antara tanggal