●DataGridに行の新規登録機能追加 (ch58DataGrid1.aspx)
ここで作成するサンプルは、DataGridにOracleデータベースのCustomers表をバインドして表示します。
Customers表から行(レコード)を抽出するには、パッケージ(CustomerPackage)に登録されているストアドプロシージャ(GetCustomersGT40)を使用します。Customers表に行を追加するには、ストアドプロシージャ(InsertCustomers)を使用します。
iSQL*PlusまたはSQL*Plusを起動して、事前にパッケージ仕様部(C:\vbora\sql\CustomerPackage.sql)とパッケージ本体部(C:\vbora\sql\CustomerPackageBody.sql)を作成してください。
パッケージ仕様部(CustomerPackage.sql)
CREATE OR REPLACE PACKAGE
TYPE rcurCustomers IS REF CURSOR;
PROCEDURE GetCustomersGT40(
orcurCustomers OUT rcurCustomers);
PROCEDURE InsertCustomers(
iCompanyName IN VARCHAR2,
iContactName IN VARCHAR2,
iPhone IN VARCHAR2);
END CustomerPackage;
パッケージ本体部(CustomerPackageBody.sql)
CREATE OR REPLACE PACKAGE BODY
PROCEDURE GetCustomersGT40(
orcurCustomers OUT rcurCustomers) IS
BEGIN
OPEN orcurCustomers FOR
SELECT *
FROM Customers
WHERE CustomerID > 40
ORDER BY CustomerID;
END GetCustomersGT40;
PROCEDURE InsertCustomers(
iCompanyName IN VARCHAR2,
iContactName IN VARCHAR2,
iPhone IN VARCHAR2) IS
BEGIN
INSERT INTO Customers
(CompanyName, ContactName, Phone)
VALUES (iCompanyName, iContactName, iPhone);
END InsertCustomers;
END CustomerPackage;
AccessのAutoNumber型、SQL ServerのIdentity型の列(フィールド)をOracleで実現するためには、SEQUECEとTRIGGERを使用します。このサンプルで使用するCustomers表は、以下のようなSEQUENCEとTRIGGERを使用してCustomerIDをAutoNumber/Identity型にしています。
Customers表には、すでに50件のレコードがロードされていますので、SEQUENCEのSTART WITHでは「51」を指定しています。TRIGGERは、Customers表にINSERT文が実行されるとき、CustomerIDをCustomers_CustomerID_Seqから生成して自動採番します。Customers_CustomerID_SeqのNEXTVALでシーケンス番号を取得するにはDUAL表を使用します。
CREATE SEQUENCE Customers_CustomerID_Seq
NOCYCLE NOORDER NOCACHE NOMAXVALUE MINVALUE 1
INCREMENT BY 1 START WITH 51;
CREATE OR REPLACE TRIGGER Customers_Tri
BEFORE INSERT ON Customers
FOR EACH ROW
BEGIN
SELECT Customers_CustomerID_Seq.NEXTVAL
INTO :new.CustomerID
FROM DUAL;
END;
このサンプルで使用するTRIGGERは、INSERT文でCustomerIDを指定しても無効として自動採番します。INSERT文でCustomerIDを有効にするには、TRIGGERを以下のように書き換えます。
IF
:new.CustomerID IS NULL THEN
SELECT Customers_CustomerID_Seq.NEXTVAL
INTO :new.CustomerID
FROM DUAL;
END IF;
このサンプルでは、以下のノウハウを習得することができます。
▼DataGridに新規行(レコード)を追加する機能を組み込む方法
▼Oracleデータベースの表にオートナンバー型の列を作成する方法
▼表に新規登録して行(レコード)のID(シーケンス)を取得する方法
▼DataTableのAutoIncremennt、AutoIncremnetSeed、AutoIncrementStepプロパティの使い方
▼DataTableのNewRowメソッドの使い方
▼DataTableのRowsコレクションのAddメソッドの使い方
▼SEQUENCE、TRIGGERの使い方
▼SEQUNCEのCURVAL、NEXTVALの使い方
▼FROM DUALの使い方
▼:new.IDの使い方
1. Webフォーム追加
ソリューションエクスプローラからフォルダ[ch5]を右クリックして、新規Webフォーム「ch58DataGrid1」を追加します。
2.
DataGridを作成して編集/削除機能追加
DataGridに編集機能と削除機能を追加します。

