カテゴリ「オープンソース」の過去ログ

現在、会社の自動ビルドシステムをNAntにしようかMSBuildにしようか評価中。半日ぐらいNAntで遊んでみたが、面白い。これってある意味XMLをプログラミング言語として使っているような感じだ。いってみればXAMLみたいな感じだ。nant.xsdをVS 2005に読み込ませて、.buildの拡張子をVS2005内でXMLエディタにマッピングさせるとNAnt用にインテリセンスが実現できる。これがなければドキュメントとの壮絶なる戦いになるだろう。そうじゃなくても読むことがたくさんあるのに・・・XSDをベースにしたインテリセンスは非常にありがたいのである。


自分の今までの(浅い)データベースの経験からデータベースサーバには次のようなスキーマが存在する。


- データベースサーバ(=1コンピュータ) ※クラスタ環境の場合は一つのコンピュータとは限らない。
   - データベース(一つのデータベースサーバに複数のデータベースが存在し得る)
      - テーブル(一つのデータベースに複数のテーブルが存在し得る)
      - ストアドプロシージャ(一つのデータベースに複数のテーブルが存在し得る)
      - ビュー(一つのデータベースに複数のビューが存在し得る)
   - データベースユーザ(一つのデータベースサーバに複数のユーザが存在し得る)


と、基本的な基本はこんな感じだが、それをどうすれば取得できるか。MySQLにはデフォルトでinformation_schema, mysqlそしてtestの3つのデータベースが存在する。



information_schemaという名前のデータベースがあるが、これにはこのMySQLのスキーマの情報が詰め込まれているのだ。コミュニケーションに関するコミュニケーションのことをメタコミュニケーションというが、information_schemaはデータベースに関するデータベースなのでメタデータベースと呼んでもいいだろうか。infromation_schemaデータベースに存在するテーブルは次の通り。



これらをクエリしていけばMySQLのスキーマの情報を取得できそうだ。初めはSCHEMATAテーブルをクエリしてMySQLに存在するデータベースを羅列してみよう。以前に作成してたMySqlEngineに次のようなメソッドを追加してみた。



上のメソッドはジェネリックを使ってMySqlDatabase(プロパティが3つの単純なクラス)を返す。このメソッドに対してテストケースを書いてみた。



結果は・・・


—— Test started: Assembly: UnitTest.dll ——


information_schema
mysql
test


1 succeeded, 0 failed, 0 skipped, took 0.50 seconds.


とこんな感じで、簡単にMySQLに存在するデータベースをリストするメソッドができてしまったのである。


データベース技術には欠かせないのがトランザクション。トランザクションとは何か。よく例に出されるのは銀行におけるコンピュータシステムでのお金の移動だ。実際のプログラミングの例を持って説明するならば、二つのテーブルにデータを挿入する処理があるとします。二つのテーブルにデータを挿入するには二つのINSRET文が必要になります。一つ目が成功して、二つ目がエラーが出てしまった場合、一つ目のテーブルにデータが入って二つ目のテーブルにはデータが入らないことになりますね。こんな場合にデータの整合性が保たれないことになります。そこでトランザクションの技術が必要になります。二つのうちどちらかがエラーになってもロールバック、つまり元に戻すことが可能になります。二つとも成功した場合はそのデータを保存してデータベースに結果を反映させます。ExecuteNonQueryを実装し、トランザクションを試すテストケースを作って見ましょう。下の画像はExecuteNonQueryを実装したものです。



ExecuteNonQueryはデータを返さず、INSRTやUPDATEなどのストアドプロシージャを実行するためのメソッドです。2つのオーバーロードメソッドがあり、それぞれの用途に合わせてどれを使ってもいいようになっています。MySQLのtestデータベース内にisp_customerというストアドプロシージャを作成してそれを実行することにします。ストアドプロシージャは次のようにごく簡単なものです。


CREATE PROCEDURE `isp_customer`(IN shi varchar(100), IN mei varchar(100))
insert into tbl_customer(氏, 名) values(shi, mei);


早速、トランザクションをテストするテストケースを作成しましょう。



