MySQL Connector/NET のラッパー

OLE DB.NET のラッパー作ったついでに MySQL Connector/NET のラッパーも作ってみました。といっても基本的に MySql.Data を参照に追加し using、OLE DB.NET のプレフィックス 「OleDb」MySql に置き換えただけです。データプロバイダは違えども、ADO.NETインターフェイスは共通なので便利ですね。
ちなみにこのラッパー、こんな感じで使います。

string connectionString = "server=hoge-server;user id=hogehoge;password=hogehoge;database=db-hoge;";
using (MySqlWrapper wrapper = new MySqlWrapper(connectionString)) {
    MySqlCommand command = new MySqlCommand("SELECT * FROM Employees");
    DataTable dt = wrapper.GetDataTable(command);
    // ・・・・・・
}


ただし、Jet.OLEDB.4.0 ならトランザクション処理をあまり考えなくてもいいでしょうけど、MySQL の場合はトランザクション処理が必須です。MySQL の既定のトランザクション分離レベルですが、SQLServer と違って RepeatableRead です。(InnoDB の場合ね・・・)本ラッパーでもそのように実装しております。
(でもネットで調べてると OLE DB でOracle に接続する記事が結構ありますね。わたくしオラクルはよく判らないのですが、オラクルに OLEDB 使って接続するケースってちと考え難いんですけど、実際どうなんでしょうかねぇ・・・)



以下ソース

using System;
using System.Data;
using MySql.Data.MySqlClient;


class MySqlWrapper : IDisposable {

    /// <summary>コネクション</summary>
    MySqlConnection _connection;
    /// <summary>トランザクション</summary>
    MySqlTransaction _transaction;
    bool _disposed;

    /// <summary>
    /// コンストラクタ
    /// </summary>
    /// <param name="connectString">接続文字列</param>
    public MySqlWrapper(string connectString) {
            _connection = new MySqlConnection(connectString);
    }

    /// <summary>
    /// リソースを解放します。
    /// </summary>
    /// <param name="disposing"></param>
    protected void Dispose(bool disposing) {

        if (_disposed == false) {
            if (disposing) {
                //
                if (_transaction != null) {
                    _transaction.Dispose();
                }

                if (_connection != null) {
                    this.Close();
                    _connection.Dispose();
                }
            }
            _disposed = true;
        }
    }

    /// <summary>
    /// リソースを解放します。
    /// </summary>
    public void Dispose() {
            this.Dispose(true);
            GC.SuppressFinalize(this);
    }

    /// <summary>
    /// トランザクションを開始します。
    /// </summary>
    public MySqlTransaction BeginTransaction() {

            try {
                _transaction = _connection.BeginTransaction(IsolationLevel.RepeatableRead);
            } catch (Exception) {
                throw;
            }
            return _transaction;
    }

    /// <summary>
    /// トランザクションを開始します。
    /// </summary>
    public MySqlTransaction BeginTransaction(IsolationLevel isolationLevel) {

            try {
                _transaction = _connection.BeginTransaction(isolationLevel);
            } catch (Exception) {
                throw;
            }
            return _transaction;
    }

    /// <summary>
    /// データベースへの接続を閉じます。
    /// </summary>
    public void Close() {
            try {
                if (_connection != null && 
                    _connection.State == ConnectionState.Open) {
                    _connection.Close();
                }
            } catch (Exception) {
                throw;
            }
    }

    /// <summary>
    /// トランザクション処理をコミットします。
    /// </summary>
    public void Commit() {
            try {
                if (_transaction != null) {
                    _transaction.Commit();
                }
            } catch (Exception) {
                throw;
            }
    }

    /// <summary>
    /// 接続に対して SQL ステートメントを実行し、影響を受けた行数を返します。 
    /// </summary>
    /// <param name="command"><see cref="MySqlCommand">MySqlCommand</see> オブジェクト</param>
    /// <returns>影響を受けた行数</returns>
    public int ExecNonQuery(MySqlCommand command) {

            int ret = 0;
            try {
                command.Connection = _connection;
                if (_transaction != null) {
                    command.Transaction = _transaction;
                }
                ret = command.ExecuteNonQuery();
            } catch (Exception) {
                throw;
            }
            return ret;
    }

    /// <summary>
    /// クエリを実行し、そのクエリが返す結果セットの最初の行にある最初の列を返します。
    /// </summary>
    /// <param name="command"><see cref="MySqlCommand">MySqlCommand</see> オブジェクト</param>
    /// <returns>結果セットの最初の行の最初の列</returns>
    public Object ExecScaler(MySqlCommand command) {

            Object ret = null;
            command.Connection = _connection;
            try {
                if (_transaction != null) {
                    command.Transaction = _transaction;
                }
                ret = command.ExecuteScalar();
            } catch (Exception) {
                throw;
            }
            return ret;
    }

    /// <summary>
    /// データテーブル取得処理
    /// </summary>
    /// <param name="command"><see cref="MySqlCommand">MySqlCommand</see> オブジェクト</param>
    /// <returns><see cref="DataTable">DataTable</see>オブジェクト</returns>
    /// <remarks>
    /// パラメータに渡されたコマンドを実行し、データテーブルを取得します。
    /// </remarks>
    public DataTable GetDataTable(MySqlCommand command) {

            DataTable ret = null;
            try {
                command.Connection = _connection;
                if (_transaction != null) {
                    command.Transaction = _transaction;
                }
                MySqlDataAdapter adapter = new MySqlDataAdapter(command);
                MySqlCommandBuilder builder = new MySqlCommandBuilder(adapter);
                ret = new DataTable();
                adapter.Fill(ret);

            } catch (Exception) {
                ret = null;
                throw;
            }
            return ret;
    }

    /// <summary>
    /// データベース接続を開きます。 
    /// </summary>
    public void Open() {
            try {
                _connection.Open();
            } catch (Exception) {
                throw;
            }
    }

    /// <summary>
    /// トランザクション処理をロールバックします。
    /// </summary>
    public void Rollback() {

            try {
                if (_transaction != null) {
                    _transaction.Rollback();
                }
            } catch (Exception) {
                throw;
            }
    }

    /// <summary>
    /// データテーブル更新処理
    /// </summary>
    /// <param name="source">更新対象となるデータテーブル</param>
    /// <param name="command"><see cref="MySqlCommand">MySqlCommand</see> オブジェクト</param>
    /// <returns>更新に成功した行数</returns>
    public int Update(DataTable source, MySqlCommand command) {

            int ret = 0;
            try {
                command.Connection = _connection;
                if (_transaction != null) {
                    command.Transaction = _transaction;
                }
                MySqlDataAdapter adapter = new MySqlDataAdapter(command);
                MySqlCommandBuilder builder = new MySqlCommandBuilder(adapter);
                ret = adapter.Update(source);

            } catch (Exception) {
                throw;
            }
            return ret;
    }
}

ちなみに私がトランザクションを学んだ教科書がこれ。当時の現場では、この本のおかげで大変助かりました!!赤間さんにはいまだに感謝しております。

 
そういや今度久々にわんくまで講演されるようですね!行きたいけど用事が入りそうなため、なんとも微妙・・・

2010/10/10 追記

コードを少し修正しました。