DataGridに行の編集機能を追加 (ch56DataGrid1.aspx)

 

ここで作成するサンプルは、DataGridOracleデータベースのCustomers表をバインドして表示します。

 

Customers表から行(レコード)を抽出するには、パッケージ(CustomerPackage)に登録されているストアドプロシージャ(GetCustomersGT40)を使用します。Customers表の行を更新するには、ストアドプロシージャ(UpdateCustomers)を使用します。

 

iSQL*PlusまたはSQL*Plusを起動して、事前にパッケージ仕様部(C:\vbora\sql\CustomerPackage.sql)とパッケージ本体部(C:\vbora\sql\CustomerPackageBody.sql)を作成してください。

 

パッケージ仕様部(CustomerPackage.sql)

CREATE OR REPLACE PACKAGE CustomerPackage AS

  TYPE rcurCustomers IS REF CURSOR;

  PROCEDURE GetCustomersGT40(

    orcurCustomers OUT rcurCustomers);

  PROCEDURE UpdateCustomers(

    iCompanyName IN VARCHAR2,

    iContactName IN VARCHAR2,

    iPhone IN VARCHAR2,

    iCustomerID IN NUMBER);

END CustomerPackage;

 

 

パッケージ本体部(CustomerPackageBody.sql)

CREATE OR REPLACE PACKAGE BODY CustomerPackage AS

  PROCEDURE GetCustomersGT40(

    orcurCustomers OUT rcurCustomers) IS

  BEGIN

    OPEN orcurCustomers FOR

      SELECT *

FROM Customers

      WHERE CustomerID > 40

      ORDER BY CustomerID;

  END GetCustomersGT40;

  PROCEDURE UpdateCustomers(

    iCompanyName IN VARCHAR2,

    iContactName IN VARCHAR2,

    iPhone IN VARCHAR2,

    iCustomerID IN NUMBER) IS

  BEGIN

    UPDATE Customers

    SET CompanyName = iCompanyName,

       ContactName = iContactName,

       Phone = iPhone

    WHERE CustomerID = iCustomerID;

  END UpdateCustomers;

END CustomerPackage;

 

このサンプルでは、以下のノウハウを習得することができます。

 

DataGridに編集機能を追加する方法

DataGridの連結列を読み取り専用にする方法

DataGridに編集ボタン列を作成する方法

DataGridEditCommandイベントの使い方

DataGridUpdateCommandイベントの使い方

DataGridCancelCommandイベントの使い方

DataGridオブジェクトのEditItemIndexプロパティの使い方

DataGridオブジェクトのDataKeyFieldコレクションの使い方

▼更新用のストアドプロシージャから更新したレコード件数を取得する方法

▼更新用のストアドプロシージャに楽観的ロックを組み込む方法

▼更新処理にトランザクションを適用する方法

PS/SQLの暗黙カーソル(SQL%ROWCOUNT)の使い方

 

 

1. Webフォーム追加

 

ソリューションエクスプローラからフォルダ[ch5]を右クリックして、新規Webフォーム「ch56DataGrid1」を追加します。

 

2. DataGrid作成

 

ツールボックスの[Webフォーム]から、DataGridをドラッグ&ドロップします。デザイナにDataGrid1のオブジェクトが作成されます。

 

3. 自動フォーマット

 

DataGrid1の右クリックから[自動フォーマット]を選択します。「自動フォーマット」が表示されたら、「スキームの選択」から[プロフェッショナル1]を選択して、[OK]をクリックします。

 

4. 連結列作成

 

DataGrid1の右クリックから[プロパティビルダ]を選択します。「DataGird1プロパティ」が表示されたら、左側から[]を選択します。[実行時に自動的に列を作成する]をクリックしてチェックを外します。「使用可能な列」から[連結列]を選択してiconRightArrowをクリックします。「選択された列」に連結列が表示されたら、連結列(BoundColumn)プロパティの「ヘッダーテキスト」に「ID」、「データフィールド」に「CustomerID」を入力します。[読み取り専用]をクリックしてチェックマークを付けます。同様の手順で、得意先、担当、電話の連結列を作成します。

 

連結列(BoundColumn)プロパティ

ヘッダーテキスト

データフィールド

読み取り専用

ID

CustomerID

チェック