これを実行するとどちらのレコードもデータベースに挿入されませんでした。ちなみに例外を発生させるコードをコメントアウトするとどちらのレコードも挿入されていました。これでトランザクションがMySQLで使えることが分かりました。


これで一通りMySQLを使う準備が整ってきましたので、次回からはMySqlEngineを使用してMySQLを管理するツールの設計、実装、そしてMySQLに対する疑問をリサーチ、実証していこうと思います。


更新:上のテストケースには欠陥がありますね。どんな場合でもテストケースが失敗になることがない・・・ _| ̄|○


 _| ̄|○


このブログを書くしょっぱなからつまずきました。今のNavicatでは日本語が入ったストアドプロシージャが作れない!まだ評価期間中なので、よかったら買ってしまおうかなとも思っていましたが、やめることにします。日本語が使えるMySQL用のツールを自分で作ったほうがいいですね。でも、このMySQL+.NETの統合をするためにそんなことにはめげていられません。今までコツコツ作ってきたMySQL用のライブラリを用いて日本語が入ったMySQLのストアドプロシージャを作ります。そこでユニットテストでこんなのを書いてMySQLにストアドプロシージャを作ってみました。



これで日本語が入ったストアドプロシージャがMySQL内にできました。こんなところにもNUnitは力を発揮しまね。ちなみに、このテストケースは開発時に便宜上作られたものですので、<Test(), Ignore(”ストアドプロシージャを作るためのもの”)> なんてしてやると、NUnitによって無視されますし、あとでまた使いたいときにIgnoreをはずしてやるとまた使えるので便利です。


Navicatで見てみると確かにsp_customerというストアドプロシージャが作成されました。



これはKokyakuIDというパラメータを取り、その値をWHERE節に使って結果を返します。このストアドプロシージャに対するユニットテストを次のように書いてみました。



これを実行すると、結果が顧客IDが1の行だけがMySQLより返されました。 キタ━━━━(゚∀゚)━━━━ッ!!



次回はトランザクションを取り上げます。


※今日はちょっと2ちゃんカルチャーをところどころに入れてみました・・・


LinuxやMacOSに浮気をしていてMySQL+.NET2.0を少々お休みしていたが、今日からまた再開します。いよいよMySQLでサポートされているストアドプロシージャを.NETから呼び出す方法を探っていきます。ストアドプロシージャは英語ではStored Procedureと書きまして、データベース側ですでにコンパイルされたクエリのことを言います。MySQLではつい最近のバージョン5からサポートされるようになりました。マイクロソフトのSQL Serverではかなり前からサポートされています。実際のデータベース開発ではこれを使わないことはまずないといって過言ではないでしょう。


MySQLに関しては初心者の私ですが、早速、ストアドプロシージャを書いてみることにします。


(5分後)


これは余談ですが・・・Navicatの評価版でストアドプロシージャを書いて、それを保存しようとしたら下のようなエラーが出ました。



Navicatは日本語版が出ているにもかかわらず、しかもコマーシャルソフトウェアなのに、基本的な部分にASCIIしか文字コードに考慮されていないなんてあまりじゃないですか?仕方がないので次のようにしてストアドプロシージャを何とか作りました。



これだとプロシージャに日本語が入らないので何とか通りました。ストアドプロシージャを呼び出してDataTableを得るメソッドはExecuteDataTableという名前にして次のように実装しました。



ユニットテストは次のようにしました。



これをTest Driven .NETのデバッグモードで実行すると・・・



と、tbl_customerテーブルからデータがDataTableに格納されました。これでストアドプロシージャがきちんと動作したことが確認されました。


次回はパラメータを持つストアドプロシージャを作ってそれを確かめてみたいと思います。


前のブログで次回はストアドプロシージャに挑戦したいといいましたが、今回はExecuteNonQueryRawSqlのバージョンの実装をきちんと終わらせてしまいたいと思います。


