C#でMySQL用のDAO作成(以前教えてもらったAccess用DAO使用)

MyDummySQLという、MySQL用のダミーデータ作成ツールを作ろうかと思い、まずはMySQL用のDAOを作ってみました。Access用から流用したものです。
まだテストしていません。orz 明日か。。。

追記:テストしました。テストコードも以下に付加しています。

あ、MySQL Connector/NETが必要です。
http://dev.mysql.com/downloads/connector/net/5.0.html#downloads
ver6.3.8を使っています。
ソリューションエクスプロラーの参照設定を右クリックして、ダイアログの「参照タブ」から「C:/ProgramFiles/MySQL・・・・/v4.0/MySQL.Data.dll」を選択する必要があります。


以下のサイトを参考にしました。
http://www2.pf-x.net/~rafysta/memo/wiki.cgi?page=C%23%A4%C7MySQL%A4%CB%C0%DC%C2%B3
http://d.hatena.ne.jp/levin_gsp/20071204/1196754042



MySQLDAOContext.cs(MySQLのコネクションやトランザクションの管理オブジェクト)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MySql.Data.MySqlClient;

namespace MyDummySQL.MySQLDAO
{
    class MySQLDAOContext : IDisposable
    {
        //コネクション
        private MySqlConnection con_ = null;
        //private mysqlProviderFactory fac_ = null;
        //トランザクション
        private MySqlTransaction tran_ = null;
        //コネクション
        public MySqlConnection Connection
        {
            get
            {
                return this.con_;
            }
            private set
            {
                this.con_ = value;
            }
        }
        /*//DBファクトリは使わない
        public DbProviderFactory Factory
        {
            get
            {
                return this.fac_;
            }
            private set
            {
                this.fac_ = value;
            }
        }
        */
        //トランザクション
        public MySqlTransaction Transaction
        {
            get
            {
                return this.tran_;
            }
            private set
            {
                this.tran_ = value;
            }
        }

        //デフォルトコンストラクタ
        //これはAccess用の接続文字列で他のコンストラクタを入れている->NGになる
        public MySQLDAOContext()
            : this("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=|DataDirectory|abc.mdb")
        {
        }

        //接続文字列を受け取るコンストラクタ
        public MySQLDAOContext(/*string providerName, */string connectionString)
        {
            //if (providerName == null) throw new ArgumentNullException("providerName");
            if (connectionString == null) throw new ArgumentNullException("connectionString");

            //this.Factory = DbProviderFactories.GetFactory(providerName);
            //this.Connection = this.Factory.CreateConnection();
            this.Connection = new MySqlConnection(connectionString);
            this.Connection.ConnectionString = connectionString;
        }

        //コネクションオープン
        public void OpenConnection()
        {
            if (this.Connection == null)
                throw new InvalidOperationException("Object is diposed.");

            if (this.Connection.State == System.Data.ConnectionState.Closed)
            {
                this.Connection.Open();
                this.Connection.GetSchema();
            }
        }

        //コネクションクローズ
        public void CloseConnection()
        {
            if (this.Connection == null)
                throw new InvalidOperationException("Object is diposed.");

            if (this.Connection.State == System.Data.ConnectionState.Open)
                this.Connection.Close();
        }

        //データベース変更
        public void changeDatabase(string dbName)
        {
            this.Connection.ChangeDatabase(dbName);
        }

        //トランザクション開始(トランザクション分離レベルを指定)
        public void BeginTransaction(System.Data.IsolationLevel isolationLevel)
        {
            if (this.Transaction != null)
                throw new InvalidOperationException("There is already a transaction.");

            this.OpenConnection();
            this.Transaction = this.Connection.BeginTransaction(isolationLevel);
        }

        //トランザクションコミット
        public void CommitTransaction()
        {
            if (this.Transaction == null)
                throw new InvalidOperationException("There is no transaction.");

            this.Transaction.Commit();
            this.Transaction = null;
        }

        //トランザクションロールバック
        public void RollbackTransaction()
        {
            if (this.Transaction == null)
                throw new InvalidOperationException("There is no transaction.");

            this.Transaction.Rollback();
            this.Transaction = null;
        }

        //アンマネージドリソース解放
        public void Dispose()
        {
            this.Dispose(true);
            GC.SuppressFinalize(this);  //ガベージコレクタファイナライズ処理
        }

