連載:Windowsフォーム開発入門【Visual Studio 2010対応】
リモート・データ活用術〜SQL Server編〜
初音 玲
2011/02/09 |
|
|
■編集画面(ダイアログ画面)を作成
ダイアログ・ボックスとなる編集画面は、「Windows フォーム」テンプレートから独自に作成する。具体的なUIデザインは図15のとおりである。
|
図15 編集画面(ダイアログ画面)のUIデザイン |
●ShowDialogメソッドを拡張する
編集画面は、拡張したShowDialogメソッドでのみ呼び出せる(※通常のShowDiaplogメソッドでは呼び出せないようにしている)。この拡張ShowDiaplogメソッドの第3パラメータに、(Pubsデータベースの)titlesテーブルPK(PrimaryKey:主キー)であるtitle_idフィールドの値を指定して呼び出すと、PKに一致するtitlesテーブルの1レコードの内容を各コントロールに表示して、それらの値を編集する機能を、この編集画面に実装している。
拡張ShowDiaplogメソッドの実装コードは下記のとおりだ。
Private EditUserID As String = Nothing
Private EditPassword As String = Nothing
Private EditTitleID As String = Nothing
Private EditDs As DataSet = Nothing
Private IsUpdate As Boolean = False
Public Overloads Function ShowDialog(ByVal owner As IWin32Window,
ByVal userID As String,
ByVal password As String,
ByVal titleID As String) _
As DialogResult
Me.EditUserID = userID
Me.EditPassword = password
Me.EditTitleID = titleID
Return MyBase.ShowDialog(owner)
End Function |
private String EditUserID = null;
private String EditPassword = null;
private String EditTitleID = null;
private DataSet EditDs = null;
private Boolean IsUpdate = false;
public DialogResult ShowDialog(IWin32Window owner,
String userID,
String password,
String titleID)
{
this.EditUserID = userID;
this.EditPassword = password;
this.EditTitleID = titleID;
return base.ShowDialog(owner);
} |
|
リスト7 ShowDiaplogメソッドを拡張したコード例(上:VB、下:C#) |
編集画面では、ShowDialogメソッドで指定された「ID」「パスワード」「タイトルID」をフォーム・クラス内のPrivate変数に保持して、それをShownイベント・プロシージャ内で利用している。
拡張したShowDialogメソッドの中でSQL Serverに接続してデータを取得するように実装した場合、ダイアログが表示される前に実行されるため、タイトル一覧画面の右クリック・メニューの[編集]をクリックしてから、編集画面が表示されるまでに、(データ取得の時間がかかって)間が空いてしまう。これを回避するために、Shownイベント・プロシージャにこの処理を実装している。
●SQL Serverからデータを取得する
編集画面でも、(タイトル一覧画面と)同様にデータ・アクセス部分をWindowsフォームから分離したので、SQL Serverから1レコード分のデータを取得するメソッド(=サンプルではGetTitleDsItemメソッド)もDataAccessClassクラスに記述する。具体的には下記のメソッドを記述する。
Friend Function GetTitleDsItem(ByVal userID As String,
ByVal password As String,
ByVal titleID As String) As DataSet
Dim ds As New DataSet
Using _cn As New SqlConnection
_cn.ConnectionString = String.Format(My.Settings.ConnectonString,
userID,
password)
_cn.Open()
Using _cmd As New SqlCommand
_cmd.Connection = _cn
_cmd.CommandText = "SELECT * " &
"FROM titles " &
"WHERE title_id=@TitleID"
_cmd.Parameters.Add(New SqlClient.SqlParameter("TitleID", titleID))
Using _da As New SqlDataAdapter
_da.SelectCommand = _cmd
_da.Fill(ds, "EditTitle")
ds.Tables("EditTitle").PrimaryKey = New DataColumn() {ds.Tables("EditTitle").Columns("title_id")}
End Using
End Using
End Using
Return ds
End Function |
internal DataSet GetTitleDsItem(String userID, String password, String titleID)
{
DataSet ds = new DataSet();
using (SqlConnection _cn = new SqlConnection())
{
_cn.ConnectionString =
String.Format(WinFormSQLCs.Properties.Settings.Default.ConnectonString,
userID,
password);
_cn.Open();
using (SqlCommand _cmd = new SqlCommand())
{
_cmd.Connection = _cn;
_cmd.CommandText = @"SELECT * " +
"FROM titles " +
"WHERE title_id=@TitleID";
_cmd.Parameters.Add(new SqlParameter(@"TitleID", titleID));
using (SqlDataAdapter _da = new SqlDataAdapter())
{
_da.SelectCommand = _cmd;
_da.Fill(ds, "EditTitle");
ds.Tables["EditTitle"].PrimaryKey = new DataColumn[] { ds.Tables["EditTitle"].Columns["title_id"] };
}
}
}
return ds;
} |
|
リスト8 SQL Serverから1レコード・データを取得するコード例(上:VB、下:C#) |
前述のタイトル一覧取得時のSELECT文では、titleフィールドの内容に対してLIKE演算子を使ったWHERE句で(titlesテーブル内の一致する全件のデータを)検索していた。編集画面の1レコードだけ取得するSELECT文では、「PKであるtitle_idフィールドが特定の値に一致するか」をWHERE句に指定して(titlesテーブル内の一致する1件のデータを)検索している。そのほかの部分はタイトル一覧取得のときのコードと同じだ。
このようにADO.NETでは、SELECT文の記述を書き換えるだけで、取得するデータを変えることができる。
●編集画面表示時に自動的にデータを表示する
1レコードのデータを編集画面に表示するにはいろいろな手法が考えられるが、このサンプルではBindingSourceコントロールを使って画面に配置したコントロールとレコードをデータ連結している。下記のコードでは、Shownイベント・プロシージャ内にその処理を実装している。
Private Sub Me_Shown(sender As Object, e As System.EventArgs) _
Handles Me.Shown
Me.Text = String.Format(Me.Tag.ToString, EditTitleID)
Me.Cursor = Cursors.WaitCursor
Try
Using _proc As New DataAccessClass
Me.EditDs = _proc.GetTitleDsItem(Me.EditUserID,
Me.EditPassword,
Me.EditTitleID)
Me.Edit_BindingSource.DataSource = Me.EditDs.Tables("EditTitle")
Me.TitleId_TextBox.DataBindings.Add(New Binding("Text",
Me.Edit_BindingSource,
"title_id",
True,
DataSourceUpdateMode.OnValidation,
String.Empty))
:
:
(中略)
:
:
Me.Notes_TextBox.DataBindings.Add(New Binding("Text",
Me.Edit_BindingSource,
"notes",
True,
DataSourceUpdateMode.OnValidation,
String.Empty))
Me.Pubdate_DateTimePicker.DataBindings.Add(New Binding("Value",
Me.Edit_BindingSource,
"pubdate",
True,
DataSourceUpdateMode.OnValidation,
DateTime.Now.Date))
If Me.EditDs.Tables("EditTitle").Rows.Count > 0 Then
Me.OK_Button.Enabled = True
Else
Me.OK_Button.Enabled = False
End If
IsUpdate = False
End Using
Catch ex As Exception
MessageBox.Show(ex.Message, Me.Text)
Finally
Me.Cursor = Cursors.Default
End Try
End Sub |
private void Me_Shown(object sender, EventArgs e)
{
this.Text = String.Format((string)this.Tag, EditTitleID);
this.Cursor = Cursors.WaitCursor;
try
{
using (DataAccessClass _proc = new DataAccessClass())
{
this.EditDs = _proc.GetTitleDsItem(this.EditUserID,
this.EditPassword,
this.EditTitleID);
this.Edit_BindingSource.DataSource = this.EditDs.Tables["EditTitle"];
this.TitleId_TextBox.DataBindings.Add(new Binding("Text",
this.Edit_BindingSource,
"title_id",
true,
DataSourceUpdateMode.OnValidation,
String.Empty));
:
:
(中略)
:
:
this.Notes_TextBox.DataBindings.Add(new Binding("Text",
this.Edit_BindingSource,
"notes",
true,
DataSourceUpdateMode.OnValidation,
String.Empty));
this.Pubdate_DateTimePicker.DataBindings.Add(new Binding("Value",
this.Edit_BindingSource,
"pubdate",
true,
DataSourceUpdateMode.OnValidation,
String.Empty));
if (this.EditDs.Tables["EditTitle"].Rows.Count > 0)
{
this.OK_Button.Enabled = true;
}
else
{
this.OK_Button.Enabled = false;
}
IsUpdate = false;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, this.Text);
}
finally
{
this.Cursor = Cursors.Default;
}
} |
|
リスト9 編集画面表示直後にデータを表示するコード例(上:VB、下:C#) |
●編集画面の内容を保存する
BindingSourceコントロールを使ったWindowsフォームで、さらにデータ・アクセス部分を別のクラス・ファイルに分離した場合、編集画面の内容を保存するコードは(下記のとおり)極めてシンプルになる。
Private Sub OK_Button_Click(sender As System.Object,
e As System.EventArgs) _
Handles OK_Button.Click
IsUpdate = Not IsDataUpdate()
Me.DialogResult = DialogResult.OK
End Sub
Private Function IsDataUpdate() As Boolean
Dim isOK As Boolean = False
Try
Me.Edit_BindingSource.EndEdit()
Using _proc As New DataAccessClass
isOK = _proc.SetTitleDsItem(Me.EditUserID,
Me.EditPassword,
Me.EditTitleID,
Me.EditDs)
End Using
isOK = True
Catch ex As Exception
MessageBox.Show(ex.Message, Me.Text)
End Try
Return isOK
End Function |
private void OK_Button_Click(object sender, EventArgs e)
{
this.IsUpdate = !IsDataUpdate();
this.DialogResult = DialogResult.OK;
}
private Boolean IsDataUpdate()
{
Boolean isOK = false;
try
{
this.Edit_BindingSource.EndEdit();
using (DataAccessClass _proc = new DataAccessClass())
{
isOK = _proc.SetTitleDsItem(this.EditUserID,
this.EditPassword,
this.EditTitleID,
this.EditDs);
}
isOK = true;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, this.Text);
}
return isOK;
} |
|
リスト10 編集画面の内容を保存するコード例(上:VB、下:C#) |
BindingSourceコントロールを使用しているので、そのEndEditメソッド(=上記のコードでは「Edit_BindingSource.EndEditメソッド」)を実行するだけで、BindingSourceコントロールを経由して、編集画面の内容をデータセットに反映できる。DataAccessClassクラスのSetTitleDsItemメソッドにより、そのデータセットの内容をSQL Serverに保存している。
●SQL Serverにデータを保存する
呼び出されたSetTitleDsItemメソッド内では、データアダプタ(=下記のコードでは「SqlDataAdapter」)のUpdateメソッドにより、データセットの内容をSQL Serverに保存している。
Updateメソッドを実行するには、UPDATE文、INSERT文、DELETE文のSQL文をデータアダプタにあらかじめ設定しておかなければならない。これらのSQL文をすべて手動でコーディングしてもいいが、ADO.NETではSELECT文からUPDATE文、INSERT文、DELETE文を生成してくれるコマンド・ビルダ(=下記のコードでは「SqlCommandBuilder」)が提供されている。
以上の内容を実装したのが下記のコードだ。
Friend Function SetTitleDsItem(userID As String,
password As String,
titleID As String,
ds As DataSet) As Boolean
Dim isOK As Boolean = False
Using _cn As New SqlConnection
_cn.ConnectionString = String.Format(My.Settings.ConnectonString,
userID,
password)
_cn.Open()
Using _tr As SqlTransaction = _cn.BeginTransaction
Try
Using _cmd As New SqlCommand
_cmd.Connection = _cn
_cmd.Transaction = _tr
_cmd.CommandText = "SELECT * " &
"FROM titles " &
"WHERE title_id=@TitleID"
_cmd.Parameters.Add(New SqlParameter("TitleID", titleID))
Using _da As New SqlDataAdapter
_da.SelectCommand = _cmd
Using _cb As New SqlCommandBuilder(_da)
_cb.ConflictOption = ConflictOption.OverwriteChanges
_cb.GetInsertCommand(True).Connection = _cn
_cb.GetInsertCommand(True).Transaction = _tr
_cb.GetUpdateCommand(True).Connection = _cn
_cb.GetUpdateCommand(True).Transaction = _tr
_cb.GetDeleteCommand(True).Connection = _cn
_cb.GetDeleteCommand(True).Transaction = _tr
_da.Update(ds, "EditTitle")
End Using
_tr.Commit()
End Using
isOK = True
End Using
Catch ex As Exception
_tr.Rollback()
Throw ex
End Try
End Using
End Using
Return isOK
End Function |
internal Boolean SetTitleDsItem(String userID, String password, String titleID, DataSet ds)
{
Boolean isOK = false;
using (SqlConnection _cn = new SqlConnection())
{
_cn.ConnectionString =
String.Format(WinFormSQLCs.Properties.Settings.Default.ConnectonString,
userID,
password);
_cn.Open();
using (SqlTransaction _tr = _cn.BeginTransaction())
{
try
{
using (SqlCommand _cmd = new SqlCommand())
{
_cmd.Connection = _cn;
_cmd.Transaction = _tr;
_cmd.CommandText = @"SELECT * " +
"FROM titles " +
"WHERE title_id=@TitleID";
_cmd.Parameters.Add(new SqlParameter(@"TitleID", titleID));
using (SqlDataAdapter _da = new SqlDataAdapter())
{
_da.SelectCommand = _cmd;
using (SqlCommandBuilder _cb = new SqlCommandBuilder(_da))
{
_cb.ConflictOption = ConflictOption.OverwriteChanges;
_cb.GetInsertCommand(true).Connection = _cn;
_cb.GetInsertCommand(true).Transaction = _tr;
_cb.GetUpdateCommand(true).Connection = _cn;
_cb.GetUpdateCommand(true).Transaction = _tr;
_cb.GetDeleteCommand(true).Connection = _cn;
_cb.GetDeleteCommand(true).Transaction = _tr;
_da.Update(ds, "EditTitle");
}
_tr.Commit();
}
isOK = true;
}
}
catch (Exception ex)
{
_tr.Rollback();
throw ex;
}
}
}
return isOK;
} |
|
リスト11 SQL Serverにデータを保存するコード例(上:VB、下:C#) |
最後に、ここまでに作成してきたアプリケーションを完成させよう。
業務アプリInsider 記事ランキング
本日
月間