Ich habe mir mal einen solchen selbst geschrieben. Allerdings musst du einige Dinge beachten:
a) Alle Connections die du hohlst, musst du auch wieder immer zurückgeben. Sonst blockiert der Verbindungspool alle Threads die neue Verbindungen haben wollen. Timeouts, das die Verbindungen nach der Zeit x freigegeben werden, gibt es nicht.
b) Evtl muss du die Stelle auskommentieren, an der die Datenbankverbindung genullt wird, wenn sie dem Pool wieder übergeben wird. Dann musst du dich aber darum kümmern, dass sie automatisch neu erzeugt wird, wenn die Verbindung mal kaputt gehen sollte. (Die Klasse erzeugt nämlich immer eine neue Verbindung, wenn ein Verbindungsobjekt benötigt wird, was du ja nicht willst)
c) Du solltest es vermeiden, mehrere Verbindungen im selben Thread zu verwenden, wenn das maximale Verbindungslimit zu gering ist. Sonst kannst du das ganze Programm blockieren.
Warscheinlich mag es sinnvoll sein, diese Klasse lediglich als Anregung für einen eingenen Verbindungspool heranzuziehen und selbst einen Verbindungspool für deine Bedürfnisse zu entwickeln.
So und jetzt der Quelltext:
using System;
using System.Collections.Generic;
using System.Text;
using MySQLDriverCS;
using System.Threading;
namespace Chat.Server.Database
{
class MySqlConnectionPool
{
MySQLConnection[] m_Connections = null;
private bool m_HasFreeConnection = false;
private Queue<int> m_FreeConnections = null;
private AutoResetEvent m_Semaphore = null;
private int m_MaxConnections = 5;
private string m_ConnectionString = "Der Connectionstring";
private MySqlConnectionPool()
{
this.m_Connections = new MySQLConnection[this.m_MaxConnections];
this.m_Semaphore = new AutoResetEvent(false);
this.m_FreeConnections = new Queue<int>();
this.m_HasFreeConnection = true;
this.m_HasFreeConnection = true;
for (int i = 0; i < this.m_Connections.Length; i++)
{
this.m_FreeConnections.Enqueue(i);
}
}
private static MySqlConnectionPool m_Instance = null;
public static MySqlConnectionPool Instance
{
get
{
if (m_Instance == null)
m_Instance = new MySqlConnectionPool();
return m_Instance;
}
}
public MySQLConnection Get()
{
if (!this.m_HasFreeConnection)
this.m_Semaphore.WaitOne();
int Index = this.m_FreeConnections.Dequeue();
this.m_Connections[Index] = new MySQLConnection(
this.m_ConnectionString);
this.m_Connections[Index].Open();
this.m_Connections[Index].Database = "chatserver";
if (this.m_FreeConnections.Count == 0)
this.m_HasFreeConnection = false;
return this.m_Connections[Index];
}
public void Return(MySQLConnection connection)
{
try
{
int index = this.IndexOf(connection);
if (this.m_Connections[index].State != System.Data.ConnectionState.Closed)
{
this.m_Connections[index].Close();
this.m_Connections[index].Dispose();
}
this.m_Connections[index] = null;
this.m_FreeConnections.Enqueue(index);
this.m_HasFreeConnection = true;
this.m_Semaphore.Set();
}
catch (Exception)
{
if (connection.State != System.Data.ConnectionState.Closed)
{
connection.Close();
connection.Dispose();
connection = null;
}
throw new Exception("Fehler: Die Datenbankverbindung existiert nicht in der Datenbankverbindungsliste");
}
}
private int IndexOf(MySQLConnection con)
{
for (int i = 0; i < this.m_Connections.Length; i++)
{
if (this.m_Connections[i] == con)
{
return i;
}
}
throw new Exception("Das angegebene Element wurde nicht gefunden");
}
}
}
Bearbeitet:
Hier ist noch ein kleines Beispiel, wie die Klasse zu verwenden ist:
MySQLConnection con = null;
try
{
con = MySqlConnectionPool.Instance.Get();
MySQLCommand com = con.CreateCommand();
com.CommandText = "DeinSQL";
//Hier kannst du dann deinen DataReader/etc ausführen....
}
catch (Exception ex)
{
Console.WriteLine(ex.Message, ex.StackTrace);
}
finally
{
if(con != null)
MySqlConnectionPool.Instance.Return(con);
}