以前にpublic int ExecuteNonQueryRawSql(string SqlText)というようなメソッドを作りました。INSERT文にはWHERE節はありませんがUPDATE文では十分考えられます。そこでpublic in ExecuteNonQueryRawSqlg SqlText, params MySql.Data.MySqlClient.MySqlParameter[] Params)というメソッドを書いてみました。



これは補足ですが、int ExecuteNonQueryRawSql(string SqlText)とほとんど同じなのでそれを次のようにしてみました。


public int ExecuteNonQueryRawSql(string SqlText)
{
   return ExecuteNonQueryRawSql(SqlText, null);
}


こうすることによって余分な重複コードを削減することができます。


テストメソッドは次のように書きました。



結果はきちんとMySQLに反映されました。


昨日は夜の9時半ぐらいに寝てしまいました・・・このブログを書くつもりでブラウザを立ち上げましたが、息子を寝静めようとベッドに入ったらそのまま眠ってしまいました。今日は気合を入れてこの記事を書きます。


SQL文をパラメータなしで実行することは実際の開発ではほとんどありえないでしょう。そのためにMySqlParameterをparam配列として取るメソッドを作ってみました。



特別なことは特にないですね。これに対するテストメソッドを作って実行してみました。


<Test()> _
Public Sub ExecuteDataSetRawSql・パラメータテスト()
Dim se As New MySqlEngine(“localhost”, “root”, “whatever”, “test”)
Dim par顧客ID As New MySqlParameter(“?顧客ID”, MySqlDbType.Int32, 11, “顧客ID”)

par顧客ID.Value = 1

Dim Customers As DataSet = se.ExecuteDataSetRawSql(“SELECT 顧客ID, 氏, 名 FROM tbl_customer where 顧客ID = ?顧客ID”, par顧客ID)
Customers.DataSetName = “顧客リスト”
Debug.Write(Customers.GetXml())
End Sub


結果は・・・


<顧客リスト>
  <Table>
    <顧客ID>1</顧客ID>
    <氏>山田</氏>
    <名>花子</名>
  </Table>
</顧客リスト>


というようにひとつだけのレコードがMySQLより返されました。上のテストメソッドを作っているときにMySQLではクエスチョンマークをパラメータの記号として使うのを知らなくてマイクロソフトのSQL Serverで使うように@をつかってて、どうしても期待した結果が得られなくてしばらく悩んでいましたが、ここのサンプルを見てクエスチョンマークだということがわかりました。上のテストメソッドのネガティブテストも作成してみましょう。


<Test(), ExpectedException(GetType(MySqlException))> _
Public Sub ExecuteDataSetRawSql・パラメータテストSQL文が文法エラーがある場合()
Dim se As New MySqlEngine(“localhost”, “root”, “whatever”, “test”)
Dim par顧客ID As New MySqlParameter(“?顧客ID”, MySqlDbType.Int32, 11, “顧客ID”)

par顧客ID.Value = 1

Dim Customers As DataSet = Nothing
Try
Customers = se.ExecuteDataSetRawSql(“SELECT 顧客ID, 氏,,,, 名 FROM tbl_customer where 顧客ID = ?顧客ID”, par顧客ID)
Catch ex As MySqlException
If ex.Number = 1064 Then
Throw
End If
End Try

Customers.DataSetName = “顧客リスト”
Debug.Write(Customers.GetXml())
End Sub


下の例は文法エラー(MySqlException+例外番号1064)をきちんと捕まえて、それじゃない場合にはAssertクラスを使ってそのユニットテストを失敗にする方法を取っています。これだと単にMySqlExceptionが発生すればいいという漠然としたテストがより明確なテストになります。幸いにもMySqlExceptionにはNumberというプロパティがありますので、同じ例外の型でもそれが本当に何の例外かを見分けることができるようです。HTML化したコードが見にくいので下のコードは画像にします。



次回はいよいよMySQLのストアドプロシージャの呼び出しに挑戦してみたいと思います。予定をしているメソッドは次のとおり。



  1. ExecuteNonQuery() (void)
  2. ExecuteScaler() (returns object)
  3. ExecuteDataSet() (returns DataSet)
  4. ExecuteDataTable() (return DataTable)