        //Dispose
        protected virtual void Dispose(bool disposing)
        {
            if (disposing)  //Dispose中?
            {
                try
                {
                    if (this.Transaction != null)
                    {
                        this.RollbackTransaction(); //トランザクションロールバック
                        this.Transaction = null;
                    }
                }
                finally //最終的に必ず行われる処理
                {
                    if (this.Connection != null)
                    {
                        this.Connection.Dispose();  //コネクション(アンマネージドリソース)解放
                        this.Connection = null;
                    }
                }
            }
        }
    }
}

MySQLDAOBase.cs(MySQL用DAOのベースクラス)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MySql.Data.MySqlClient;
using System.Data;

namespace MyDummySQL.MySQLDAO
{
    class MySQLDAOBase
    {
        //SQL文中のバインド変数
        private readonly List parameters = new List();

        //コネクションなど
        private MySQLDAOContext context_ = null;

        //コネクションなど
        public MySQLDAOContext Context
        {
            get
            {
                return this.context_;
            }
            private set
            {
                this.context_ = value;
            }
        }

        //バインド変数(IListに変換)
        public IList Parameters
        {
            get { return this.parameters; }
        }

        //コンストラクタ
        public MySQLDAOBase(MySQLDAOContext context)
        {
            if (context == null) throw new ArgumentNullException("context");
            this.Context = context;
        }

        //バインド変数追加
        public void AddParameter(string parameterName, DbType dbType, object value)
        {
            MySqlParameter p = new MySqlParameter();
            p.ParameterName = parameterName;
            p.DbType = dbType;
            p.Value = value;
            this.parameters.Add(p);
        }

        //バインド変数クリア
        public void ClearParameters()
        {
            this.parameters.Clear();
        }

        //SQL実行。実行ロジック自体は、actionデリゲートで行う。
        protected void ExecuteCommand(string commandText, IEnumerable parameters,
            Action action)
        {
            MySqlCommand command = new MySqlCommand(commandText, this.Context.Connection);
            command.Connection = this.Context.Connection;
            command.Transaction = this.Context.Transaction;
            foreach (MySqlParameter parameter in parameters)
                command.Parameters.Add(parameter);
            action(command);
        }

        //DML(SELECT以外)実行。(独自のパラメータを指定してよい)
        protected int ExecuteNonQuery(string commandText, IEnumerable parameters)
        {
            int count = 0;
            this.ExecuteCommand(commandText, parameters, delegate(MySqlCommand command)
            {
                count = command.ExecuteNonQuery();
            });
            return count;
        }

        //DML(SELECT以外)実行。(パラメータはこのDAOのプロパティ)
        protected int ExecuteNonQuery(string commandText)
        {
            return this.ExecuteNonQuery(commandText, this.parameters);
        }

        //SELECT。DataTableで受け取る。(独自のパラメータを指定してよい)
        protected DataTable GetTable(string commandText, IEnumerable parameters)
        {
            DataTable table = new DataTable();
            this.ExecuteCommand(commandText, parameters, delegate(MySqlCommand command)
            {
                using (MySqlDataReader reader = command.ExecuteReader())
                {
                    table.Load(reader);
                }
            });
            return table;
        }

        //SELECT。DataTableで受け取る。(パラメータはこのDAOのプロパティ)
        protected DataTable GetTable(string commandText)
        {
            return this.GetTable(commandText, this.Parameters);
        }
    }
}

MySQLConString.cs(接続文字列生成):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MyDummySQL.MySQLDAO
{
    class MySQLConString
    {
        private string conString_ = "";
        public MySQLConString(string serverName, string userId, string password, string dbName, int port, bool isPooling)
        {
            string strgPooling = "";
            if (isPooling)
            {
                strgPooling = "true";
            }
            else
            {
                strgPooling = "false";
            }

            this.conString_ = String.Format("server={0};user id={1}; password={2}; database={3}; port={4};pooling={5}; ", serverName, userId, password, dbName, port.ToString(), strgPooling);
        }
        public string ConString
        {
            get
            {
                return this.conString_;
            }
        }
    }
}

