DataSetを使ってMySQLを扱う場合の勘所

タイトルに「MySQL」とありますが、旧来のDataSet/DataTableを使う場合のコツ、と思ってください。
# SQL to LINQ や ADO.NET Entity Framework を使う場合は、もうちょっと別なスタイルもありです。

業務アプリケーションでデータベースを扱う場合、利用方法は次のパターンに分けられます。

<001>

20100831_04.jpg 

データベースは次の2種類

・更新系のテーブル
 → 頻繁に更新するデータ
 → 売上データ、月次データなど
・マスター系のテーブル
 → ほとんど更新しないデータ
 → 部門情報、会社名一覧など

これを操作する画面が次の2種類

・一般の画面
 → 主に更新用のテーブルを扱う画面
 → 一般ユーザーが使うので、利用しやすい画面にしないと駄目
・マスタ画面
 → 主にマスタ系のテーブルを扱う
 → 保守に利用するためなので、チープ画面でよい。SEが使う。

これで、DataSetを直接扱うと良いのが、図のなかで「D」(DataSet)となっているところです。

・一般画面から更新系DBへ
 → キャッシュとして、DataSetに保持しておく。
 → 部門の一覧をコンボボックスで表示とか。
・マスタ画面からマスタ系DBへ
 → グリッドやリストなどの自動バインド(DataSource)にDataSetを直接指定。
 → DataSetの内容を直接マスタに書き込んでしまう。

一般画面から更新系DBへの矢印は、SqlCommandを使ってちまちまと更新します。
ちまちま更新は、ストアドプロシージャにしてもOK。しなくてもOK。パラメータは必須(にすると良い)。

このパターンを、MVCに当てはめると(というか、ベースがMVCなのです。このパターン/考え方は2000年頃から使っている)、

<002>

20100831_01.jpg

画面のほうは、いわずもがなの「View」、
参照系のキャッシュ部分は、「Model」、
更新系は直接データベースを扱う(SqlCommandで)ので「Controller」に相当します。

デスクトップ系のアプリケーションを作る場合、VB6(.NETにあらず)の頃は、このデータベースを扱う部分がViewに分散してしまうので、実際の開発(多人数の開発)では、もうひと工夫必要です。

開発プロジェクトの特性として、全てベテランプログラマで揃えらえることはまれです。というか、オープンソースのプロジェクトぐらいしかないでしょう。業務の場合は必ず「新人」と「ベテラン(中堅)」がいます。
そうすると、新人と中堅の技術差があります。あって当然です。

なので、この技術差をうまく活かすために、次のように配置をします。

<003>

20100831_03.jpg

新人は画面側を担当します。これは、新人の弾くスキルでは、画面、SQLなどの両方をこなすのが難しいという点。長期に続いていたプロジェクトだと、データベース周りは既に社内にいる人間しかわからないという状態になっているので覚えることが多すぎるので、できるだけデータベースから遠くに置くためです。
なので、中堅、ベテランは、新人がデータベースを扱えるように「DAO(Data Access Object)」を作ります。このDAOは、O/Rマッピングでも良いし、単なる関数呼び出しでもよいし、手順書でも良いのです。役目としては「新人をデータベースから遠くに置く」ためです。新人は「データベース」を扱いたいのではなく、「データ」を扱いたいのですから。

DAO(Data Access Object)の利点は、このほかにも、

・開発中のデータベース構造が変わっても、DAOが吸収できる(可能性がある)。
・ワンクッションあるので、実行ログがとりやすい。
・ViewにデータアクセスのSQL文が分散するのを防ぐ。

というものがあります。

一例としては、

class DAO会計情報
{
 // マスターデータの参照として使う
 // 直接使えるように公開してしまう
 public DataTable ds部署一覧;
 public DataTable ds会社一覧;
 public DataTable ds取引先一覧;

 // 更新系はメソッドを用意する。
 public bool Update月次( … );
 public bool Update日報( … );
 // 情報を取得する場合とか
 public DataTable Get月次一覧( string 個人名 );
}

のようなクラスを用意しておいて、新人には、


list部署一覧.DataSource = 会計情報.ds部署一覧
list会社一覧.DataSource = 会計情報.ds会社一覧
dv取引先.DataSource = 会計情報.ds取引先一覧

で画面を設定させて、保存ボタンを押したときに、

if ( 会計情報.Update月次( … ) == false )
{
 // 何か失敗したので、エラーメッセージ
 return ;
}
// 更新に成功した


な感じで使って貰う、という形です。

適宜、DAOの種類は増やしてください。トランザクション系もDAOに押し込めると、画面からトランザクションを意識しなくてよくなるので便利です。

Update等の戻り値は、本来は例外がいいのでしょうが、bool値とかにするほうが経験的に間違いが少なくなります。新人の「慣れ」によって適宜作ると良いかと。

このDAOの使い方をするとですね、実はテストがしやすいのです。
DAO自体に実行ログを入れるのもそうですが、うまく作ってやるとテストデータをDAOに直接読み込ませることができます。
また、単体でDAOのテストが可能になるので(MVCの良い特徴として)、NUnitなどのUnitTestが使えます。

ええと、一応、欠点も書き並べておくと、こんな感じです。

・テーブルを変更した場合、DAOも書き換わるので、手間が掛かる。
 → 各画面にSQLが散らなくていいけど、DAOが一手に引き受けるので。
・画面系が早く終わって、DAOが出来ていないとテストができない。
 あるいは、DAOのインターフェースを決めないと、画面が作れない。
 → ひとまず、インターフェースだけ先に作って、仮ビルドしてリリースします。
 → なので、DAOを使う場合は、設計が勝負どころです。
・画面が複数社に分かれる時は、DAOが使いづらい。
 → DAOを作成専門の会社/人がいればいいのですが、請負で数社に分かれると大抵破綻します。
 → なので、「身を守るために」自社だけこっそりDAO形式を使う、というのがベターです。

先日のドットネットラボの懇親会でも愚痴りましたが、理想的には「DBA(データベース管理者)」が、データベースアクセス周りを作ればよいのですが、現実問題として日本のソフトウェア業界では無理です。大規模システムの場合、元請け会社がデータベース周りを扱うことが多く、画面やその他の割り振りを子会社/孫会社に振ります。なので、データベース周り(本来DAOの部分)と画面系の部分が、会社/契約として分離されてしまうため、「大手の新人SEがDBA」を担当するという事態が発生しますし、請負→発注元という要求の通りにくいラインが邪魔をしてしまいます。
という訳で、「DBA」を前提としているデータベース技術はちょっと疑問なのですなぁ、と。

ま、それは兎も角、現実的なラインを探さないといけないわけで、最近では、幸いなことにデータベース構造までも丸投げする場合が多いし、MySQLを使った小規模の開発ならば、この手法が使えます。
ので、お試しあれ。

カテゴリー: 開発, MySQL パーマリンク

DataSetを使ってMySQLを扱う場合の勘所 への2件のフィードバック

  1. konica のコメント:

    お・・なるほど。
    実際、同じDBでなくて、参照させる様に、
    更新DB・マスターと分けるのは理解。
    早速実践してみますね。

  2. masuda のコメント:

    おぉ、こんな記事を書いていたのか。今やっていることと同じだ。ぶれてない>俺。

コメントは停止中です。