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 Listparameters = 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のMySQLのDDL(テーブル作成SQL):
- -
- テーブルの構造 `t_table1`
- -
テストコード(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"); } }
マウスホイールでズームボタン・ラベル・テキストボックスの共通ルーチンをアダプタ
http://d.hatena.ne.jp/kabacsharp/20111119
で書いた、拡大縮小コントロ−ルの続きです。
初期化ルーチンや比率セットメソッドで、ロジックをフォーム側に書いていましたが、これを修正しました。
ボタンやラベルなどのコントロールはButton, Labelクラスで共通の親クラスはControl。
C#は多重継承できないので、継承によってアダプタクラスを作れませんでした。
そこで委譲によるアダプタクラスを作りました。
拡大縮小責務インターフェース:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace メールのみ.UserClass { public interface IControlResizable { int pWidth { get; set; } int pHeight { get; set; } float pFontSize { get; set; } int pTop { get; set; } int pLeft { get; set; } int OrgHeight { get; set; } int OrgWidth { get; set; } float OrgFontsize { get; set; } int OrgTop { get; set; } int OrgLeft { get; set; } float TuneRatio { get; set; } void InitSize(); void ChangeViewRatio(int ratio); } }
アダプタクラス:
ControlResizableAdapter.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using メールのみ.UserClass; namespace 波佐見弁利v2.UserClass { public class ControlResizableAdapter { private IControlResizable ctl_ = null; public float tuneratio = 1.0F; public ControlResizableAdapter(IControlResizable ctl) { this.ctl_ = ctl; } public void InitSize() { this.ctl_.OrgWidth = this.ctl_.pWidth; this.ctl_.OrgHeight = this.ctl_.pHeight; this.ctl_.OrgFontsize = this.ctl_.pFontSize; this.ctl_.OrgTop = this.ctl_.pTop; this.ctl_.OrgLeft = this.ctl_.pLeft; } public void ChangeViewRatio(int ratio) //ratio: 50-200 { this.ctl_.pHeight = (int)((this.ctl_.OrgHeight * ratio / 100) * this.tuneratio); this.ctl_.pWidth = (int)((this.ctl_.OrgWidth * ratio / 100) * this.tuneratio); this.ctl_.pFontSize = (float)((this.ctl_.OrgFontsize * ratio / 100) * this.tuneratio); this.ctl_.pTop = (int)((this.ctl_.OrgTop * ratio / 100) * this.tuneratio); this.ctl_.pLeft = (int)((this.ctl_.OrgLeft * ratio / 100) * this.tuneratio); } } }
アダプタクラスに委譲したボタンクラス:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows.Forms; using 波佐見弁利v2.UserClass; namespace メールのみ.UserClass { public class MyButtonKnowsOrgSize : Button, IControlResizable { private ControlResizableAdapter adapt_ = null; public MyButtonKnowsOrgSize() : base() { //フォーカスをとらない this.SetStyle(ControlStyles.Selectable, false); this.adapt_ = new ControlResizableAdapter(this); } public void ChangeViewRatio(int ratio) { this.adapt_.ChangeViewRatio(ratio); } public void InitSize() { this.adapt_.InitSize(); } public float TuneRatio { get { return this.adapt_.tuneratio; } set { this.adapt_.tuneratio = value; } } public int OrgHeight { get; set; } public int OrgWidth { get; set; } public float OrgFontsize { get; set; } public int OrgTop { get; set; } public int OrgLeft { get; set; } public int pHeight { get { return this.Height; } set { this.Height = value; } } public int pWidth { get { return this.Width; } set { this.Width = value; } } public float pFontSize { get { return this.Font.Size; } set { this.Font = new System.Drawing.Font("MS UI Gothic", value, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(128))); } } public int pTop { get { return this.Top; } set { this.Top = value; } } public int pLeft { get { return this.Left; } set { this.Left = value; } } } }
同じくアダプタクラスに委譲したラベルクラス:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows.Forms; using 波佐見弁利v2.UserClass; namespace メールのみ.UserClass { public class MyLabelKnowsOrgSize : Label, IControlResizable { private ControlResizableAdapter adapt_ = null; public MyLabelKnowsOrgSize() : base() { //フォーカスをとらない this.SetStyle(ControlStyles.Selectable, false); this.adapt_ = new ControlResizableAdapter(this); } public void ChangeViewRatio(int ratio) { this.adapt_.ChangeViewRatio(ratio); } public void InitSize() { this.adapt_.InitSize(); } public float TuneRatio { get { return this.adapt_.tuneratio; } set { this.adapt_.tuneratio = value; } } public int OrgHeight { get; set; } public int OrgWidth { get; set; } public float OrgFontsize { get; set; } public int OrgTop { get; set; } public int OrgLeft { get; set; } public int pHeight { get { return this.Height; } set { this.Height = value; } } public int pWidth { get { return this.Width; } set { this.Width = value; } } public float pFontSize { get { return this.Font.Size; } set { this.Font = new System.Drawing.Font("MS UI Gothic", value, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(128))); } } public int pTop { get { return this.Top; } set { this.Top = value; } } public int pLeft { get { return this.Left; } set { this.Left = value; } } } }
フォーム側(メイン側)のルーチン:
private void ChangeViewRatio(int ratio_org) { foreach (IControlResizable ctl in this.panel1.Controls.OfType()) { ctl.ChangeViewRatio(ratio); } } private void InitOrgSize() { //ボタンオリジナルサイズ foreach (IControlResizable ctl in this.panel1.Controls.OfType ()) { ctl.InitSize(); } } private void Form1_Load(object sender, EventArgs e) { this.InitOrgSize(); }
まだメイン側に改良の余地が。
IControlResizableのコレクションを持って、イベントで一気にInitSizeやChangeViewRatioをまとめて送信したいのですが、無駄ですかね。
テキストボックス、ボタン、ラベルなどをホイールでズームしてみた。
メールのみ!というメーラーを作っています。
http://lsl.way-nifty.com/mailonly/
画面や文字を拡大したいな、と思って作ってみました。
ICtlResizableというインターフェースを作った。
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace メールのみ.UserClass { interface ICtlResizable { int pWidth { get; set; } int pHeight { get; set; } float pFontSize { get; set; } int pTop { get; set; } int pLeft { get; set; } int OrgHeight { get; set; } int OrgWidth { get; set; } float OrgFontsize { get; set; } int OrgTop { get; set; } int OrgLeft { get; set; } } }
テキストボックスなどは、継承して作成。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows.Forms; namespace メールのみ.UserClass { class MyTextBoxOrgKnowsSize : TextBox, ICtlResizable { public MyTextBoxOrgKnowsSize() : base() { } public int OrgHeight { get; set; } public int OrgWidth { get; set; } public float OrgFontsize { get; set; } public int OrgTop { get; set; } public int OrgLeft { get; set; } public int pHeight { get { return this.Height; } set { this.Height = value; } } public int pWidth { get { return this.Width; } set { this.Width = value; } } public float pFontSize { get { return this.Font.Size; } set { this.Font = new System.Drawing.Font("MS UI Gothic", value, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(128))); } } public int pTop { get { return this.Top; } set { this.Top = value; } } public int pLeft { get { return this.Left; } set { this.Left = value; } } } }
フォームロード時に、以下の拡大縮小時使う初期サイズを取得する関数を呼ぶ。
ただし、拡張メソッドを使っているので、LINQをインポートする。
using System.Linq; private void InitOrgSize() { foreach (ICtlResizable ctl in this.panel1.Controls.OfType()) { ctl.OrgWidth = ctl.pWidth; ctl.OrgHeight = ctl.pHeight; ctl.OrgFontsize = ctl.pFontSize; ctl.OrgTop = ctl.pTop; ctl.OrgLeft = ctl.pLeft; } }
そして、ホイールボタンを設定。
//Form_Load時 //ホイール this.btnWheel.TextBoxForWheel = this.tbxWheel; this.btnWheel.OnMouseWheelHook += this.ChangeViewRatio;
こうすると、ホイールボタン上で、ホイールすると以下のメソッドが呼び出される。
private void ChangeViewRatio(int ratio) { if (ratio < 50) ratio = 50; if (ratio > 200) ratio = 200; foreach (ICtlResizable ctl in this.panel1.Controls.OfType()) { ctl.pHeight = ctl.OrgHeight * ratio / 100; ctl.pWidth = ctl.OrgWidth * ratio / 100; float sz = ((float)ctl.OrgFontsize * ratio) / 100; ctl.pFontSize = sz; ctl.pTop = ctl.OrgTop * ratio / 100; ctl.pLeft = ctl.OrgLeft * ratio / 100; } float lsz = this.listView1OrgFontSize * ratio / 100; this.listView1.Font = new System.Drawing.Font("MS UI Gothic", lsz, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(128))); this.panel1.Height = this.pnl1OrgHeight * ratio / 100; this.Height = this.frmOrgHeight * ratio / 100; this.Width = this.frmOrgWidth * ratio / 100; this.Resize_Form(); }
*ホイールボタンクラスは以下のよう。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows.Forms; using System.Drawing; namespace ABCS.UserClass { class WheelButton : Button { public WheelButton() : base() { this.Font = new Font(this.Font.FontFamily, 6, FontStyle.Bold); this.Text = "↑\n↓"; } public delegate void OnMouseWheelHookDelegate(int zoomsize); public event OnMouseWheelHookDelegate OnMouseWheelHook = null; public TextBox TextBoxForWheel { get; set; } protected override void OnMouseHover(EventArgs e) { base.OnMouseHover(e); this.Focus(); } protected override void OnMouseLeave(EventArgs e) { base.OnMouseLeave(e); if (this.TextBoxForWheel != null) { this.TextBoxForWheel.Focus(); } } public int wheelValue = 100; protected override void OnMouseWheel(MouseEventArgs e) { base.OnMouseWheel(e); this.wheelValue += e.Delta / 24; if (this.wheelValue < 50) { this.wheelValue = 50; } if (this.wheelValue >= 200) { this.wheelValue = 200; } this.TextBoxForWheel.Text = this.wheelValue.ToString(); if (this.OnMouseWheelHook != null) { this.OnMouseWheelHook(this.wheelValue); } } } }
まだ汚いですが。
試みにTwitterクライアント作成開始
DLR本が遅くなりそうなので、Twitterクライアントを先に作ってみようかと。
http://hasami-food.sakura.ne.jp/wp/keyborttaro/
とりあえず、グーグル先生に聞いたら、C#ではnojimaさんの日記が。
http://d.hatena.ne.jp/nojima718/20100129/1264792636
あとは、Accessに保存するよういつものようにDAO作成。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using ABCS.DAOs; using System.Data; namespace きぼったろうーテスト.DAOs { class twitterDAO : MyDAOBase { public twitterDAO(DAOContext con) : base(con) { } private DataTable selectAccount() { string sql = @"select * from twitter "; return base.GetTable(sql); } public DictionarygetAccountData() { Dictionary ac = new Dictionary (); DataTable tbl = this.selectAccount(); if (tbl.Rows.Count < 1) return null; DataRow row = tbl.Rows[0]; ac["AccessToken"] = row["AccessToken"].ToString(); ac["AccessTokenSecret"] = row["AccessTokenSecret"].ToString(); ac["UserId"] = row["UserId"].ToString(); ac["ScreenName"] = row["ScreenName"].ToString(); return ac; } public int updateAccount(Dictionary ac) { string sql = @"update twitter set AccessToken = @paccesstoken, AccessTokenSecret = @paccesstokensecret, UserId = @puserid, ScreenName = @pscreenname where ID = 1"; this.ClearParameters(); this.AddParameter("paccesstoken", DbType.String, ac["AccessToken"]); this.AddParameter("paccesstokensecret", DbType.String, ac["AccessTokenSecret"]); this.AddParameter("puserid", DbType.String, ac["UserId"]); this.AddParameter("pscreenname", DbType.String, ac["ScreenName"]); return base.ExecuteNonQuery(sql); } } }
DLRの勉強を試みたのですが。
この前の記事で、DLR本を買ったと書きました。
http://d.hatena.ne.jp/kabacsharp/20111111/1320996523
が、はずれでした。ヽ(TдT)ノ
その本は、IronPythonの解説・実践本でした。amazonで買うとこれだよ。
必死にPythonの文法覚えている自分・・・。orz
今月はもうお金もないため、来月、以下の本を買います。
でも輸送に時間がかかるんだよな。
Pro DLR in .NET 4 (Expert's Voice in .NET) | |
Chaur Wu Apress 2010-11-30 売り上げランキング : 200488 Amazonで詳しく見る by G-Tools |
あと、Pro本のLINQ本も買いたい。