得意先

CompanyName

 

担当

ContactName

 

電話

Phone

 

 

fig5-6-1

プロパティビルダの[]から連結列作成

 

5. 編集ボタン列作成

 

「プロパティビルダ」の「使用可能な列」から[ボタン列]をクリックして展開します。[編集、更新、キャンセル]を選択したら、iconRightArrowをクリックします。右側の「選択された列」に編集ボタンが表示されます。編集ボタン列(EditCommandColumn)プロパティの「テキストのキャンセル[1]」を「中止」に書き換えます。「ボタンの種類」から[PushButton]を選択します。

 

fig5-6-2

プロパティビルダの[]から編集ボタン列作成

 

6. ヘッダーを中央揃え

 

「プロパティビルダ」の左側から[書式]を選択したら、画面中央の「オブジェクト」から[ヘッダー]を選択します。「水平方向の配置」から[中央]を選択してヘッダーを中央揃えに設定します。

 

fig5-6-3

プロパティビルダの[書式]からヘッダーの書式設定

 

7. IDの連結列を右揃え

 

「プロパティビルダ」の「オブジェクト」から[]をクリックして展開します。[Columns[0]-ID]をクリックして展開したら[項目]を選択します。「水平方向の配置」から[]を選択して、IDを右揃えに設定します。

 

fig5-6-4

図プロパティビルダの[書式]からIDの書式設定

 

8. 編集ボタン列を中央揃え

 

「プロパティビルダ」の左側から[書式]を選択したら、画面中央の「オブジェクト」から[Columns[4]]をクリックして展開します。[項目]を選択したら、「水平方向の配置」から[中央]を選択して編集列ボタンを中央揃えに設定します。最後に、[OK]をクリックしてダイアログを閉じます。

 

fig5-6-5

プロパティビルダの[書式]から編集列ボタンの書式設定

 

 

9. コードビューに切り替え

 

メニューバーから[表示][コード]を選択してコードビューに切り替えます。クラスモジュールの先頭に、以下のImportsステートメントを追加します。

 

Imports System.Data

Imports Oracle.DataAccess.Client

Imports Oracle.DataAccess.Types

 

Page_Loadイベントに、以下のコードを追加します。

 

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs)

cccHandles MyBase.Load

  If Not IsPostBack Then

    BindGrid()

  End If

End Sub

 

クラスモジュールの最後に、Sub BindGridFunction CreateDataSetを追加します。

 

Private Sub BindGrid()

  With DataGrid1

    .DataSource = CreateDataSet("CustomerPackage.GetCustomersGT40")

    .DataKeyField = "CustomerID"

    .DataBind()

  End With

End Sub

 

Private Function CreateDataSet(ByVal strPackage As String) As DataSet

  Dim con As New OracleConnection(ConfigurationSettings.AppSettings("conStringOraNw"))

  Dim cmd As New OracleCommand(strPackage, con)

  Dim da As New OracleDataAdapter

  Dim ds As New DataSet

 

  cmd.CommandType = CommandType.StoredProcedure

  cmd.Parameters.Add("1", OracleDbType.RefCursor, ParameterDirection.Output)

  da.SelectCommand = cmd

  da.Fill(ds)

  Return ds

End Function

 

10. EditCommandイベント作成

 

コードビュー左上の「クラス名」のドロップダウンリストから[DataGrid1]を選択します。右上の「メソッド名」のドロップダウンリストから[EditCommand]を選択します。DataGrid1_EditCommandイベントが作成されたら、以下のコードを追加します。

 

Private Sub DataGrid1_EditCommand(ByVal source As Object,

cccByVal e As System.Web.UI.WebControls.DataGridCommandEventArgs)

cccHandles DataGrid1.EditCommand

  DataGrid1.EditItemIndex = e.Item.ItemIndex

  BindGrid()

End Sub

 

 

11. CancelCommandイベント作成

 

コードビュー左上の「クラス名」のドロップダウンリストから[DataGrid1]を選択します。右上の「メソッド名」のドロップダウンリストから[CancelCommand]を選択します。DataGrid1_CancelCommandイベントが作成されたら、以下のコードを追加します。

 

Private Sub DataGrid1_CancelCommand(ByVal source As Object,

cccByVal e As System.Web.UI.WebControls.DataGridCommandEventArgs)