テストテーブルt_table1用DAO:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MySql.Data.Types;
using System.Data;
namespace MyDummySQL.MySQLDAO
{
    class t_table1Dao : MySQLDAOBase
    {
        public t_table1Dao(MySQLDAOContext con) : base(con) { }

        public DataTable select(int id)
        {
            string sql = @"select *
                            from t_table1
                            where
                                id = @pid";

            this.ClearParameters();
            this.AddParameter("pid", DbType.Int32, id);

            DataTable tbl = base.GetTable(sql);
            return tbl;
        }
        public DataTable selectAll()
        {
            string sql = @"select *
                            from t_table1";

            this.ClearParameters();

            DataTable tbl = base.GetTable(sql);
            return tbl;
        }

        public int insert(string strgName)
        {
            string sql = @"insert into
                            t_table1(
                                name
                            )
                            values(
                                 @pname
                            )";

            this.ClearParameters();
            this.AddParameter("pname", DbType.String, strgName);

            return base.ExecuteNonQuery(sql);
        }

        public int update(int id, string name)
        {
            string sql = @"update t_table1
                            set
                                name = @pname
                            where
                                id = @pid";

            this.ClearParameters();
            this.AddParameter("pname", DbType.String, name);
            this.AddParameter("pid", DbType.Int32, id);

            return base.ExecuteNonQuery(sql);
        }

        public int delete(int id)
        {
            string sql = @"delete from t_table1
                            where
                                id = @pid";

            this.ClearParameters();
            this.AddParameter("pid", DbType.Int32, id);

            return base.ExecuteNonQuery(sql);
        }

    }
}

テストテーブルt_table1のMySQLDDL(テーブル作成SQL):

  • -
    • テーブルの構造 `t_table1`
  • -
CREATE TABLE IF NOT EXISTS `t_table1` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=3 ;

テストコード(Form1.cs内イベントハンドラ):

       private MySQLDAO.MySQLConString getObjConstring()
        {
            int port = 0;
            int.TryParse(tbxPortNo.Text, out port);

            MySQLDAO.MySQLConString objConString = new MySQLDAO.MySQLConString(
                 tbxServername.Text,
                 tbxUserName.Text,
                 tbxPassword.Text,
                 tbxDbName.Text,
                 port,
                 false);

            return objConString;
        }

        private void btnTest1_Click(object sender, EventArgs e)
        {
            MySQLDAO.MySQLConString objConString = this.getObjConstring();

            try
            {
                using (MySQLDAO.MySQLDAOContext con = new MySQLDAO.MySQLDAOContext(objConString.ConString))
                {
                    con.OpenConnection();
                    con.CloseConnection();
                    MessageBox.Show("success");
                }
            }
            catch (MySql.Data.MySqlClient.MySqlException excep)
            {
                MessageBox.Show("error");
            }
        }

        private void btnSqlTest_Click(object sender, EventArgs e)
        {
            MySQLDAO.MySQLConString objConString = this.getObjConstring();

            using (MySQLDAO.MySQLDAOContext con = new MySQLDAO.MySQLDAOContext(objConString.ConString))
            {
                con.OpenConnection();
                t_table1Dao dao = new t_table1Dao(con);

                //insert
                dao.insert("test1");

                int id = 1;

                //select
                DataTable tbl = dao.selectAll();
                if (tbl.Rows.Count > 0)
                {
                    MessageBox.Show(tbl.Rows[0]["name"].ToString() + "がInsertされました。");
                    id = (int)tbl.Rows[0]["id"];
                }
                else
                {
                    MessageBox.Show("insert失敗");
                }

                //update
                dao.update(id, "test2");

                //select
                DataTable tbl2 = dao.select(id);
                if (tbl2.Rows.Count > 0)
                {
                    string name = tbl2.Rows[0]["name"].ToString();
                    if ("test2".Equals(name))
                    {
                        MessageBox.Show(name + "にupdateされました。");
                    }
                    else
                    {
                        MessageBox.Show("updateに失敗しました。");
                    }
                }

                //delete
                dao.delete(id);

                //select
                DataTable tbl3 = dao.select(id);
                if (tbl3.Rows.Count > 0)
                {
                    MessageBox.Show("deleteに失敗しました。");
                }
                else
                {
                    MessageBox.Show("deleteに成功しました。");
                }

                con.CloseConnection();
                MessageBox.Show("success");
            }
        }