一括削除 (C#)
1 回の操作で複数のデータベース レコードを削除する方法について説明します。 ユーザー インターフェイス レイヤーでは、前のチュートリアルで作成した強化された GridView を基に構築します。 データ アクセス層では、トランザクション内で複数の削除操作をラップして、すべての削除が成功するか、すべての削除がロールバックされるようにします。
はじめに
前のチュートリアルでは、完全に編集可能な GridView を使用してバッチ編集インターフェイスを作成する方法について説明しました。 ユーザーが一度に多くのレコードを編集する状況では、バッチ編集インターフェイスで必要なポストバックとキーボードからマウスへのコンテキスト切替が大幅に少なくなり、エンド ユーザーの作業効率が向上します。 この手法は、ユーザーが一度に多くのレコードを削除するのが一般的なページでも、同様に有効です。
オンライン メール クライアントを使用したユーザーは、最も一般的なバッチ削除インターフェイスの 1 つである、グリッドの各行にチェックボックスがあり、対応する [チェックされた項目をすべて削除] ボタンがあるインターフェイスに既に精通しています (図 1 を参照)。 このチュートリアルは、Web ベースのインターフェイスと、一連のレコードを 1 つのアトミック操作として削除するメソッドの両方を作成する前のチュートリアルのすべてのハード作業を既に行っているため、かなり短いです。 チェックボックスの GridView 列を追加するチュートリアルでは、チェックボックスの列を含む GridView を作成しました。トランザクション内のデータベース変更をラップするのチュートリアルでは、トランザクションを使用して ProductID
値の List<T>
を削除するメソッドを BLL で作成しました。 ここでは、前のチュートリアルを基に構築し、マージして、実際のバッチ削除の例を作成します。
図 1: 各行に含まれるチェック ボックス (クリックするとフルサイズの画像が表示されます)
手順 1: バッチ削除インターフェイスの作成
チェックボックスの GridView 列を追加するのチュートリアルでバッチ削除インターフェイスを既に作成しているため、最初から作成するのではなく、単に BatchDelete.aspx
へコピーできます。 まず、BatchData
フォルダー内の BatchDelete.aspx
ページと EnhancedGridView
フォルダー内の CheckBoxField.aspx
ページを開きます。 CheckBoxField.aspx
ページからソース ビューに移動し、図 2 に示すように <asp:Content>
のタグ間でマークアップをコピーします。
図 2: CheckBoxField.aspx
の宣言型マークアップをクリップボードにコピーする (クリックするとフルサイズの画像が表示されます)
次に、BatchDelete.aspx
でソース ビューに移動し、クリップボードの内容を <asp:Content>
タグ内に貼り付けます。 また、CheckBoxField.aspx.cs
の分離コード クラス内のコードを BatchDelete.aspx.cs
の分離コード クラス内にコピーして貼り付けます (DeleteSelectedProducts
ボタンの Click
イベント ハンドラーと ToggleCheckState
メソッド、CheckAll
ボタンと UncheckAll
ボタンの Click
イベント ハンドラー)。 このコンテンツをコピーした後、BatchDelete.aspx
ページの分離コード クラスには次のコードが含まれている必要があります。
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
public partial class BatchData_BatchDelete : System.Web.UI.Page
{
protected void DeleteSelectedProducts_Click(object sender, EventArgs e)
{
bool atLeastOneRowDeleted = false;
// Iterate through the Products.Rows property
foreach (GridViewRow row in Products.Rows)
{
// Access the CheckBox
CheckBox cb = (CheckBox)row.FindControl("ProductSelector");
if (cb != null && cb.Checked)
{
// Delete row! (Well, not really...)
atLeastOneRowDeleted = true;
// First, get the ProductID for the selected row
int productID = Convert.ToInt32(Products.DataKeys[row.RowIndex].Value);
// "Delete" the row
DeleteResults.Text += string.Format
("This would have deleted ProductID {0}<br />", productID);
//... To actually delete the product, use ...
//ProductsBLL productAPI = new ProductsBLL();
//productAPI.DeleteProduct(productID);
//............................................
}
}
// Show the Label if at least one row was deleted...
DeleteResults.Visible = atLeastOneRowDeleted;
}
private void ToggleCheckState(bool checkState)
{
// Iterate through the Products.Rows property
foreach (GridViewRow row in Products.Rows)
{
// Access the CheckBox
CheckBox cb = (CheckBox)row.FindControl("ProductSelector");
if (cb != null)
cb.Checked = checkState;
}
}
protected void CheckAll_Click(object sender, EventArgs e)
{
ToggleCheckState(true);
}
protected void UncheckAll_Click(object sender, EventArgs e)
{
ToggleCheckState(false);
}
}
宣言型マークアップとソース コードをコピーした後、ブラウザーで BatchDelete.aspx
を表示してテストしてみましょう。 GridView に最初の 10 個の製品が一覧表示され、各行に製品名、カテゴリ、価格がチェックボックスと共に一覧表示されます。 [Check All]、[Uncheck All]、[Delete Selected Products] の 3 つのボタンが必要です。 [Check All] ボタンをクリックするとすべてのチェックボックスが選択され、[Uncheck All]はすべてのチェックボックスをオフにします。 [Delete Selected Products] をクリックすると、選択した製品の ProductID
値を 一覧表示するメッセージが表示されますが、実際には製品は削除されません。
図 3: CheckBoxField.aspx
のインターフェイスが BatchDeleting.aspx
に移動 (クリックするとフルサイズの画像が表示されます)
手順 2: トランザクションを使用してチェックされた製品を削除する
バッチ削除インターフェイスが正常に BatchDeleting.aspx
にコピーされると、あとは、ProductsBLL
クラスの DeleteProductsWithTransaction
メソッドを使って、選択された商品の削除ボタンがチェックされた商品を削除するようにコードを更新するだけです。 トランザクション内のデータベース変更をラップするチュートリアルで追加されたこのメソッドは、入力として ProductID
の List<T>
値を受け取り、トランザクションの範囲内で対応する ProductID
をそれぞれ削除します。
DeleteSelectedProducts
ボタン Click
のイベント ハンドラーは現在、次の foreach
ループを使用して各 GridView 行を反復処理します。
// Iterate through the Products.Rows property
foreach (GridViewRow row in Products.Rows)
{
// Access the CheckBox
CheckBox cb = (CheckBox)row.FindControl("ProductSelector");
if (cb != null && cb.Checked)
{
// Delete row! (Well, not really...)
atLeastOneRowDeleted = true;
// First, get the ProductID for the selected row
int productID = Convert.ToInt32(Products.DataKeys[row.RowIndex].Value);
// "Delete" the row
DeleteResults.Text += string.Format
("This would have deleted ProductID {0}<br />", productID);
//... To actually delete the product, use ...
//ProductsBLL productAPI = new ProductsBLL();
//productAPI.DeleteProduct(productID);
//............................................
}
}
各行に対して、ProductSelector
チェックボックス Web コントロールがプログラムによって参照されます。 チェックボックスをオンにすると、行 の ProductID
が DataKeys
コレクションから取得され、DeleteResults
ラベルの Text
プロパティは、行が削除対象として選択されたことを示すメッセージが含むよう更新されます。
上記のコードでは、ProductsBLL
クラスの Delete
メソッドの呼び出しがコメント アウトされるため、実際にはレコードは削除されません。この削除ロジックを適用すると、コードはアトミック操作内ではなく製品を削除します。 つまり、シーケンス内の最初のいくつかの削除が成功したが、後の削除が失敗した場合 (おそらく外部キー制約違反が原因)、例外がスローされますが、既に削除された製品は削除されたままです。
アトミック性を確保するために、代わりに ProductsBLL
クラスの DeleteProductsWithTransaction
メソッドを使用する必要があります。 このメソッドは ProductID
値のリストを受け入れるので、最初にグリッドからこのリストをコンパイルし、パラメーターとして渡す必要があります。 最初に、型 int
の List<T>
のインスタンスを作成します。 foreach
ループ内で、選択した製品の ProductID
値をこの List<T>
に追加する必要があります。 ループの後、List<T>
は ProductsBLL
クラスの DeleteProductsWithTransaction
メソッドに渡す必要があります。 DeleteSelectedProducts
ボタンの Click
イベント ハンドラーを 次のコードで更新します。
protected void DeleteSelectedProducts_Click(object sender, EventArgs e)
{
// Create a List to hold the ProductID values to delete
System.Collections.Generic.List<int> productIDsToDelete =
new System.Collections.Generic.List<int>();
// Iterate through the Products.Rows property
foreach (GridViewRow row in Products.Rows)
{
// Access the CheckBox
CheckBox cb = (CheckBox)row.FindControl("ProductSelector");
if (cb != null && cb.Checked)
{
// Save the ProductID value for deletion
// First, get the ProductID for the selected row
int productID = Convert.ToInt32(Products.DataKeys[row.RowIndex].Value);
// Add it to the List...
productIDsToDelete.Add(productID);
// Add a confirmation message
DeleteResults.Text += string.Format
("ProductID {0} has been deleted<br />", productID);
}
}
// Call the DeleteProductsWithTransaction method and show the Label
// if at least one row was deleted...
if (productIDsToDelete.Count > 0)
{
ProductsBLL productAPI = new ProductsBLL();
productAPI.DeleteProductsWithTransaction(productIDsToDelete);
DeleteResults.Visible = true;
// Rebind the data to the GridView
Products.DataBind();
}
}
更新されたコードでは、int
型 (productIDsToDelete
) の List<T>
が作成され、それには削除する ProductID
値が入ります。 foreach
ループの後に、少なくとも 1 つの製品が選択されている場合、 ProductsBLL
クラスの DeleteProductsWithTransaction
メソッドが呼び出され、このリストが渡されます。 DeleteResults
ラベルも表示され、データが GridView にリバインドされます (新しく削除されたレコードがグリッド内の行として表示されなくなります)。
図 4 は、複数の行が削除対象として選択された後の GridView を示しています。 図 5 は、[Delete Selected Products] ボタンがクリックされた直後の画面を示しています。 図 5 では、削除されたレコードの ProductID
値は GridView の下のラベルに表示され、それらの行は GridView に表示されなくなります。
図 4: 選択した製品が削除される (クリックするとフルサイズの画像が表示されます)
図 5: 削除された製品の ProductID
値が GridView の下に一覧表示される (クリックするとフルサイズの画像が表示されます)
Note
DeleteProductsWithTransaction
メソッドのアトミック性をテストするには、Order Details
テーブルに製品のエントリを手動で追加し、その製品を (他と共に) 削除します。 関連する注文を含む製品を削除しようとすると、外部キー制約違反が発生しますが、選択した他の製品の削除がどのようにロールバックされるかに注意してください。
まとめ
バッチ削除インターフェイスを作成するには、チェック ボックスの列とボタン Web コントロールを含む GridView を追加する必要があります。ボタン Web コントロールをクリックすると、選択したすべての行が 1 つのアトミック操作として削除されます。 このチュートリアルでは、前の 2 つのチュートリアル、チェックボックスの GridView 列を追加するとトランザクション内のデータベース変更をラップするで行った作業をまとめて、このようなインターフェイスを構築しました。 最初のチュートリアルでは、チェックボックスの列を含む GridView を作成しました。後者では、ProductID
値の List<T>
を渡す際に、トランザクションのスコープ内でそれらをすべて削除するメソッドを BLL に実装しました。
次のチュートリアルでは、バッチ挿入を実行するためのインターフェイスを作成します。
プログラミングに満足!
著者について
Scott Mitchell は、7 冊の ASP/ASP.NET 書籍の著者であり、4GuysFromRolla.com の創設者です。1998 年から Microsoft の Web テクノロジに携わっています。 Scott は、独立したコンサルタント、トレーナー、ライターとして働いています。 彼の最新の本は サムズは24時間で2.0 ASP.NET 自分自身を教えています。 にアクセスするか、ブログを使用して にアクセスmitchell@4GuysFromRolla.comできます。これは でhttp://ScottOnWriting.NET見つけることができます。
特別な感謝
このチュートリアル シリーズは、多くの役に立つ校閲者によってレビューされました。 このチュートリアルのレビュー リーダーは、Hilton Giesenow と Teresa Murphy でした。 今後の MSDN の記事を確認することに関心がありますか? その場合は、 にmitchell@4GuysFromRolla.com行をドロップしてください。