cccHandles DataGrid1.CancelCommand

  DataGrid1.EditItemIndex = -1

  BindGrid()

End Sub

 

12. UpdateCommandイベント作成

 

コードビュー左上の「クラス名」のドロップダウンリストから[DataGrid1]を選択します。右上の「メソッド名」のドロップダウンリストから[UpdateCommand]を選択します。DataGrid1_UpdateCommandイベントが作成されたら、以下のコードを追加します。

 

Private Sub DataGrid1_UpdateCommand(ByVal source As Object,

cccByVal e As System.Web.UI.WebControls.DataGridCommandEventArgs)

cccHandles DataGrid1.UpdateCommand

  Dim strCompanyName As String = CType(e.Item.Cells(1).Controls(0), TextBox).Text

  Dim strContactName As String = CType(e.Item.Cells(2).Controls(0), TextBox).Text

  Dim strPhone As String = CType(e.Item.Cells(3).Controls(0), TextBox).Text

  Dim intCustomerID As Integer = DataGrid1.DataKeys(e.Item.ItemIndex)

 

  UpdateRecord(strCompanyName, strContactName, strPhone, intCustomerID)

  DataGrid1.EditItemIndex = -1

  BindGrid()

End Sub

 

DataGrid1_UpdateCommandイベントの後に、Function UpdateRecordを追加します。

 

Private Function UpdateRecord(ByVal strCompanyName As String, _

  ByVal strContactName As String, _

  ByVal strPhone As String, _

  ByVal intCustomerID As Integer) As Integer

 

  Dim con As New OracleConnection(ConfigurationSettings.AppSettings("conStringOraNw"))

  Dim cmd As New OracleCommand("CustomerPackage.UpdateCustomers", con)

 

  With cmd

    .CommandType = CommandType.StoredProcedure

    .BindByName = True

    .Parameters.Add("iCompanyName", OracleDbType.Varchar2, 40).Value = strCompanyName

    .Parameters.Add("iContactName", OracleDbType.Varchar2, 30).Value = strContactName

    .Parameters.Add("iPhone", OracleDbType.Varchar2, 24).Value = strPhone

    .Parameters.Add("iCustomerID", OracleDbType.Int32).Value = intCustomerID

  End With

 

  con.Open()

  Dim intRetValue As Integer = cmd.ExecuteNonQuery()

  con.Close()

  Return intRetValue

End Function

 

13. ブラウザに表示

 

ソリューションエクスプローラから[ch56DataGrid1.aspx]を右クリックしてブラウザに表示します。DataGridCustomers表が表示されます。DataGridの右端に表示されている[編集]をクリックします。得意先、担当、電話の列がテキストボックスに表示されます。[更新]をクリックすると行(レコード)を更新します。[中止]をクリックすると、変更された内容を無効にします。

 

fig5-6-6

DataGrid[編集]ボタンをクリックして編集モードに切り替えた例

 

 

■解説

 

DataGridに編集機能を組み込むには、「プロパティビルダ」の[]から[編集ボタン列]を追加します。編集ボタン列には、[編集][更新][キャンセル]の3個のボタンが含まれています。「テキストの編集」には、編集ボタンに表示する表題を入力します。デフォルトで「編集」が表示されます。編集ボタン列プロパティの「テキストの更新」には、更新ボタンに表示する表題を入力します。デフォルトで「更新」が表示されます。「テキストのキャンセル」には、キャンセルボタンに表示する表題を入力します。デフォルトで「キャンセル」が表示されます。このサンプルは、キャンセルボタンの表題を「中止」に書き換えています。

 

「ボタンの種類」からは、[LinkButton]または[PushButton]のいずれかを選択します。デフォルトは、[LinkButton]になります。「プロパティビルダ」から[OK]をクリックすると、編集ボタン列が生成されます。

 

