using System; using System.Data; using MySql.Data.MySqlClient; using Hang.Core; namespace Hang.Storage { /// /// Represents a client of a database, /// public sealed class DatabaseClient : IDisposable { #region Fields private uint mHandle; private DateTime mLastActivity; private DatabaseManager mManager; private MySqlConnection mConnection; private MySqlCommand mCommand; internal bool IsBussy = false; #endregion #region Properties /// /// Gets the handle of this database client. /// internal uint Handle { get { return mHandle; } } /// /// Gets whether this database client is anonymous and does not recycle in the database manager. /// internal bool Anonymous { get { return (mHandle == 0); } } /// /// Gets the DateTime object representing the date and time this client has been used for the last time. /// //internal DateTime LastActivity //{ // get { return mLastActivity; } //} /// /// Gets the amount of seconds that this client has been inactive. /// internal int Inactivity { get { return (int)(DateTime.Now - mLastActivity).TotalSeconds; } } /// /// Gets the state of the connection instance. /// internal ConnectionState State { get { return (mConnection != null) ? mConnection.State : ConnectionState.Broken; } } #endregion #region Constructor /// /// Constructs a new database client with a given handle to a given database proxy. /// /// The identifier of this database client as an unsigned 32 bit integer. /// The instance of the DatabaseManager that manages the database proxy of this database client. internal DatabaseClient(uint Handle, DatabaseManager pManager) { if (pManager == null) throw new ArgumentNullException("pManager"); mHandle = Handle; mManager = pManager; mConnection = new MySqlConnection(mManager.CreateConnectionString()); mCommand = mConnection.CreateCommand(); UpdateLastActivity(); } #endregion #region Methods /// /// Attempts to open the database connection. /// internal void Connect() { if (mConnection == null) throw new DatabaseException("Connection instance of database client " + mHandle + " holds no value."); if (mConnection.State != ConnectionState.Closed) throw new DatabaseException("Connection instance of database client " + mHandle + " requires to be closed before it can open again."); try { mConnection.Open(); } catch (MySqlException mex) { throw new DatabaseException("Failed to open connection for database client " + mHandle + ", exception message: " + mex.Message); } } /// /// Attempts to close the database connection. /// internal void Disconnect() { try { mConnection.Close(); } catch { } } /// /// Closes the database connection (if open) and disposes all resources. /// internal void Destroy() { Disconnect(); mConnection.Dispose(); //mConnection = null; mCommand.Dispose(); //mCommand = null; //mManager = null; GC.SuppressFinalize(this); } /// /// Updates the last activity timestamp to the current date and time. /// internal void UpdateLastActivity() { mLastActivity = DateTime.Now; } /// /// Returns the DatabaseManager of this database client. /// //internal DatabaseManager GetManager() //{ // return mManager; //} internal void AddParamWithValue(string sParam, object val) { mCommand.Parameters.AddWithValue(sParam, val); } internal void query(string sQuery) { IsBussy = true; mCommand.CommandText = sQuery; mCommand.ExecuteScalar(); mCommand.CommandText = null; } internal DataTable query_read(string sQuery) { IsBussy = true; DataTable pDataTable = new DataTable(); mCommand.CommandText = sQuery; using (MySqlDataAdapter pAdapter = new MySqlDataAdapter(mCommand)) { pAdapter.Fill(pDataTable); } mCommand.CommandText = null; return pDataTable; } internal DataRow query_assoc(string sQuery) { IsBussy = true; DataTable pDataTable = query_read(sQuery); if (pDataTable != null && pDataTable.Rows.Count > 0) return pDataTable.Rows[0]; return null; } internal String query_string(string sQuery) { IsBussy = true; mCommand.CommandText = sQuery; String result = mCommand.ExecuteScalar().ToString(); mCommand.CommandText = null; return result; } internal Int32 query_rows(string sQuery) { IsBussy = true; mCommand.CommandText = sQuery; Int32 result = (Int32)mCommand.ExecuteScalar(); mCommand.CommandText = null; return result; } internal Int32 ReadInt32(string Query) { IsBussy = true; mCommand.CommandText = Query; Int32 result = Int32.Parse(mCommand.ExecuteScalar().ToString()); mCommand.CommandText = null; return result; } #region IDisposable members /// /// Returns the DatabaseClient to the DatabaseManager, where the connection will stay alive for 30 seconds of inactivity. /// public void Dispose() { if (this.Anonymous == false) // No disposing for this client yet! Return to the manager! { IsBussy = false; //Reset this! mCommand.CommandText = null; mCommand.Parameters.Clear(); mManager.ReleaseClient(mHandle); } else // Anonymous client, dispose this right away! { Destroy(); } } #endregion #endregion } }