あともうひとつ考えているのはトランザクションです。MySQLではトランザクションがサポートされていますし、使用しているConnector/Netでもトランザクションがサポートされているので多分いけると思います。


 


うちのシステムが元に戻りつつあるので、MySQLに接続についてのブログを続けていきたいと思います。


SQLを実行するには概して直接SQL文を渡す方法ストアドプロシージャの方法の二つありますが、今回は直接SQL文をMySQLに渡して実行するメソッド、ExecuteNonQueryRawSql()のメソッドのひとつを紹介します。



※更新1:上の黄色のマーカーの行を実際に実行するとSystem.NotSupportedExceptionの例外が発生してしまいます。Connector/Net1.0ではCommandTimeoutがまだサポートされていないんでしょう。


更新2:Connector/Net1.0のソースコードが上のリンクからダウンロードできます。そこでMySqlCommandのソースのCommandTimeoutプロパティのsetterを見てみると、やはり次のようになっていました。


        /// <include file=’docs/mysqlcommand.xml’ path=’docs/CommandTimeout/*’/>
        [Category(“Misc”)]
        [Description(“Time to wait for command to execute”)]
        public int CommandTimeout
        {
            // TODO: support this
            get { return 0; }
            set { if (value != 0) throw new NotSupportedException(); }
        }


このメソッドは渡されたSQL文は何でも実行してしまいます。以前、作ったtbl_customerというテーブルにデータを追加するSQL文を書いてそれをUnitTestから実行してみましょう。



これを実行すると次のようにtbl_customerにデータが挿入されました。



顧客IDのフィールドは自動追加(auto increment)になっていますので、MySQLが勝手に番号を振り当ててくれます。次回は、SELECT文でデータをMySQLから取り出すのをやって見ましょう。


さて準備ができたところで.NETからどうやってMySQLに接続するのだろうといろいろ見てみたところ、MySQLのウェブサイト上にMySQL Connector/Netというのがありました。ADO .NET用のMySQLのDriverだそうです。それがないとMySQLに接続はできないでしょう。他にもいろいろプロバイダがあるようだが、今回はこれでやってみることにします。526kbと非常に軽い。インストールは簡単すぎて説明することがありません。


それをインストールするとC:\Program Files\MySQL\MySQL Connector Net 1.0.6\binにアセンブリが書くフレームワーク用に存在しています。うーむ・・・2.0用はまだないのか。仕方がないので1.1用で試してみることにします。早速MySqlGuiLibからMySql.Data.dllに参照を設定することにしよう。今の時点ではクラスを設計するよりも、とにかく接続してみたいのでTestClass.csをMySqlGuiLibに作ってそこにコードを書くことにします。コードを書く前にちょっと見ていただきたいのがこの間MySQL内のtestデータベースに作ったtbl_customerです。そのテーブルにNavicatを使って3つのデータをサンプル用に追加しました。下のテーブルをクエリーしてデータを取り出すコードを書くことにしましょう。



コードサンプル。


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

namespace MySqlGuiLib
{
public class TestClass
{
public void ConnectToMySql()
{
//とりあえずConnectionStringを決める。
string ConnStr = “database=test;User ID=root;Password=whatever;Host=localhost;Port=3306;”;
//MySqlconnectionのインスタンスを作成。
MySqlConnection Conn = new MySqlConnection(ConnStr);

//MySqlDataAdapterのインスタンスを作成。コンストラクタにSQLとMySqlConnectionを入れてやる。
MySqlDataAdapter da = new MySqlDataAdapter(“SELECT * FROM tbl_customer”, Conn);

//CommandTypeはText。
da.SelectCommand.CommandType = CommandType.Text;

//上のMySqlDataAdapterを利用してDataSetオブジェクトをデータで埋める。
DataSet ds = new DataSet(“顧客”);

//SQLを実行する前にMySqlconnectionを開く。
Conn.Open();

//SQLを実行してデータセットを埋める。
da.Fill(ds);

//Connectionを閉じる。
Conn.Close();
}
}
}