<asp:DataGrid id="DataGrid1" runat="server"

  AutoGenerateColumns="False" ・・・>

  <Columns>

    <asp:BoundColumn DataField="CustomerID"

      ReadOnly="True" HeaderText="ID">

    </asp:BoundColumn>

    <asp:BoundColumn DataField="CompanyName"

      HeaderText="得意先">

    </asp:BoundColumn>

    <asp:BoundColumn DataField="ContactName"

      HeaderText="担当">

    </asp:BoundColumn>

    <asp:BoundColumn DataField="Phone"

      HeaderText="電話">

    </asp:BoundColumn>

    <asp:EditCommandColumn ButtonType="PushButton"

      UpdateText="更新" CancelText="中止" EditText="編集">

    </asp:EditCommandColumn>

  </Columns>

</asp:DataGrid>

 

DataGridから[編集]ボタンをクリックすると、[更新][キャンセル]ボタンに切り替わります。このとき、カレント行の連結列がテキストボックスに表示されます。ただし、得意先IDのように読み取り専用になっている列は、テキストボックスに表示されません。

 

[編集]ボタンをクリックするとWebページがポストバックされて、Page_LoadDataGrid1_EditCommandの順にイベントが発生します。

 

Page_Loadイベントでは、IsPostBackプロパティを調べて初期ロードのときBindGridメソッドを実行します。

 

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs)

cccHandles MyBase.Load

  If Not IsPostBack Then

    BindGrid()

  End If

End Sub

 

BindGridメソッドは、CreateDataSetメソッドを実行してCustomers表のDataSetを作成します。CreateDataSetメソッドの引数には、パッケージ(CustomerPackage)のストアドプロシージャ(GetCustomersGT40[2])を指定します。DataGridDataSourceプロパティにDataSetのオブジェクトを設定して、DataBindメソッドを実行すると、DataGridDataSetがバインドされてCustomers表が表示されます。

 

Private Sub BindGrid()

  With DataGrid1

    .DataSource = CreateDataSet("CustomerPackage.GetCustomersGT40")

    .DataKeyField = "CustomerID"

    .DataBind()

  End With

End Sub

 

DataGrid1_EditCommandイベントでは、DataGridCommandEventArgsオブジェクトのItem.ItemIndexプロパティからカレントのアイテム番号を取得して、DataGridEditItemIndexプロパティに設定します。BindGridメソッドを実行すると、Customers表をDataGridに再度バインドします。これで、カレントの行が編集行として表示されます。さらに、[編集]ボタンが[更新][中止]ボタンに切り替わります。[編集]ボタンをクリックすると、Webページがポストバックされて、Page_LoadDataGrid1_UpdateCommandの順にイベントが発生します。[中止]ボタンをクリックすると、Webページがポストバックされて、Page_LoadDataGrid1_CancelCommandの順にイベントが発生します。

 

Private Sub DataGrid1_EditCommand(ByVal source As Object,

cccByVal e As System.Web.UI.WebControls.DataGridCommandEventArgs)

cccHandles DataGrid1.EditCommand

  DataGrid1.EditItemIndex = e.Item.ItemIndex

  BindGrid()

End Sub

 

DataGrid1_UpdateCommandイベントでは、DataGridCommandEventArgsオブジェクトのItem.CellsコレクションからTextBoxのオブジェクトを取得します。TextBoxTextプロパティから編集後のデータを取得して変数に保存します。カレント行の主キーは、DataGridDataKeys[3]コレクションに格納されています。DataKeysコレクションからカレント行の主キー(CustomerID)を取得したら変数に保存します。UpdateRecordメソッドを実行して更新した行をOracleデータベースに反映します。DataGridEditItemIndexに「-1」を設定して、BindGridメソッドを実行すると、編集した行がDataGridに通常行として表示されます。

 

Private Sub DataGrid1_UpdateCommand(ByVal source As Object,

cccByVal e As System.Web.UI.WebControls.DataGridCommandEventArgs)

cccHandles DataGrid1.UpdateCommand

  Dim strCompanyName As String = CType(e.Item.Cells(1).Controls(0), TextBox).Text

  Dim strContactName As String = CType(e.Item.Cells(2).Controls(0), TextBox).Text

  Dim strPhone As String = CType(e.Item.Cells(3).Controls(0), TextBox).Text

  Dim intCustomerID As Integer = DataGrid1.DataKeys(e.Item.ItemIndex)

 

  UpdateRecord(strCompanyName, strContactName, strPhone, intCustomerID)

  DataGrid1.EditItemIndex = -1

  BindGrid()

End Sub

 

