一括更新 (VB)
1 回の操作で複数のデータベース レコードを更新する方法について説明します。 ユーザー インターフェイス レイヤーでは、各行が編集可能な GridView を作成します。 データ アクセス層では、トランザクション内で複数の更新操作をラップして、すべての更新が成功するか、すべての更新プログラムがロールバックされるようにします。
はじめに
前の チュートリアル では、データ アクセス層を拡張してデータベース トランザクションのサポートを追加する方法について説明しました。 データベース トランザクションでは、一連のデータ変更ステートメントが 1 つのアトミック操作として扱われることが保証されます。これにより、すべての変更が失敗するか、すべて成功します。 この低レベルの DAL 機能を使用すると、バッチ データ変更インターフェイスの作成に注意を向ける準備が整いました。
このチュートリアルでは、各行が編集可能な GridView を構築します (図 1 を参照)。 各行は編集インターフェイスでレンダリングされるため、[編集]、[更新]、[キャンセル] ボタンの列は必要ありません。 代わりに、ページ上に 2 つの [製品の更新] ボタンがあり、クリックすると GridView 行を列挙し、データベースを更新します。
図 1: GridView の各行は編集可能です (クリックするとフルサイズの画像が表示されます)
始めましょう。
注意
バッチ更新の実行に関するチュートリアルでは、DataList コントロールを使用してバッチ編集インターフェイスを作成しました。 このチュートリアルは、GridView を使用する前のチュートリアルとは異なり、バッチ更新はトランザクションのスコープ内で実行されます。 このチュートリアルを完了したら、前のチュートリアルに戻り、前のチュートリアルで追加したデータベース トランザクション関連の機能を使用するように更新することをお勧めします。
すべての GridView 行を編集可能にする手順の確認
「 データの挿入、更新、削除の概要 」チュートリアルで説明したように、GridView では、基になるデータを行ごとに編集するための組み込みのサポートが提供されます。 内部的には、GridView では、そのプロパティを使用してEditIndex
編集可能な行が記録されます。 GridView はデータ ソースにバインドされるときに、各行をチェックして、行のインデックスが の EditIndex
値と等しいかどうかを確認します。 その場合、その行のフィールドは編集インターフェイスを使用してレンダリングされます。 BoundFields の場合、編集インターフェイスは TextBox であり、その Text
プロパティには BoundField の DataField
プロパティで指定されたデータ フィールドの値が割り当てられます。 TemplateFields では、 EditItemTemplate
の代わりに が使用されます ItemTemplate
。
ユーザーが行の [編集] ボタンをクリックすると、編集ワークフローが開始されることを思い出してください。 これによりポストバックが発生し、GridView の EditIndex
プロパティがクリックされた行のインデックスに設定され、データがグリッドに再バインドされます。 行の [キャンセル] ボタンがクリックされると、ポストバック時に、 EditIndex
はグリッドにデータを再バインドする前に の -1
値に設定されます。 GridView の行は 0 からインデックス作成を開始するため、 を に-1
設定EditIndex
すると、GridView が読み取り専用モードで表示されます。
プロパティは EditIndex
行ごとの編集には適していますが、バッチ編集用には設計されていません。 GridView 全体を編集可能にするには、編集インターフェイスを使用して各行をレンダリングする必要があります。 これを実現する最も簡単な方法は、 で定義された編集インターフェイスを使用して、編集可能な各フィールドが TemplateField として実装される場所を ItemTemplate
作成することです。
次のいくつかの手順では、完全に編集可能な GridView を作成します。 手順 1 では、まず GridView とその ObjectDataSource を作成し、その BoundFields と CheckBoxField を TemplateFields に変換します。 手順 2 と 3 では、編集インターフェイスを TemplateFields EditItemTemplate
からその ItemTemplate
インターフェイスに移動します。
手順 1: 製品情報の表示
行が編集可能な GridView の作成について心配する前に、まず製品情報を表示します。 フォルダー内のBatchUpdate.aspx
ページをBatchData
開き、GridView をツールボックスからDesignerにドラッグします。 GridView を ID
に ProductsGrid
設定し、そのスマート タグから、 という名前 ProductsDataSource
の新しい ObjectDataSource にバインドすることを選択します。 クラスの GetProducts
メソッドからデータを取得するように ObjectDataSource をProductsBLL
構成します。
図 2: クラスを使用するように ObjectDataSource を構成する ProductsBLL
(クリックするとフルサイズの画像が表示されます)
図 3: メソッドを使用して製品データを取得する GetProducts
(クリックするとフルサイズの画像が表示されます)
GridView と同様に、ObjectDataSource の変更機能は行ごとに機能するように設計されています。 レコードのセットを更新するには、データをバッチ処理して BLL に渡すコードを ASP.NET ページの分離コード クラスに少し記述する必要があります。 したがって、ObjectDataSource の UPDATE タブ、INSERT タブ、DELETE タブのドロップダウン リストを (None) に設定します。 [完了] をクリックしてウィザードを終了します。
図 4: UPDATE、INSERT、および DELETE タブの Drop-Down Lists を に設定します ([なし] をクリックすると、フルサイズの画像が表示されます)
データ ソースの構成ウィザードを完了すると、ObjectDataSource の宣言型マークアップは次のようになります。
<asp:ObjectDataSource ID="ProductsDataSource" runat="server"
OldValuesParameterFormatString="original_{0}"
SelectMethod="GetProducts" TypeName="ProductsBLL">
</asp:ObjectDataSource>
また、データ ソースの構成ウィザードを完了すると、Visual Studio で GridView の製品データ フィールドに対して BoundFields と CheckBoxField が作成されます。 このチュートリアルでは、ユーザーが製品の名前、カテゴリ、価格、および廃止された状態のみを表示および編集できるようにします。 、UnitPrice
CategoryName
および Discontinued
以外ProductName
のフィールドをすべて削除し、最初の 3 つのフィールドのプロパティの名前をそれぞれ Product、Category、Price に変更HeaderText
します。 最後に、GridView のスマート タグの [ページングを有効にする] チェック ボックスと [並べ替えを有効にする] チェック ボックスをチェックします。
この時点で、GridView には 3 つの BoundField (ProductName
、、 CategoryName
) と UnitPrice
CheckBoxField (Discontinued
) があります。 これらの 4 つのフィールドを TemplateFields に変換し、編集インターフェイスを TemplateFields EditItemTemplate
から その ItemTemplate
に移動する必要があります。
注意
「データ変更インターフェイスのカスタマイズ」チュートリアルで TemplateFields の作成とカスタマイズについて説明しました。 BoundFields と CheckBoxField を TemplateFields に変換し、編集インターフェイス ItemTemplate
を定義する手順について説明しますが、スタックしたり、リフレッシャーが必要な場合は、この前のチュートリアルを参照してください。
GridView のスマート タグで、[列の編集] リンクをクリックして [フィールド] ダイアログ ボックスを開きます。 次に、各フィールドを選択し、[このフィールドを TemplateField に変換する] リンクをクリックします。
図 5: 既存の BoundFields と CheckBoxField を TemplateFields に変換する
各フィールドが TemplateField になったので、編集インターフェイスを s から EditItemTemplate
s に移動する ItemTemplate
準備ができました。
手順 2: インターフェイスのProductName
UnitPrice
作成、およびDiscontinued
編集
、、および Discontinued
編集インターフェイスのProductName
UnitPrice
作成は、この手順のトピックであり、各インターフェイスが TemplateField でEditItemTemplate
既に定義されているため、非常に簡単です。 該当するカテゴリの CategoryName
DropDownList を作成する必要があるため、編集インターフェイスの作成にはもう少し関係があります。 この CategoryName
編集インターフェイスは、手順 3 で取り組みます。
TemplateField から始 ProductName
めましょう。 GridView のスマート タグから [テンプレートの編集] リンクをクリックし、TemplateFields EditItemTemplate
にProductName
ドリルダウンします。 [テキスト ボックス] を選択し、クリップボードにコピーし、TemplateFields ItemTemplate
にProductName
貼り付けます。 TextBox の プロパティを ID
に ProductName
変更します。
次に、 に RequiredFieldValidator を ItemTemplate
追加して、ユーザーが各製品名の値を確実に指定できるようにします。 プロパティを ControlToValidate
ProductName に設定し、 プロパティを ErrorMessage
に設定します。製品の名前を指定する必要があります。 および プロパティを Text
* に指定します。 にこれらの追加を行った後、 ItemTemplate
画面は図 6 のようになります。
図 6: ProductName
TemplateField に TextBox と RequiredFieldValidator が含まれるようになりました (フルサイズの画像を表示するには、ここをクリックします)
編集インターフェイスの場合は UnitPrice
、まず TextBox を から EditItemTemplate
に ItemTemplate
コピーします。 次に、TextBox の前に $ を配置し、その ID
プロパティを UnitPrice に設定し、その Columns
プロパティを 8 に設定します。
また、 に CompareValidator を追加してUnitPrice
ItemTemplate
、ユーザーが入力した値が $0.00 以上の有効な通貨値であることを確認します。 検証コントロールの ControlToValidate
プロパティを UnitPrice に設定し、その ErrorMessage
プロパティを [有効な通貨値を入力する必要があります] に設定します。 通貨記号は省略してください。、そのText
プロパティは *、プロパティは に、Type
プロパティは Operator
Currency
にGreaterThanEqual
、プロパティValueToCompare
は 0 です。
図 7: CompareValidator を追加して、入力した価格が負以外の通貨値であることを確認する (フルサイズの画像を表示する をクリックします)
Discontinued
TemplateField の場合は、 で既に定義されている CheckBox をItemTemplate
使用できます。 を ID
Discontinued に設定し、そのプロパティを Enabled
に True
設定するだけです。
手順 3: 編集インターフェイスのCategoryName
作成
TemplateFields EditItemTemplate
のCategoryName
編集インターフェイスには、データ フィールドの値を表示する TextBox がCategoryName
含まれています。 これを、可能なカテゴリを一覧表示する DropDownList に置き換える必要があります。
注意
「データ変更インターフェイスのカスタマイズ」チュートリアルでは、TextBox ではなく DropDownList を含むようにテンプレートをカスタマイズする方法について詳しく説明します。 ここでの手順は完了していますが、簡潔に示されています。 カテゴリ DropDownList の作成と構成の詳細については、 データ変更インターフェイスのカスタマイズ に関するチュートリアルを参照してください。
DropDownList をツールボックスから TemplateFields ItemTemplate
にドラッグしCategoryName
、 を ID
にCategories
設定します。 この時点では、通常、スマート タグを使用して DropDownLists のデータ ソースを定義し、新しい ObjectDataSource を作成します。 ただし、これにより 内に ObjectDataSource ItemTemplate
が追加され、その結果、GridView 行ごとに ObjectDataSource インスタンスが作成されます。 代わりに、GridView の TemplateFields の外部に ObjectDataSource を作成してみましょう。 テンプレートの編集を終了し、ObjectDataSource をツールボックスから ObjectDataSource の下のDesignerにProductsDataSource
ドラッグします。 新しい ObjectDataSource CategoriesDataSource
に名前を付け、クラス s GetCategories
メソッドをCategoriesBLL
使用するように構成します。
図 8: クラスを使用するように ObjectDataSource を構成する CategoriesBLL
(クリックするとフルサイズの画像が表示されます)
図 9: メソッドを使用してカテゴリ データを取得する GetCategories
(クリックするとフルサイズの画像が表示されます)
この ObjectDataSource は単にデータを取得するために使用されるため、UPDATE タブと DELETE タブのドロップダウン リストを (None) に設定します。 [完了] をクリックしてウィザードを終了します。
図 10: UPDATE タブと DELETE タブの Drop-Down Lists を に設定します ([なし] をクリックすると、フルサイズの画像が表示されます)
ウィザードを完了すると、 CategoriesDataSource
宣言型マークアップは次のようになります。
<asp:ObjectDataSource ID="CategoriesDataSource" runat="server"
OldValuesParameterFormatString="original_{0}"
SelectMethod="GetCategories" TypeName="CategoriesBLL">
</asp:ObjectDataSource>
をCategoriesDataSource
作成して構成したら、TemplateField にItemTemplate
戻りCategoryName
、DropDownList のスマート タグから [データ ソースの選択] リンクをクリックします。 [データ ソースの構成] ウィザードで、最初のCategoriesDataSource
ドロップダウン リストからオプションを選択し、表示とCategoryID
値として使用したCategoryName
オプションを選択します。
図 11: DropDownList を に CategoriesDataSource
バインドする (クリックするとフルサイズの画像が表示されます)
この時点で、 Categories
DropDownList はすべてのカテゴリを一覧表示しますが、GridView 行にバインドされている製品の適切なカテゴリはまだ自動的には選択されません。 これを実現するには、DropDownList を製品のSelectedValue
CategoryID
値に設定Categories
する必要があります。 図 12 に示すように、DropDownList のスマート タグから [Edit DataBindings]\(DataBindings の編集\) リンクをクリックし、プロパティをCategoryID
データ フィールドに関連付けますSelectedValue
。
図 12: 製品の CategoryID
値を DropDownList s SelectedValue
プロパティにバインドする
最後の問題の 1 つが残っています。製品に値が指定されていない CategoryID
場合は、 の SelectedValue
databinding ステートメントによって例外が発生します。 これは、DropDownList にはカテゴリの項目のみが含まれており、 のデータベース値CategoryID
を持つNULL
製品にはオプションが提供されないためです。 これを解決するには、DropDownList の AppendDataBoundItems
プロパティを に True
設定し、宣言構文から プロパティを省略して Value
、DropDownList に新しい項目を追加します。 つまり、DropDownList の宣言型構文が Categories
次のようになっていることを確認します。
<asp:DropDownList ID="Categories" runat="server" AppendDataBoundItems="True"
DataSourceID="CategoriesDataSource" DataTextField="CategoryName"
DataValueField="CategoryID" SelectedValue='<%# Bind("CategoryID") %>'>
<asp:ListItem Value=">-- Select One --</asp:ListItem>
</asp:DropDownList>
<asp:ListItem Value="">
-- Select One -- の属性がValue
空の文字列に明示的に設定されていることに注意してください。 ケースを処理NULL
するためにこの追加の DropDownList 項目が必要な理由と、空の文字列へのプロパティの割り当てが不可欠な理由については、データ変更インターフェイスのValue
カスタマイズに関するチュートリアルを参照してください。
注意
ここには、言及する価値がある潜在的なパフォーマンスとスケーラビリティの問題があります。 各行には データ ソースとして を CategoriesDataSource
使用する DropDownList があるため、 CategoriesBLL
クラスの GetCategories
メソッドはページ訪問ごとに n 回呼び出されます。ここで、 n は GridView 内の行数です。 これらの n は を呼び出して GetCategories
、データベースに 対する n 個 のクエリを生成します。 このデータベースへの影響は、返されたカテゴリを要求ごとのキャッシュにキャッシュするか、SQL キャッシュ依存関係または非常に短い時間ベースの有効期限を使用してキャッシュレイヤーを介してキャッシュすることで軽減される可能性があります。
手順 4: 編集インターフェイスの完了
進行状況を表示するために一時停止せずに、GridView のテンプレートに対していくつかの変更を行いました。 ブラウザーを使用して進行状況を確認してください。 図 13 に示すように、各行は、セルの編集インターフェイスを含む を使用して ItemTemplate
レンダリングされます。
図 13: 各 GridView 行は編集可能です (クリックするとフルサイズの画像が表示されます)
この時点で対処する必要がある小さな書式設定の問題がいくつかあります。 最初に、値に UnitPrice
4 つの小数点が含まれていることに注意してください。 これを解決するには、TemplateFields ItemTemplate
にUnitPrice
戻り、TextBox のスマート タグから [Edit DataBindings]\(DataBindings の編集\) リンクをクリックします。 次に、プロパティを Text
数値として書式設定するように指定します。
図 14: プロパティを Text
数値として書式設定する
次に、(左揃えではなく) 列の Discontinued
チェック ボックスを中央に配置します。 GridView のスマート タグから [列の編集] をクリックし、左下隅にあるフィールドの一覧から [TemplateField] を選択 Discontinued
します。 図 15 に示すように、ドリルダウン ItemStyle
して プロパティを HorizontalAlign
Center に設定します。
図 15: CheckBox を中央揃えするDiscontinued
次に、ValidationSummary コントロールをページに追加し、その ShowMessageBox
プロパティを に True
、その ShowSummary
プロパティを に False
設定します。 また、ボタン Web コントロールを追加します。このコントロールをクリックすると、ユーザーの変更が更新されます。 具体的には、GridView の上と下の 2 つのボタン Web コントロールを追加し、両方のコントロールの Text
プロパティを Update Products に設定します。
GridView の編集インターフェイスは TemplateFields ItemTemplate
で定義されているため、 EditItemTemplate
s は余分であり、削除される可能性があります。
上記の書式設定を変更し、Button コントロールを追加し、不要 EditItemTemplate
な を削除すると、ページの宣言構文は次のようになります。
<p>
<asp:Button ID="UpdateAllProducts1" runat="server" Text="Update Products" />
</p>
<p>
<asp:GridView ID="ProductsGrid" runat="server" AutoGenerateColumns="False"
DataKeyNames="ProductID" DataSourceID="ProductsDataSource"
AllowPaging="True" AllowSorting="True">
<Columns>
<asp:TemplateField HeaderText="Product" SortExpression="ProductName">
<ItemTemplate>
<asp:TextBox ID="ProductName" runat="server"
Text='<%# Bind("ProductName") %>'></asp:TextBox>
<asp:RequiredFieldValidator ID="RequiredFieldValidator1"
ControlToValidate="ProductName"
ErrorMessage="You must provide the product's name."
runat="server">*</asp:RequiredFieldValidator>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Category"
SortExpression="CategoryName">
<ItemTemplate>
<asp:DropDownList ID="Categories" runat="server"
AppendDataBoundItems="True"
DataSourceID="CategoriesDataSource"
DataTextField="CategoryName"
DataValueField="CategoryID"
SelectedValue='<%# Bind("CategoryID") %>'>
<asp:ListItem>-- Select One --</asp:ListItem>
</asp:DropDownList>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Price"
SortExpression="UnitPrice">
<ItemTemplate>
$<asp:TextBox ID="UnitPrice" runat="server" Columns="8"
Text='<%# Bind("UnitPrice", "{0:N}") %>'></asp:TextBox>
<asp:CompareValidator ID="CompareValidator1" runat="server"
ControlToValidate="UnitPrice"
ErrorMessage="You must enter a valid currency value.
Please omit any currency symbols."
Operator="GreaterThanEqual" Type="Currency"
ValueToCompare="0">*</asp:CompareValidator>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Discontinued" SortExpression="Discontinued">
<ItemTemplate>
<asp:CheckBox ID="Discontinued" runat="server"
Checked='<%# Bind("Discontinued") %>' />
</ItemTemplate>
<ItemStyle HorizontalAlign="Center" />
</asp:TemplateField>
</Columns>
</asp:GridView>
</p>
<p>
<asp:Button ID="UpdateAllProducts2" runat="server" Text="Update Products" />
<asp:ObjectDataSource ID="ProductsDataSource" runat="server"
OldValuesParameterFormatString="original_{0}"
SelectMethod="GetProducts" TypeName="ProductsBLL">
</asp:ObjectDataSource>
<asp:ObjectDataSource ID="CategoriesDataSource" runat="server"
OldValuesParameterFormatString="original_{0}"
SelectMethod="GetCategories" TypeName="CategoriesBLL">
</asp:ObjectDataSource>
<asp:ValidationSummary ID="ValidationSummary1" runat="server"
ShowMessageBox="True" ShowSummary="False" />
</p>
図 16 は、ボタン Web コントロールが追加され、書式設定が変更された後にブラウザーで表示された場合のこのページを示しています。
図 16: ページに 2 つの更新プログラム製品ボタンが含まれるようになりました (クリックするとフルサイズの画像が表示されます)
手順 5: 製品の更新
ユーザーがこのページにアクセスすると、変更を加え、2 つの [製品の更新] ボタンのいずれかをクリックします。 その時点で、行ごとにユーザーが入力した値をインスタンスに ProductsDataTable
保存し、それを BLL メソッドに渡し、その ProductsDataTable
インスタンスを DAL メソッド UpdateWithTransaction
に渡す必要があります。 前のチュートリアルで作成した メソッドをUpdateWithTransaction
使用すると、変更のバッチがアトミック操作として更新されます。
で という名前 BatchUpdate
の BatchUpdate.aspx.vb
メソッドを作成し、次のコードを追加します。
Private Sub BatchUpdate()
' Enumerate the GridView's Rows collection and create a ProductRow
Dim productsAPI As New ProductsBLL()
Dim products As Northwind.ProductsDataTable = productsAPI.GetProducts()
For Each gvRow As GridViewRow In ProductsGrid.Rows
' Find the ProductsRow instance in products that maps to gvRow
Dim productID As Integer = _
Convert.ToInt32(ProductsGrid.DataKeys(gvRow.RowIndex).Value)
Dim product As Northwind.ProductsRow = products.FindByProductID(productID)
If product IsNot Nothing Then
' Programmatically access the form field elements in the
' current GridViewRow
Dim productName As TextBox = _
CType(gvRow.FindControl("ProductName"), TextBox)
Dim categories As DropDownList = _
CType(gvRow.FindControl("Categories"), DropDownList)
Dim unitPrice As TextBox = _
CType(gvRow.FindControl("UnitPrice"), TextBox)
Dim discontinued As CheckBox = _
CType(gvRow.FindControl("Discontinued"), CheckBox)
' Assign the user-entered values to the current ProductRow
product.ProductName = productName.Text.Trim()
If categories.SelectedIndex = 0 Then
product.SetCategoryIDNull()
Else
product.CategoryID = Convert.ToInt32(categories.SelectedValue)
End If
If unitPrice.Text.Trim().Length = 0 Then
product.SetUnitPriceNull()
Else
product.UnitPrice = Convert.ToDecimal(unitPrice.Text)
End If
product.Discontinued = discontinued.Checked
End If
Next
' Now have the BLL update the products data using a transaction
productsAPI.UpdateWithTransaction(products)
End Sub
このメソッドは、まず、BLL s GetProducts
メソッドの呼び出しを介して、すべての製品を に戻ProductsDataTable
すことから始まります。 次に、GridView のコレクションをProductGrid
Rows
列挙します。 コレクションにはRows
、GridView にGridViewRow
表示される各行のインスタンスが含まれています。 ページごとに最大 10 行が表示されるため、GridView のコレクションには 10 個以下の Rows
項目が含まれます。
各行に対して、 ProductID
がコレクションからDataKeys
取得され、 からProductsDataTable
適切な ProductsRow
が選択されます。 4 つの TemplateField 入力コントロールは、プログラムによって参照され、その値はインスタンスのプロパティに ProductsRow
割り当てられます。 各 GridView 行の値を使用して を ProductsDataTable
更新した後、BLL s UpdateWithTransaction
メソッドに渡されます。これは、前のチュートリアルで説明したように、DAL メソッド UpdateWithTransaction
を呼び出すだけです。
このチュートリアルで使用されるバッチ更新アルゴリズムは、製品の ProductsDataTable
情報が変更されているかどうかに関係なく、GridView の行に対応する の各行を更新します。 このようなブラインド更新は通常、パフォーマンスの問題ではありませんが、データベース テーブルの変更を監査すると、余分なレコードが発生する可能性があります。 バッチ更新の実行に関するチュートリアルに戻り、DataList を使用してバッチ更新インターフェイスを調べ、ユーザーが実際に変更したレコードのみを更新するコードを追加しました。 必要に応じて、Batch 更新 の実行に関するページの手法を自由に使用して、このチュートリアルのコードを更新してください。
注意
スマート タグを使用してデータ ソースを GridView にバインドすると、Visual Studio によってデータ ソースの主キー値が GridView の DataKeyNames
プロパティに自動的に割り当てられます。 手順 1 で説明したように、GridView のスマート タグを使用して ObjectDataSource を GridView にバインドしなかった場合は、コレクションを通じてDataKeys
各行の値にアクセスProductID
するために、GridView の DataKeyNames
プロパティを ProductID に手動で設定する必要があります。
でBatchUpdate
使用されるコードは、BLL メソッドUpdateProduct
で使用されるコードと似ていますが、メイン違いは、メソッド内で UpdateProduct
1 つのProductRow
インスタンスのみがアーキテクチャから取得されることです。 のProductRow
プロパティを割り当てるコードは、 メソッドと のループ内For Each
のコードの間UpdateProducts
でBatchUpdate
、全体的なパターンと同じです。
このチュートリアルを完了するには、いずれかの [製品の BatchUpdate
更新] ボタンがクリックされたときに メソッドを呼び出す必要があります。 これら 2 つの Button コントロールのイベントのイベント ハンドラー Click
を作成し、イベント ハンドラーに次のコードを追加します。
BatchUpdate()
ClientScript.RegisterStartupScript(Me.GetType(), "message", _
"alert('The products have been updated.');", True)
最初に に対する呼び出し BatchUpdate
が行われます。 次に、 プロパティをClientScript
使用して JavaScript を挿入し、製品が更新されましたと読み取るメッセージ ボックスを表示します。
このコードをテストするには、少し時間がかかります。 ブラウザーを使用してアクセス BatchUpdate.aspx
し、複数の行を編集し、[Update Products]\(製品の更新\) ボタンのいずれかをクリックします。 入力検証エラーがないと仮定すると、"製品が更新されました" というメッセージ ボックスが表示されます。 更新プログラムの原子性を確認するには、1234.56 の値を許可しないUnitPrice
ようなランダムCHECK
制約を追加することを検討してください。 次に から BatchUpdate.aspx
、複数のレコードを編集し、製品 UnitPrice
の値の 1 つを禁止値 ( 1234.56) に設定します。 これにより、バッチ操作中に他の変更が元の値にロールバックされた状態で [製品の更新] をクリックするとエラーが発生します。
代替BatchUpdate
メソッド
先ほど調べたメソッドはBatchUpdate
、BLL メソッドGetProducts
からすべての製品を取得し、GridView に表示されるレコードのみを更新します。 この方法は、GridView がページングを使用しない場合に最適ですが、ページングが行われる場合は、数百、数千、または数万の製品が存在する可能性がありますが、GridView には 10 行しかありません。 このような場合、データベースからすべての製品を 10 個変更するだけでは理想的ではありません。
このような状況では、代わりに次 BatchUpdateAlternate
のメソッドを使用することを検討してください。
Private Sub BatchUpdateAlternate()
' Enumerate the GridView's Rows collection and create a ProductRow
Dim productsAPI As New ProductsBLL()
Dim products As New Northwind.ProductsDataTable()
For Each gvRow As GridViewRow In ProductsGrid.Rows
' Create a new ProductRow instance
Dim productID As Integer = _
Convert.ToInt32(ProductsGrid.DataKeys(gvRow.RowIndex).Value)
Dim currentProductDataTable As Northwind.ProductsDataTable = _
productsAPI.GetProductByProductID(productID)
If currentProductDataTable.Rows.Count > 0 Then
Dim product As Northwind.ProductsRow = currentProductDataTable(0)
Dim productName As TextBox = _
CType(gvRow.FindControl("ProductName"), TextBox)
Dim categories As DropDownList = _
CType(gvRow.FindControl("Categories"), DropDownList)
Dim unitPrice As TextBox = _
CType(gvRow.FindControl("UnitPrice"), TextBox)
Dim discontinued As CheckBox = _
CType(gvRow.FindControl("Discontinued"), CheckBox)
' Assign the user-entered values to the current ProductRow
product.ProductName = productName.Text.Trim()
If categories.SelectedIndex = 0 Then
product.SetCategoryIDNull()
Else
product.CategoryID = Convert.ToInt32(categories.SelectedValue)
End If
If unitPrice.Text.Trim().Length = 0 Then
product.SetUnitPriceNull()
Else
product.UnitPrice = Convert.ToDecimal(unitPrice.Text)
End If
product.Discontinued = discontinued.Checked
' Import the ProductRow into the products DataTable
products.ImportRow(product)
End If
Next
' Now have the BLL update the products data using a transaction
productsAPI.UpdateProductsWithTransaction(products)
End Sub
BatchMethodAlternate
は、 という名前products
の新しい空ProductsDataTable
の を作成することによって開始されます。 次に、GridView の Rows
コレクションをステップ実行し、各行に対して BLL メソッドを使用して特定の GetProductByProductID(productID)
製品情報を取得します。 取得したProductsRow
インスタンスのプロパティは と同じ方法BatchUpdate
で更新されますが、行を更新すると、DataTable の ImportRow(DataRow)
メソッドを介して にproducts
ProductsDataTable
インポートされます。
ループが For Each
完了すると、 products
GridView の各行に対して 1 つの ProductsRow
インスタンスが含まれます。 各インスタンスは ProductsRow
(更新されるのではなく) に products
追加されているため、それをメソッドに盲目的に渡 UpdateWithTransaction
すと、 ProductsTableAdapter
は各レコードをデータベースに挿入しようとします。 代わりに、これらの各行が変更されたことを指定する必要があります (追加されていません)。
これは、 という名前 UpdateProductsWithTransaction
の BLL に新しいメソッドを追加することで実現できます。 UpdateProductsWithTransaction
を次に示します。 内ProductsDataTable
の各インスタンスの ProductsRow
を にModified
設定RowState
し、 を DAL メソッドUpdateWithTransaction
に渡ProductsDataTable
します。
Public Function UpdateProductsWithTransaction _
(ByVal products As Northwind.ProductsDataTable) As Integer
' Mark each product as Modified
products.AcceptChanges()
For Each product As Northwind.ProductsRow In products
product.SetModified()
Next
' Update the data via a transaction
Return UpdateWithTransaction(products)
End Function
まとめ
GridView には、行ごとの組み込みの編集機能が用意されていますが、完全に編集可能なインターフェイスを作成するためのサポートがありません。 このチュートリアルで説明したように、このようなインターフェイスは可能ですが、少しの作業が必要です。 すべての行が編集可能な GridView を作成するには、GridView のフィールドを TemplateFields に変換し、 内で編集インターフェイスを定義する ItemTemplate
必要があります。 さらに、Update All -type Button Web コントロールは、GridView とは別にページに追加する必要があります。 これらの Buttons Click
イベント ハンドラーは、GridView の Rows
コレクションを列挙し、変更を に ProductsDataTable
格納し、更新された情報を適切な BLL メソッドに渡す必要があります。
次のチュートリアルでは、バッチ削除用のインターフェイスを作成する方法について説明します。 特に、各 GridView 行にはチェック ボックスが含まれており、[すべての種類の更新] ボタンの代わりに、[選択した行の削除] ボタンが表示されます。
プログラミングに満足!
著者について
7 冊の ASP/ASP.NET 書籍の著者であり、 4GuysFromRolla.com の創設者である Scott Mitchell は、1998 年から Microsoft Web テクノロジと協力しています。 Scott は、独立したコンサルタント、トレーナー、ライターとして働いています。 彼の最新の本は サムズは24時間で2.0 ASP.NET 自分自身を教えています。 にアクセスするか、ブログを使用して にアクセスmitchell@4GuysFromRolla.comできます。これは でhttp://ScottOnWriting.NET見つけることができます。
特別な感謝
このチュートリアル シリーズは、多くの役に立つ校閲者によってレビューされました。 このチュートリアルのリード レビュー担当者は、テレサ マーフィーと David Suru でした。 今後の MSDN の記事を確認することに関心がありますか? その場合は、 にmitchell@4GuysFromRolla.com行をドロップしてください。
フィードバック
https://aka.ms/ContentUserFeedback」を参照してください。
以下は間もなく提供いたします。2024 年を通じて、コンテンツのフィードバック メカニズムとして GitHub の issue を段階的に廃止し、新しいフィードバック システムに置き換えます。 詳細については、「フィードバックの送信と表示