図 DataGridに編集と削除ボタン追加
3. 新規登録ボタン作成
ツールボックスの[Webフォーム]からButtonをドラッグ&ドロップして、DataGrid1の左下にButton1のオブジェクトを作成します。Button1のプロパティウィンドウから「Text」プロパティに「新規登録」を設定します。「ID」のプロパティを「btnAddRow」に書き換えます。
4. Clickイベント作成
デザイナの新規登録ボタンをダブルクリックして、コードビューに切り替えます。btnAddRow_Clickイベントが作成されたら、次のコードを追加します。
Private Sub btnAddRow_Click(ByVal sender As Object, ByVal e As System.EventArgs)
Handles btnAddRow.Click
Dim dr As DataRow = mdt.NewRow
mdt.Rows.Add(dr)
Me.AddingNew = True
Session(mCachekey) = mdt
DataGrid1.EditItemIndex = DataGrid1.Items.Count
BindGrid()
End Sub
5. AddingNewプロパティ追加
モジュールクラスの最後に、AddingNewのプロパティを追加します。
Public Property AddingNew() As Boolean
Get
Dim obj As Object = ViewState("AddingNew")
If obj Is Nothing Then
Return False
End If
Return CType(obj, Boolean)
End Get
Set(ByVal Value As Boolean)
ViewState("AddingNew") = Value
End Set
End Property
6. Page_Loadイベントの書き換え
クラスレベルの変数mdtと定数mCachekeyを追加したら、Page_Loadイベントを以下のように書き換えます。
Private mdt As DataTable
Private Const mCachekey = "ch58DataGrid1DataTable"
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs)
Handles MyBase.Load
If Not IsPostBack Then
BindGrid()
Else
mdt = Session(mCachekey)
End If
End Sub
7. Sub BindGridの書き換え
Sub BindGridを以下にように書き換えます。
Private Sub BindGrid()
If mdt Is Nothing Then
mdt = CreateDataTable("CustomerPackage.GetCustomersGT40")
Dim dc As DataColumn = mdt.Columns("CustomerID")
With dc
.AutoIncrement = True
.AutoIncrementSeed = -1
.AutoIncrementStep = -1
End With
mdt.PrimaryKey = New DataColumn() {dc}
Session(mCachekey) = mdt
End If
With DataGrid1
.DataSource = mdt
.DataKeyField = "CustomerID"
.DataBind()
End With
End Sub
8. CancelCommandイベントの書き換え
DataGrid1_CancelCommandイベントを以下のように書き換えます。
Private Sub DataGrid1_CancelCommand(ByVal source As Object,
ByVal e As System.Web.UI.WebControls.DataGridCommandEventArgs)
Handles DataGrid1.CancelCommand
If Me.AddingNew Then
Dim dr As DataRow = mdt.Rows(mdt.Rows.Count - 1)
dr.RejectChanges()
Session(mCachekey) = mdt
End If
Me.AddingNew = False
DataGrid1.EditItemIndex = -1
BindGrid()
End Sub
9. UpdateCommandイベントの書き換え
DataGrid1_UpdateCommandイベントを以下にように書き換えます。
Private Sub DataGrid1_UpdateCommand(ByVal
source As Object, ByVal e As
System.Web.UI.WebControls.DataGridCommandEventArgs)
Handles 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
If Me.AddingNew Then
InsertRecord(strCompanyName, strContactName, strPhone)
Else
Dim intCustomerID As Integer = DataGrid1.DataKeys(e.Item.ItemIndex)
UpdateRecord(strCompanyName, strContactName, strPhone, intCustomerID)
End If
Me.AddingNew = False
DataGrid1.EditItemIndex = -1
mdt = Nothing
BindGrid()
End Sub
10. InsertRecordを追加
クラスモジュールの最後に、Function InsertRecordを追加します。
Private Function InsertRecord(ByVal strCompanyName As String, _
ByVal strContactName As String, _
ByVal strPhone As String) As Integer
Dim con As New OracleConnection(ConfigurationSettings.AppSettings("conStringOraNw"))
Dim cmd As New OracleCommand("CustomerPackage.InsertCustomers", 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
End With
con.Open()
Dim intRetValue As Integer = cmd.ExecuteNonQuery()
con.Close()
Return intRetValue
End Function
11. ブラウザに表示
ソリューションエクスプローラから[ch58DataGrid1.aspx]を右クリックしてブラウザに表示します。DataGridにCustomers表が表示されます。Webページから[新規登録]をクリックすると、DataGridに空白行が追加されますので、テキストボックスに得意先、担当、電話を入力して[更新]をクリックします。[中止]をクリックすると、DataGridから空白行が削除されます。空白行のID列には、意図的に負の番号が採番されるようにしています。

図 [新規登録]をクリックして空白行追加
■解説
DataGridに新規行(レコード)を追加するには、ツールボックスからButtonをドラッグ&ドロップしてWebフォームに新規登録ボタンを作成します。
<asp:button id="btnAddRow" runat="server"
Text="新規登録">
</asp:button>
デザイナに新規登録ボタンが作成されたら、ボタンをダブルクリックしてClickイベントを作成します。btnAddRow_Clickイベントでは、DataTableオブジェクトのNewRowメソッドを実行してDataRowオブジェクトを作成します。DataTableのRowsコレクションのAddメソッドで、DataRowをDataTableに追加します。
DataTableのCustomerID列のAutoIncrementプロパティにTrueが設定されていますので、得意先ID(CustomerID)が自動採番されます。AutoIncrementSeedプロパティに「-1」が設定されていますので負の番号が採番されます。
Dim dc As DataColumn = mdt.Columns("CustomerID")
With dc
.AutoIncrement = True
.AutoIncrementSeed = -1
.AutoIncrementStep = -1
End With
AddingNewプロパティにTrueを設定して、DataTableをセッションステートに保存します。DataGridのEditItemIndexプロパティに、新規に追加したDataRowのインデックス番号を設定して、BindGridメソッドを実行します。DataGridに空白行が編集モードで表示されます。
Private Sub btnAddRow_Click(ByVal sender As Object, ByVal e As System.EventArgs)
Handles btnAddRow.Click
Dim dr As DataRow = mdt.NewRow
mdt.Rows.Add(dr)
Me.AddingNew = True
Session(mCachekey) = mdt
DataGrid1.EditItemIndex = DataGrid1.Items.Count
BindGrid()
End Sub
空白行のテキストボックスに、得意先、担当、電話を入力して[更新]をクリックすると、WebページがポストバックされてPage_Load→DataGrid1_UpdateCommandの順にイベントが発生します。[中止]をクリックしたときは、Page_Load→DataGrid1_CancelCommandの順にイベントが発生します。
Page_Loadイベントでは、IsPostBackプロパティを調べて初期ロードまたはポストバックか調べます。初期ロードのときは、BindGridメソッドを実行してDataGridにCustomers表をバインドします。ポストバックのときは、セッションステートからDataTableを復元します。
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs)
Handles MyBase.Load
If Not IsPostBack Then
BindGrid()
Else
mdt = Session(mCachekey)
End If
End Sub
DataGrid1_UpdateCommandイベントでは、DataGridCommandEventArgsオブジェクトのe.Item.CellsコレクションからTextBoxのオブジェクトを取得します。TextBoxのTextプロパティから得意先、担当、電話を取得して変数に保存します。AddingNewプロパティを調べて、新規登録ならInsertRecordメソッドを実行します。新規登録でないときは、UpdateRecordメソッドを実行します。
レコードを追加、更新したら、AddingNewプロパティにFalseを設定して初期化します。DataGridのEditItemIndexプロパティに「-1」を設定して、編集モードを解除します。DataTableオブジェクトの変数をNullに初期化したら、BindGridメソッドを実行してCustomers表をバインドします。変数mdtをNullに初期化すると、BindGridはCustomers表をOracleのデータベースから読み込み[1]ます。
Private Sub DataGrid1_UpdateCommand(ByVal
source As Object, ByVal e As
System.Web.UI.WebControls.DataGridCommandEventArgs)
Handles 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
If Me.AddingNew Then
InsertRecord(strCompanyName, strContactName, strPhone)
Else
Dim intCustomerID As Integer = DataGrid1.DataKeys(e.Item.ItemIndex)
UpdateRecord(strCompanyName, strContactName, strPhone, intCustomerID)
End If
Me.AddingNew = False
DataGrid1.EditItemIndex = -1
mdt = Nothing
BindGrid()
End Sub
InsertRecordメソッドは、新規行をCustomers表に追加します。OracleConnectionとOracleCommandのインスタンスを生成します。OracleConnectionの引数には、Oracleデータベースの接続文字列を指定します。OracleCommandの引数には、パッケージ(CustomerPackage)に登録されているストアドプロシージャ(InsertCustomers)を指定します。
OracleCommandオブジェクトのCommandTypeプロパティにCommandType.StoredProcedure、BindByNameプロパティにTrueを設定します。
PROCEDURE InsertCustomers(
iCompanyName IN VARCHAR2,
iContactName IN VARCHAR2,
iPhone IN VARCHAR2) IS
BEGIN
INSERT INTO Customers
(CompanyName, ContactName, Phone)
VALUES (iCompanyName, iContactName, iPhone);
END InsertCustomers;
ParametersコレクションのAddメソッドには、ストアドプロシージャ(InsertCustomers[2])に宣言しているパラメータ名を指定します。
cmd.Parameters.Add("iCompanyName", OracleDbType.Varchar2, 40).Value = strCompanyName
OracleConnectionオブジェクトのOpenメソッドでOracleデータベースを開いたら、OracleCommandオブジェクトのExecuteNonQueryメソッドでストアドプロシージャを実行します。OracleConnectionオブジェクトのCloseメソッドでOracleデータベースを閉じたら、ExecuteNonQuery[3]メソッドの戻り値を返します。
Private Function InsertRecord(ByVal strCompanyName As String, _
ByVal strContactName As String, _
ByVal strPhone As String) As Integer
Dim con As New OracleConnection(ConfigurationSettings.AppSettings("conStringOraNw"))
Dim cmd As New OracleCommand("CustomerPackage.InsertCustomers", 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
End With
con.Open()
Dim intRetValue As Integer = cmd.ExecuteNonQuery()
con.Close()
Return intRetValue
End Function
DataGrid1_CancelCommandイベントでは、空白行が追加されたか調べて元の状態に復元します。AddingNewプロパティにTrueが設定されているときは、DataTableに空白行のDataRowが追加されています。空白行を削除するには、DataTableのRowsコレクションからDataRowを取得して、DataRowオブジェクトのRejectChangesメソッドを実行します。これで、DataTableから空白行のDataRowが削除されます。
AddingNewプロパティにFalseを設定して初期化します。DataGridのEditItemIndexプロパティに「-1」を設定して、BindGridメソッドを実行します。EditItemIndexプロパティに「-1」を設定すると、編集行が通常行として表示されます。
Private Sub DataGrid1_CancelCommand(ByVal source As Object,
ByVal e As System.Web.UI.WebControls.DataGridCommandEventArgs)
Handles DataGrid1.CancelCommand
If Me.AddingNew Then
Dim dr As DataRow = mdt.Rows(mdt.Rows.Count - 1)
dr.RejectChanges()
Session(mCachekey) = mdt
End If
Me.AddingNew = False
DataGrid1.EditItemIndex = -1
BindGrid()
End Sub