UpdateRecordメソッドは、パッケージ(CustomerPackage)のストアドプロシージャ(UpdateCustomers)を使用してCustomers表の行を更新します。OracleConnectionOracleCommandのインスタンスを生成したら、OracleCommandオブジェクトのCommandTypeプロパティにCommandType.StoredProcedureを設定します。さらに、BindByNameプロパティにTrueを設定して名前指定のパラメータを使用することを指示します。

 

PROCEDURE UpdateCustomers(

  iCompanyName IN VARCHAR2,

  iContactName IN VARCHAR2,

  iPhone IN VARCHAR2,

  iCustomerID IN NUMBER) IS

BEGIN

  UPDATE Customers

    SET CompanyName = iCompanyName,

      ContactName = iContactName,

      Phone = iPhone

    WHERE CustomerID = iCustomerID;

END UpdateCustomers;

 

ParametersコレクションのAddメソッドでパラメータを追加するとき、引数にはストアドプロシージャに宣言しているパラメータ名を指定します。

 

OracleCommand.Parameters.Add("iCompanyName",

cccOracleDbType.Varchar2, 40).Value = strCompanyName

 

OracleConnectionオブジェクトのOpenメソッドでOracleデータベースを開いたら、OracleCommandオブジェクトのExecuteNonQueryメソッドでストアドプロシージャのUPDATE文を実行します。次に、OracleConnectionオブジェクトのCloseメソッドでOracleデータベースを閉じて戻ります。このメソッドからは、戻り値として更新した行数(レコード数[4])を返します。

 

Private Function UpdateRecord(ByVal strCompanyName As String, _

  ByVal strContactName As String, _

  ByVal strPhone As String, _

  ByVal intCustomerID As Integer) As Integer

 

  Dim con As New OracleConnection(ConfigurationSettings.AppSettings("conStringOraNw"))

  Dim cmd As New OracleCommand("CustomerPackage.UpdateCustomers", con)

  With cmd

    .CommandType = CommandType.StoredProcedure

    .BindByName = True

    .Parameters.Add("iCompanyName", OracleDbType.Varchar2, 40).Value = strCompanyName

    .Parameters.Add("iContactName", OracleDbType.Varchar2, 30).Value = strContactName

    .Parameters.Add("iPhone", OracleDbType.Varchar2, 24).Value = strPhone

    .Parameters.Add("iCustomerID", OracleDbType.Int32).Value = intCustomerID

  End With

  con.Open()

  Dim intRetValue As Integer = cmd.ExecuteNonQuery()

  con.Close()

  Return intRetValue

End Function

 

 

STEP UP

楽観的ロックを組み込む (ch56DataGrid1a.aspx)

 

ch56DataGrid1.aspxのサンプルは、排他制御を一切考慮していませんので、他のユーザーが更新したデータを上書きする可能性があります。ここで紹介するサンプルは、楽観的ロックを採用してすでに他のユーザーがレコードを変更しているときは、排他制御エラーにして再試行させるようにします。以下に、Ch56DataGrid1.aspxのサンプルに楽観的ロックを組み込む手順を解説します。

 

1. ストアドプロシージャの追加

 

パッケージの仕様部(CustomerPackage)と本体部(CustomerPackageBody)に、ストアドプロシージャ(UpdateCustomersConcurrencyIDRc)を追加します。このストアドプロシージャは、得意先ID(CustomerID)と更新回数(ConcurrencyID)が一致したときに行(レコード)を更新するように改善しています。また、出力パラメータ(oRowCount)に更新されたレコード数を設定して返します。SQL%ROWCOUNT[5]には、更新されたレコード数が格納されています。これで、レコードが他のユーザーから変更されていないときのみ更新されます。

 

パッケージの仕様部

CREATE OR REPLACE PACKAGE CustomerPackage AS

  PROCEDURE UpdateCustomersConcurrencyIDRc(

    iCompanyName IN VARCHAR2,

    iContactName IN VARCHAR2,

    iPhone IN VARCHAR2,

    iCustomerID IN NUMBER,

    iConcurrencyID IN NUMBER,

    oRowCount OUT NUMBER);

END CustomerPackage;

 

パッケージの本体部