早速上のコードをテストするコードをUnitTestプロジェクト内に作ってみよう。テストのファイルはTestClassTest.vbと名前をつけました。



上のテストメソッドを右クリックして今度はTest With… ->Debuggerとし、Test.ConnectToMySql()にブレークポイントを置くと今度はユニットテストがデバッグモードでできてしまいます。da.Fill(ds);が実行した時点でdsの上にマウスを持っていって虫メガネアイコンをクリックするとDataSet Visualizerなるものが現れて、データセットの内容をグリッドに表示してくれます。これはありがたい!ただしVS2003でもXML Visualizer for Visual Studio .NET 2003というアドインを使用すると可能になります。



てな感じでVS2005(.NET Framework 2.0)からMySQL5.0への接続、クエリーが成功しました。これから徐々にいろいろなことをMySQL+VS2005で試して行こうと思います。もし「こんなこと試してほしい」ということがありましたらコメントいただければうれしいです。コメントに直接書いてくださってもかまいません。


このサンプルに用いたソースコードを下にアップしておきました。

MySqlGUI.zip (113.17 KB)


前に.NETからMySQLに接続してみたいとこのブログに書きました。昨日NAgileの記事を読んだのでNUnitTest Driven .NETを用いてMySQLへの接続コードをテストしてみようと思います。


初めにNUnitとTest Driven .NETはVS2005上でもきちんと動作しますので安心してインストールしていただいてかまいません。ここではNUnit2.2とTest Driven .NET 1.0はすでにインストールしてあるものとします。


とりあえず二つのクラスライブラリプロジェクトを用意します。一つはMySqlGuiLibでC#プロジェクトとします。このプロジェクトは実際MySQLへの接続をするライブラリプロジェクトです。もう一つはそれをテストするプロジェクトで単純にUnitTestと名前をつけましょう。このプロジェクトはVB.NETにしておきます。別々の言語を使うのには特に意味はありません。単にバラエティを楽しみたいだけです。(笑)VB.NETのプロジェクト作成するときはOption StrictをOnにしておきましょう



プロジェクトを作成するときには常にClass1.cs/vbというファイルがデフォルトで作成されるのでそれは消しておきました。次にしなければいけないのはUnitTestプロジェクトの参照設定です。NUnitのフレームワークをUnitTestに使用しますので、それを参照しなくてはいけません。C:\Program Files\NUnit 2.2\binにあるnunit.framework.dllをUnitTestプロジェクトにコピーします。nunit.framework.dllがあるフォルダをWindows Explorerで開いてそこから一気にソリューションエクスプローラにドラッグアンドドロップ(日本語にすると引きずり落す?)をしてしまいましょう。ちなみにコピペでもOKです。



次はそのアセンブリ(nunit.framework.dll)に対してUnitTestプロジェクトから参照をしてやります。それにはUnitTestを右クリックして参照の追加(Add Reference)を選択してやります。*ここの説明はVS初心者用です。



My Projectをダブルクリックするか、すべてのファイルを表示するにしてやると下の画像のように参照を確認することができます。デフォルトで参照が見えないのはVB.NETプロジェクトに特有でC#では常に表示されています。



NUnit Frameworkに参照を追加したのでそれが実際ちゃんと動くかどうか確かめてみましょう。UnitTestプロジェクトにSampleTest.vbというクラスファイルを追加して、次のようにコードを書きます。



このサンプルテストはMySqlLibにあるコードを試すものでも何でもなくて、単にNUnitとTest Driven .NETがきちんと動作するかどうかを確かめるものです。MyTestのあたりを右クリックしてRun Test(s)を選択してやるとTest Driven .NETがNUnitを通してMyTestを実行してくれます。Outputに下の画像のような結果が出たら成功です。



いずれはUnitTestプロジェクトに今度はMySqlLibにプロジェクト参照を追加してやり、UnitTestプロジェクトからあらゆるコードをテストできるということです。NUnitについては@ITにおいて記事がありますのでこちらを参考にしてみてください。


こんな感じでテストをする環境ができました。次のブログでは実際にMySQLに接続するコードを書いてみます。