// ByteFX.Data data access components for .Net // Copyright (C) 2002-2003 ByteFX, Inc. // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA using System; using System.Data; using System.Collections.Specialized; using System.Text; using System.ComponentModel; using System.Globalization; using ByteFX.Data.Common; namespace ByteFX.Data.MySqlClient { /// /// Represents an open connection to a MySQL Server database. This class cannot be inherited. /// /// [System.Drawing.ToolboxBitmap( typeof(MySqlConnection), "Designers.connection.bmp")] [System.ComponentModel.DesignerCategory("Code")] [ToolboxItem(true)] public sealed class MySqlConnection : Component, IDbConnection, ICloneable { internal ConnectionState state; private MySqlInternalConnection internalConnection; private MySqlDataReader dataReader; private NumberFormatInfo numberFormat; private MySqlConnectionString settings; /// /// Occurs when the state of the connection changes. /// public event StateChangeEventHandler StateChange; /// /// Creates a new connection /// public MySqlConnection() { settings = new MySqlConnectionString(); } /// /// Creates a new connection /// /// public MySqlConnection(System.ComponentModel.IContainer container) { settings = new MySqlConnectionString(); } // Have a constructor that takes a connection string. /// /// Creates a new connection using the specified connection string. /// /// public MySqlConnection(string connectString) { settings = new MySqlConnectionString(connectString); } /// /// Gets the name of the MySQL server to which to connect. /// #region Properties [Browsable(true)] public string DataSource { get { return settings.Host; } } /// /// Gets the time to wait while trying to establish a connection before terminating the attempt and generating an error. /// /// [Browsable(true)] public int ConnectionTimeout { get { return settings.ConnectTimeout; } } /// /// Gets the name of the current database or the database to be used after a connection is opened. /// [Browsable(true)] public string Database { get { return settings.Database; } } /// /// Indicates if this connection should use compression when communicating with the server. /// [Browsable(false)] public bool UseCompression { get { return settings.UseCompression; } } /// /// Gets the current state of the connection. /// [Browsable(false)] public ConnectionState State { get { return state; } } internal MySqlDataReader Reader { get { return dataReader; } set { dataReader = value; } } internal MySqlInternalConnection InternalConnection { get { return internalConnection; } } internal NumberFormatInfo NumberFormat { get { if (numberFormat == null) { numberFormat = new NumberFormatInfo(); numberFormat = (NumberFormatInfo)NumberFormatInfo.InvariantInfo.Clone(); numberFormat.NumberDecimalSeparator = "."; } return numberFormat; } } /// /// Gets a string containing the version of the MySQL server to which the client is connected. /// [Browsable(false)] public string ServerVersion { get { return internalConnection.Driver.Version; } } internal Encoding Encoding { get { if (internalConnection == null) return System.Text.Encoding.Default; else return internalConnection.Driver.Encoding; } } /// /// Gets or sets the string used to connect to a MySQL Server database. /// /// #if WINDOWS [Editor(typeof(Designers.ConnectionStringEditor), typeof(System.Drawing.Design.UITypeEditor))] #endif [Browsable(true)] [Category("Data")] public string ConnectionString { get { // Always return exactly what the user set. // Security-sensitive information may be removed. return settings.ConnectString; } set { settings.ConnectString = value; if (internalConnection != null) internalConnection.Settings = settings; } } #endregion #region Transactions /// /// Begins a database transaction. /// /// public MySqlTransaction BeginTransaction() { if (state != ConnectionState.Open) throw new MySqlException("Invalid operation: The connection is closed"); MySqlTransaction t = new MySqlTransaction(); t.Connection = this; InternalConnection.Driver.SendCommand( DBCmd.QUERY, "BEGIN"); return t; } /// /// /// IDbTransaction IDbConnection.BeginTransaction() { return BeginTransaction(); } /// /// /// /// /// public MySqlTransaction BeginTransaction(IsolationLevel level) { if (state != ConnectionState.Open) throw new MySqlException("Invalid operation: The connection is closed"); MySqlTransaction t = new MySqlTransaction(); t.Connection = this; t.IsolationLevel = level; string cmd = "SET SESSION TRANSACTION ISOLATION LEVEL "; switch (level) { case IsolationLevel.ReadCommitted: cmd += "READ COMMITTED"; break; case IsolationLevel.ReadUncommitted: cmd += "READ UNCOMMITTED"; break; case IsolationLevel.RepeatableRead: cmd += "REPEATABLE READ"; break; case IsolationLevel.Serializable: cmd += "SERIALIZABLE"; break; case IsolationLevel.Chaos: throw new NotSupportedException("Chaos isolation level is not supported"); } InternalConnection.Driver.SendCommand( DBCmd.QUERY, cmd ); InternalConnection.Driver.SendCommand( DBCmd.QUERY, "BEGIN"); return t; } /// /// /// /// /// IDbTransaction IDbConnection.BeginTransaction(IsolationLevel level) { return BeginTransaction(level); } #endregion /// /// Changes the current database for an open MySqlConnection. /// /// public void ChangeDatabase(string dbName) { if (state != ConnectionState.Open) throw new MySqlException("Invalid operation: The connection is closed"); //TODOinternalConnection.ChangeDatabase( dbName ); InternalConnection.Driver.SendCommand( DBCmd.INIT_DB, dbName ); } internal void SetState( ConnectionState newState ) { ConnectionState oldState = state; state = newState; if (this.StateChange != null) StateChange(this, new StateChangeEventArgs( oldState, newState )); } /// /// Opens a database connection with the property settings specified by the ConnectionString. /// public void Open() { if (state == ConnectionState.Open) throw new MySqlException("error connecting: The connection is already Open (state=Open)."); SetState( ConnectionState.Connecting ); if (settings.Pooling) { internalConnection = MySqlPoolManager.GetConnection( settings ); } else { internalConnection = new MySqlInternalConnection( settings ); internalConnection.Open(); } SetState( ConnectionState.Open ); internalConnection.SetServerVariables(this); ChangeDatabase( settings.Database ); } /// /// Closes the connection to the database. This is the preferred method of closing any open connection. /// public void Close() { if (state == ConnectionState.Closed) return; if (dataReader != null) dataReader.Close(); if (settings.Pooling) MySqlPoolManager.ReleaseConnection( internalConnection ); else internalConnection.Close(); SetState( ConnectionState.Closed ); } IDbCommand IDbConnection.CreateCommand() { return CreateCommand(); } /// /// Creates and returns a MySqlCommand object associated with the MySqlConnection. /// /// public MySqlCommand CreateCommand() { // Return a new instance of a command object. MySqlCommand c = new MySqlCommand(); c.Connection = this; return c; } #region ICloneable /// /// Creates a new MySqlConnection object with the exact same ConnectionString value /// /// A cloned MySqlConnection object object ICloneable.Clone() { MySqlConnection clone = new MySqlConnection(); clone.ConnectionString = this.ConnectionString; //TODO: how deep should this go? return clone; } #endregion #region IDisposeable /// /// Releases the resources used by the MySqlConnection. /// public new void Dispose() { if (State == ConnectionState.Open) Close(); base.Dispose(); } #endregion } }