CREATE OR REPLACE PACKAGE BODY CustomerPackage AS

  PROCEDURE UpdateCustomersConcurrencyIDRc(

    iCompanyName IN VARCHAR2,

    iContactName IN VARCHAR2,

    iPhone IN VARCHAR2,

    iCustomerID IN NUMBER,

    iConcurrencyID IN NUMBER,

    oRowCount OUT NUMBER) IS

  BEGIN

    UPDATE Customers

    SET CompanyName = iCompanyName,

      ContactName = iContactName,

      Phone = iPhone,

      ConcurrencyID = ConcurrencyID+1

    WHERE CustomerID = iCustomerID

      AND ConcurrencyID = iConcurrencyID;

    oRowCount := SQL%ROWCOUNT;

  END UpdateCustomersConcurrencyIDRc;

END CustomerPackage;

 

 

2. DataGridに連結列追加

 

DataGrid1の「プロパティビルダ」を表示したら、[]から連結列を作成して連結列(BoundColumn)プロパティの「データフィールド」に「ConcurrencyID」を入力します。[読み取り専用]をクリックしてチェックマークを付けます。「可視」をクリックしてチェックを外します。これで、ConcurrencyIDの連結列が不可視になります。ここで追加した「ConcurrencyID」の連結列を上下の矢印キーを使用して「電話」の連結列の次に移動します。

 

3. UpdateCommandイベントを書き換え

 

コードビューに切り替えたら、DataGrid1_UpdateCommandを以下のように書き換えます。ConcurrencyIDの連結列から更新回数を取得して変数に保存します。UpdateRecordメソッドに引数intConcurrencyIDを追加します。戻り値が「0」のときは、排他制御エラーのメッセージを表示して再試行させます。

 

Private Sub DataGrid1_UpdateCommand(ByVal source As Object,

cccByVal e As System.Web.UI.WebControls.DataGridCommandEventArgs)

cccHandles DataGrid1.UpdateCommand

  Dim strCompanyName As String = CType(e.Item.Cells(1).Controls(0), TextBox).Text

  Dim strContactName As String = CType(e.Item.Cells(2).Controls(0), TextBox).Text

  Dim strPhone As String = CType(e.Item.Cells(3).Controls(0), TextBox).Text

  Dim intConcurrencyID As Integer = Int32.Parse(e.Item.Cells(4).Text)

  Dim intCustomerID As Integer = DataGrid1.DataKeys(e.Item.ItemIndex)

 

  Dim intAffectedRecords As Integer = UpdateRecord(strCompanyName, _

    strContactName, strPhone, intCustomerID, intConcurrencyID)

  If intAffectedRecords = 0 Then

    Response.Write("該当行が他のユーザーから更新されています!<br>再試行してください.<br>")

  End If

  DataGrid1.EditItemIndex = -1

  BindGrid()

End Sub

 

4. Function UpdateRecordの書き換え

 

Function UpdateRecordを以下のように書き換えます。入力パラメータ(iConcurrencyID)と出力パラメータ(oRowCount)を追加します。ExecuteNonQuery[6]メソッド実行後、出力パラメータから更新されたレコード数を取得します。

 

Private Function UpdateRecord(ByVal strCompanyName As String, _

  ByVal strContactName As String, _

  ByVal strPhone As String, _

  ByVal intCustomerID As Integer, _

  ByVal intConcurrencyID As Integer) As Integer

 

  Dim con As New OracleConnection(ConfigurationSettings.AppSettings("conStringOraNw"))

  Dim cmd As New OracleCommand("CustomerPackage.UpdateCustomersConcurrencyIDRc", con)

 

  With cmd

    .CommandType = CommandType.StoredProcedure

    .BindByName = True

    .Parameters.Add("iCompanyName", OracleDbType.Varchar2, 40).Value = strCompanyName

    .Parameters.Add("iContactName", OracleDbType.Varchar2, 30).Value = strContactName

    .Parameters.Add("iPhone", OracleDbType.Varchar2, 24).Value = strPhone

    .Parameters.Add("iCustomerID", OracleDbType.Int32).Value = intCustomerID

    .Parameters.Add("iConcurrencyID", OracleDbType.Int32).Value = intConcurrencyID

    .Parameters.Add("oRowCount", OracleDbType.Int32).Direction = ParameterDirection.Output

  End With

  con.Open()

  cmd.ExecuteNonQuery()

  Dim intRetValue As Integer = Int32.Parse(cmd.Parameters("oRowCount").Value)

  con.Close()

  Return intRetValue

