C# [データベース]

C# にはデータベースを簡単に扱えるコンポーネントが多数用意されています。 開発工数を大幅に簡略化できそうです。
更新日 2016-02-13

DataSet クラスを使う

DataSet クラスは、初期ロード後はオフラインで作業できるようにする為のデータベースのキャッシュ機能を提供してくれます。

データの取り込み

MySQL server に繋ぐにはMySQL Connector/Net をインストールしておきます。VisualStudio2012 での開発環境で使う場合は、MySQL Installerの方を入れます。
#using  MySql.Data.MySqlClient;

String strConnect = "Server=MySQLServer;User Id=user;Password=pass;Database=ast_db";
MySqlConnection mySqlConnection = null;
ast_dbDataSet dsAstDB = null;

try
{
	mySqlConnection = new MySqlConnection(strConnect);

	// connect
	mySqlConnection.Open();

	// check connection state
	if (mySqlConnection.State == ConnectionState.Open)
    {
		// excute sql and fill dataset result.
		dsAstDB = new ast_dbDataSet();

		// .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
		// articles
		{
			MySqlDataAdapter mySqlDataAdapter = new MySqlDataAdapter(
				"select * from articles", mySqlConnection);
			mySqlDataAdapter.Fill(dsAstDB, "articles");

			dsAstDB.articles.PrimaryKey = new DataColumn[] {
				dsAstDB.articles.Columns["pic"]
			};
		}
		// .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
	}
}
catch (Exception ex)
{

}
finally
{
	mySqlConnection.Close();
	mySqlConnection = null;
}

データの操作

DataSet 内のテーブルには自由にアクセスできます。また内容の変更を施した場合は、 その旨が内部にログとして自動的に記憶されてゆきます。
String strPic = "001";

// 要cast                    
ast_dbDataSet.articlesRow dRow = 
    (ast_dbDataSet.articlesRow)dsAstDB.articles.Rows.Find(strPic);
                    
if (dRow.visible != bVisible)
{
	dRow.visible = bVisible;
}

変更されたデータをデータベースに反映

DataSet に施された更新をデータベースにも同じように反映させる事ができます。 実に効率的で大変便利です。
String strConnect = "Server=MySQLServer;User Id=user;Password=pass;Database=ast_db";
MySqlConnection mySqlConnection = null;

try
{
	mySqlConnection = new MySqlConnection(strConnect);

	// connect
	mySqlConnection.Open();

	// update table articles.
	MySqlDataAdapter mySqlDataAdapter = 
		new MySqlDataAdapter("select * from articles", mySqlConnection);

	MySqlCommandBuilder mySqlCommandBuilder = new MySqlCommandBuilder(mySqlDataAdapter);
	mySqlDataAdapter.ContinueUpdateOnError = true;
	mySqlDataAdapter.Update(dsAstDB, "articles");

    // change all dataset's modify flag to nochange.
    dsAstDB.AcceptChanges();
}
finally
{
	mySqlConnection.Close();
    mySqlConnection = null;
}

注意点

オフラインで使うという事は処理速度や回線の負担軽減には役立ちますが、複数の異なるユーザーから 頻繁に更新が行われるという状況ではデータの整合性を保つ為の実装も求められるでしょう。

Timestamp は使うべからず

MySqlCommandBuilder はupdate の時に、変更前の全カラムの値をwhere 文で指定してきます。 ところがTimestamp は更新時のサーバー側の時刻で設定されるため、最初のUpdate でもって更新されてしまうと、 以降はDataSet 側の値と合わなくなり「行が見つからず更新できませんでした」となります。
自動更新されない DATETIME 型に変更しましょう。

DataGridView を使う

DataGridView クラスはDataSet クラスのテーブル内容を表示したり編集できたりする、まるで エクセルのようなコンポーネントです。大変使いやすく、カスタマイズも柔軟な優れものです。

DataView を使った抽出

テーブルデータから特定条件による抽出を行ったDataView を作り、それをDataGridView に表示します。DataView のコンストラクタでも作れますが、 より柔軟なクエリが使えるLINQ を使う事にします。
EnumerableRowCollection<DataRow> query = 
	from p in dsAstDB.Tables["articles"].AsEnumerable()
	where ((((p.RowState & DataRowState.Deleted) != DataRowState.Deleted)) &&
          (p.IsNull("name") == false) && p.Field<String>("name").Length != 0
    orderby p.Field<String>("name_kana")
	select p;

DataView dataView = query.AsDataView();
dataView.Sort = "name_kana";
                
this.m_dataGridView_Users.DataSource = dataView;

削除された行を通して、その行の情報にアクセスすることはできません。

order by を含むLinq to DataSet において、データセットの一部をdelete してデータベースに反映させると 「System.Data.DeletedRowInaccessibleException: 削除された行を通して、その行の情報にアクセスすることはできません。」 というエラーが出ます。あからじめwhere 句でdelete された列を除いておきます。
もしくはDataView 側でソートを行います。

セルの書式やテキストをランタイムで変更する

DataGridView のCellFormatting イベントハンドラを実装します。
private void dataGridView_CellFormatting(object sender, 
DataGridViewCellFormattingEventArgs e)
{
    if (e.ColumnIndex == 1)
    {
        String strPic = e.Value.ToString();

        DataRow dRow = dsAstDB.Tables["articles"].Rows.Find(strPic);

        int nStatus = (int)dRow["status"];
        if (nStatus == 0)
        {
            Color bgColor = Color.LightBlue;

            e.CellStyle.BackColor = bgColor;
            e.FormattingApplied = true;

            DataGridViewRow dgvRow = this.m_dataGridView_Orders.Rows[e.RowIndex];
            dgvRow.Cells[3].Style.BackColor = bgColor;
        }
    }
	else if (e.ColumnIndex == 4)
    {
        e.Value = "(" + e.Value + ")";
        e.FormattingApplied = true;
    }
}