連載:VS 2005でいってみようDBプログラミング

第6回 データソース・コントロールでいってみよう(前編)

山田 祥寛(http://www.wings.msn.to/
2006/07/29
Page1 Page2 Page3

データベースの内容をDataSetオブジェクトとして取得する

 さて、ObjectDataSourceコントロールの基本的な動作を確認できたところで、同じく取得結果をDataSetとして返すGetBooksDataSetメソッドを作成してみましょう(リスト2)。

 第3回でも述べたように、DataReaderが前方への読み取り専用の手段を提供するシンプルなオブジェクトであるのに対して、DataSetはメモリ上に常駐する仮想的なデータベースのようなものであり、内部的にテーブルやリレーションシップを表現できる高機能なオブジェクトです。取得したデータのソートやキャッシュなどを行いたい場合には、データをDataSetオブジェクトとして取得する必要があります。

 リスト1のBookクラスに、次のリスト2で示すgetBooksDataSetメソッドを追加します。

<DataObjectMethod(DataObjectMethodType.Select, False)> _
Public Function getBooksDataSet(ByVal publish As String) As DataSet

  Dim setting As ConnectionStringSettings = _
     ConfigurationManager.ConnectionStrings("MyDB")

  Dim factory As DbProviderFactory = _
    DbProviderFactories.GetFactory(setting.ProviderName)

  Dim db As DbConnection = factory.CreateConnection()
  db.ConnectionString = setting.ConnectionString

  Dim adapter As DbDataAdapter = factory.CreateDataAdapter()
  Dim comm As DbCommand = factory.CreateCommand()
  comm.Connection = db
 
  If publish <> "-" Then
    comm.CommandText = _
      "SELECT * FROM books WHERE publish=@publish"
    Dim param As DbParameter = factory.CreateParameter()
    param.ParameterName = "@publish"
    param.Value = publish
    comm.Parameters.Add(param)
  Else
    comm.CommandText = "SELECT * FROM books"
  End If
 
  Dim ds As New DataSet()
  adapter.SelectCommand = comm
  adapter.Fill(ds, "books")
  Return ds
End Function
リスト2 Book.vbに追加するgetBooksDataSetメソッド

 DataSetオブジェクトにデータを格納するには、DbDataAdapterオブジェクトを使用します。DbDataAdapterオブジェクトを取得するには、DbProviderFactoryオブジェクトのCreateDataAdapterメソッドを使用します(リスト2- )。

 データ取得に使用するDbCommandオブジェクトをSelectCommandプロパティにセットします(リスト2- )。DbCommand/DbParameterオブジェクトの設定方法については、前項の説明を参照してください。

 あとは、Fillメソッドを呼び出してDataSetオブジェクトにSELECTメソッドの結果を流し込むだけです(リスト2- )。Fillメソッドはデータ取得時に自動的にデータベースへの接続を確立し、取得後に即座に切断しますので、明示的にCloseメソッドを呼び出す必要はありません。Fillメソッドの第2パラメータには、DataSet内でのテーブル名を指定します。

 これでDataSetオブジェクトの取得手続きは完了です。データソース構成ウィザードから[SELECT]メソッドを「getBooksDataSet(String publish)、戻り値 DataSet」と選択し直したうえで実行してみましょう。先ほどと同様の結果が得られれば成功です。

ObjectDataSourceコントロールに削除機能を実装する

 以上、ObjectDataSourceコントロールによるデータ取得の手順を見てきましたが、もちろん、ObjectDataSourceコントロールでもSqlDataSourceコントロールと同様、挿入/更新/削除処理を実装することが可能です。

 ここでは、既存の書籍情報を削除するdeleteBookメソッド(リスト3)を定義してみることにします。

<DataObjectMethod(DataObjectMethodType.Delete, True)> _
Public Sub deleteBook(ByVal isbn As String)

  Dim setting As ConnectionStringSettings = _
     ConfigurationManager.ConnectionStrings("MyDB")

  Dim factory As DbProviderFactory = _
    DbProviderFactories.GetFactory(setting.ProviderName)

  Using db As DbConnection = factory.CreateConnection()
    db.ConnectionString = setting.ConnectionString
   
    Dim adapter As DbDataAdapter = factory.CreateDataAdapter()
    Dim comm As DbCommand = factory.CreateCommand()
    comm.CommandText = _
        "DELETE FROM books WHERE isbn=@isbn"
   
    Dim param As DbParameter = factory.CreateParameter()
    param.ParameterName = "@isbn"
    param.Value = isbn
   
    comm.Parameters.Add(param)
    comm.ExecuteNonQuery()
  End Using
End Sub
リスト3 Book.vbに追加するdeleteBookメソッド

 ここで注目していただきたいのは、以下の2点です。

■オブジェクトを自動破棄するUsingステートメント(リスト3-

 第1回でも紹介したように、.NET FrameworkのCLR(Common Language Runtime)はアプリケーションのメモリ管理を一手に担っていますので、不要になったメモリは任意のタイミングでガベージ・コレクタにより自動的に解放されます(ガベージ・コレクション機能)。

 もっとも、ガベージ・コレクタによるメモリ解放は必ずしもリアルタイムに行われるわけではありません。しかし、データベース接続のような限られた高価なリソースはなるべく早いタイミングで解放するべきです。1人のユーザーがリソースを占有してしまうと、ほかのユーザーがそのリソース(ここではデータベース接続)を利用した処理を行うことができなくなってしまうためです。よってデータベースを利用した後は、できるだけ速やかにCloseメソッドを呼び出し、接続を解放する必要があります。

 しかしより厳密には、単にCloseメソッドを呼び出すだけでは十分ではありません。というのも、Openメソッドによって接続が確立された後、何らかの理由で正常に切断される前に例外が発生してしまったとしたらどうでしょう。Closeメソッドが呼び出されないため、接続が解放されないままになってしまいます(このような状態のことを「コネクション・リーク」といいます)。これを防ぐために、Try〜Finallyブロックを利用して、以下のようなコードを記述することが可能です。

Try
  db.Open()
  ' ……任意のデータベース処理……
Finally
  db.Close()
End Try
Try〜Finallyブロックを利用したデータベース接続の解放
データベース処理の最中に例外が発生してもFinallyブロックは実行されるため確実に接続を解放できる。

 しかしコードが冗長になるうえに、一見して本来の例外処理との区別がつきにくくなるなどの理由から、必ずしも最適のアプローチとはいえません。そこで登場するのが、Visual Basic 2005から追加されたUsingステートメントなのです*5

 Usingステートメントを使用して宣言されたオブジェクトは、Usingブロックを抜けるタイミングで(End Usingの個所で)即座に破棄されます。データベースへの接続コードを記述する場合の重要な構文ですので、ここでしっかりと押さえておきたいところです。

*5 ちなみに、C#では.NET Framework 1.xからusingステートメントを利用できます。

■結果を返さないSQL命令はExecuteNonQueryメソッドで(リスト3-

 先ほど紹介したExecuteReaderメソッドは、結果セットを返すSELECT命令を発行するためのメソッドです。INSERT/UPDATE/DELETEのような結果を返さないSQL命令を発行する場合には、ExecuteNonQueryメソッドを使用してください。ExecuteNonQueryメソッドは戻り値としてINSERT/UPDATE/DELETE命令を実行した結果、影響を受けたレコード数を返します。

 ちなみに、SELECT命令でも(例えば)SUM、AVG、COUNTのような集計関数を用いており、あらかじめ単一の値が返されることが分かっている場合には、ExecuteScalarメソッドを使用することが可能です。このメソッドを使用した場合、データベースから返された結果セットの先頭行先頭列の値をスカラー値として返します。ただし、SELECT命令が複数列複数行を返した場合にも、ExecuteScalarメソッドは先頭行先頭列の値だけを返し、ほかの値は無視されますので注意してください。

 リスト3については、以上の2点以外はすでに解説済みです。これでデータアクセス・コンポーネント側の実装は完了です。

 「.aspx」ファイルの側でも、削除機能を有効にするためのいくつかの設定を施しておくことにしましょう。GridViewコントロールのDataKeyNamesプロパティに主キー列である「isbn」を指定したうえで、タスク・メニューから[削除を有効にする]をチェックしてください。

 DataKeyNamesプロパティはデータの主キー列を表すためのプロパティです。SqlDataSourceコントロールではデータソース構成ウィザードによって自動設定されていたため、開発者が意識する必要はありませんでしたが、ObjectDataSourceコントロールを利用している場合には明示的にプロパティ・ウィンドウから設定しておく必要があります。本プロパティが設定されていない場合、正しく更新や削除を行うことができませんので注意してください。

 以上の手順を終えたら、ObjectDataSource.aspxを実行してみましょう。グリッド上の削除ボタンをクリックし、正しく該当のデータが削除されれば成功です。

 以上、今回はObjectDataSourceコントロールを利用して、データアクセス・コンポーネント経由でデータソースにアクセスし、データアクセス・コントロールに展開する方法について紹介しました。

 ページの都合上、本稿では選択/削除機能についてのみ紹介しましたが、同様の要領で、必要なパラメータを受け取るメソッドを定義すれば、挿入/更新機能を実装することも可能です。余力のある方は、ぜひ試してみてください。

 次回は、引き続きObjectDataSourceをはじめ、AccessDataSource、XmlDataSourceコントロールなどデータソース・コントロールを扱う予定です。どうぞお楽しみに。End of Article


 INDEX
  Visual Studio 2005でいってみようDBプログラミング
  第6回 データソース・コントロールでいってみよう(前編)
    1.データアクセス・コンポーネントを作成する
    2.ObjectDataSourceコントロールを設定する
  3.ObjectDataSourceコントロールに削除機能を実装する
 
インデックス・ページヘ  「Visual Studio 2005でいってみようDBプログラミング」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間