End Function

 

 

STEP UP

トランザクションを適用するには (ch56DataGrid1b.aspx)

 

DataGridで編集した行(レコード)をOracleデータベースに反映するときトランザクションを適用するには、ch56DataGrid1a.aspxUpdateRecordメソッドを以下のように書き換えます。

 

トランザクション処理を適用するには、OracleConnectionオブジェクトのOpenメソッドからCloseメソッドまでの一連の処理をTry...Catch...Finallyブロックに記述します。

 

Tryブロックでは、OracleConnectionオブジェクトのOpenメソッドでOracleデータベースを開きます。次に、BeginTransaction[7]メソッドでトランザクションの開始を宣言します。OracleCommandオブジェクトのExecuteNonQueryメソッドでOracleデータベースを更新したら、OracleTransactionオブジェクトのCommitメソッドで確定させます。

 

Catchブロックでは、OracleTransactionオブジェクトが作成されているとき、Rollbackメソッドでトランザクション開始時点に復元します。

 

Finallyブロックでは、OracleConnectionオブジェクトのCloseメソッドでOracleデータベースを閉じます。

 

 

Private Function UpdateRecord(ByVal strCompanyName As String, _

  ByVal strContactName As String, _

  ByVal strPhone As String, _

  ByVal intCustomerID As Integer, _

  ByVal intConcurrencyID As Integer) As Integer

 

  Dim intRetValue As Integer = 0

  Dim con As New OracleConnection(ConfigurationSettings.AppSettings("conStringOraNw"))

  Dim cmd As New OracleCommand("CustomerPackage.UpdateCustomersConcurrencyIDRc", con)

  Dim txn As OracleTransaction

 

  With cmd

    .CommandType = CommandType.StoredProcedure

    .BindByName = True

    .Parameters.Add("iCompanyName", OracleDbType.Varchar2, 40).Value = strCompanyName

    .Parameters.Add("iContactName", OracleDbType.Varchar2, 30).Value = strContactName

    .Parameters.Add("iPhone", OracleDbType.Varchar2, 24).Value = strPhone

    .Parameters.Add("iCustomerID", OracleDbType.Int32).Value = intCustomerID

    .Parameters.Add("iConcurrencyID", OracleDbType.Int32).Value = intConcurrencyID

    .Parameters.Add("oRowCount", OracleDbType.Int32).Direction = ParameterDirection.Output

  End With

 

  Try

    con.Open()

    txn = con.BeginTransaction

    cmd.ExecuteNonQuery()

    intRetValue = Int32.Parse(cmd.Parameters("oRowCount").Value)

    txn.Commit()

  Catch ex As Exception

    If Not (txn Is Nothing) Then

      txn.Rollback()

    End If

  Finally

    con.Close()

  End Try

  Return intRetValue

End Function

 

 

 

 



[1] 「テキストのキャンセル」とは、キャンセルボタンの表題として表示するテキストのことです。

[2] このストアドプロシージャは、Customers表から得意先ID40以上の行(レコード)を抽出します。

[3] DataKeysコレクションは、DataGridDataKeyFieldプロパティに表(テーブル)の主キーの列名(CustomerID)を設定したときのみ有効です。

[4] Oracleデータベースに対してExecuteNonQueryメソッドを実行したときは、常に「-1」が返ります。レコードが正常に更新されたか調べるには、出力パラメータに更新されたレコード数(%ROWCOUNT)を返します。

[5] WHERE句に該当するレコードな存在しないときは0が格納されます。INSERTUPDATEDELETE文で%ROWCOUNTを使用するときは、暗黙カーソル属性を意味する「SQL」を付加して「SQL%ROWCOUNT」のように記述します。

[6] AccessMySQLSQL Serverに対してExecuteNonQueryを実行すると更新されたレコード数が返されますが、Oracleに対して実行すると常に「-1」が返されます。

[7] Oracleの場合、OracleCommandTransactionプロパティを暗黙的に設定します。AccessSQL Serverの場合、OleDbCommandSqlCommandTransactionプロパティにTransactionオブジェクトを明示的に設定する必要があります。