Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
oleh Scott Mitchell
Tutorial ini adalah yang pertama dari empat yang melihat memperbarui, menghapus, dan menyisipkan batch data. Dalam tutorial ini kita mempelajari bagaimana transaksi database memungkinkan modifikasi batch dilakukan sebagai operasi atomik, yang memastikan bahwa semua langkah berhasil atau semua langkah gagal.
Pendahuluan
Seperti yang kita lihat dimulai dengan tutorial Gambaran Umum Menyisipkan, Memperbarui, dan Menghapus Data , GridView menyediakan dukungan bawaan untuk pengeditan dan penghapusan tingkat baris. Dengan beberapa klik mouse dimungkinkan untuk membuat antarmuka modifikasi data yang kaya tanpa menulis baris kode, selama Anda puas dengan pengeditan dan penghapusan berdasarkan per baris. Namun, dalam skenario tertentu ini tidak mencukupi dan kami perlu memberi pengguna kemampuan untuk mengedit atau menghapus batch rekaman.
Misalnya, sebagian besar klien email berbasis web menggunakan kisi untuk mencantumkan setiap pesan di mana setiap baris menyertakan kotak centang bersama dengan informasi email (subjek, pengirim, dan sebagainya). Antarmuka ini mengizinkan pengguna untuk menghapus beberapa pesan dengan memeriksanya lalu mengklik tombol Hapus Pesan yang Dipilih. Antarmuka pengeditan batch sangat ideal dalam situasi di mana pengguna biasanya mengedit banyak rekaman yang berbeda. Daripada memaksa pengguna untuk mengklik Edit, buat perubahan mereka, lalu klik Perbarui untuk setiap rekaman yang perlu dimodifikasi, antarmuka pengeditan batch merender setiap baris dengan antarmuka pengeditannya. Pengguna dapat dengan cepat mengubah kumpulan baris yang perlu diubah lalu menyimpan perubahan ini dengan mengklik tombol Perbarui Semua. Dalam set tutorial ini kita akan memeriksa cara membuat antarmuka untuk menyisipkan, mengedit, dan menghapus batch data.
Saat melakukan operasi batch, penting untuk menentukan apakah mungkin beberapa operasi dalam batch berhasil sementara yang lain gagal. Pertimbangkan antarmuka penghapusan batch - apa yang harus terjadi jika rekaman pertama yang dipilih berhasil dihapus, tetapi yang kedua gagal, katakanlah, karena pelanggaran batasan kunci asing? Haruskah penghapusan rekaman pertama digulung balik atau dapat diterima agar rekaman pertama tetap dihapus?
Jika Anda ingin operasi batch diperlakukan sebagai operasi atomik, salah satu di mana semua langkah berhasil atau semua langkah gagal, maka Lapisan Akses Data perlu ditambah untuk menyertakan dukungan untuk transaksi database. Transaksi database menjamin atomitas untuk serangkaian INSERT
pernyataan , , UPDATE
dan DELETE
yang dijalankan di bawah payung transaksi dan merupakan fitur yang didukung oleh sebagian besar semua sistem database modern.
Dalam tutorial ini kita akan melihat cara memperluas DAL untuk menggunakan transaksi database. Tutorial berikutnya akan memeriksa penerapan halaman web untuk menyisipkan, memperbarui, dan menghapus antarmuka batch. Mari kita mulai!
Catatan
Saat memodifikasi data dalam transaksi batch, atomitas tidak selalu diperlukan. Dalam beberapa skenario, mungkin dapat diterima agar beberapa modifikasi data berhasil dan yang lain dalam batch yang sama gagal, seperti saat menghapus sekumpulan email dari klien email berbasis web. Jika ada kesalahan database di tengah proses penghapusan, mungkin dapat diterima bahwa rekaman tersebut diproses tanpa kesalahan tetap dihapus. Dalam kasus seperti itu, DAL tidak perlu dimodifikasi untuk mendukung transaksi database. Namun, ada skenario operasi batch lainnya, di mana atomitas sangat penting. Ketika pelanggan memindahkan dananya dari satu rekening bank ke rekening bank lain, dua operasi harus dilakukan: dana harus dikurangi dari rekening pertama dan kemudian ditambahkan ke yang kedua. Meskipun bank mungkin tidak keberatan memiliki langkah pertama berhasil tetapi langkah kedua gagal, pelanggannya akan marah. Saya mendorong Anda untuk bekerja melalui tutorial ini dan menerapkan peningkatan ke DAL untuk mendukung transaksi database bahkan jika Anda tidak berencana menggunakannya dalam batch menyisipkan, memperbarui, dan menghapus antarmuka yang akan kita bangun dalam tiga tutorial berikut.
Gambaran Umum Transaksi
Sebagian besar database menyertakan dukungan untuk transaksi, yang memungkinkan beberapa perintah database dikelompokkan ke dalam satu unit kerja logis. Perintah database yang terdiri dari transaksi dijamin atomik, yang berarti bahwa semua perintah akan gagal atau semua akan berhasil.
Secara umum, transaksi diimplementasikan melalui pernyataan SQL menggunakan pola berikut:
- Menunjukkan awal transaksi.
- Jalankan pernyataan SQL yang terdiri dari transaksi.
- Jika ada kesalahan dalam salah satu pernyataan dari Langkah 2, gulung balik transaksi.
- Jika semua pernyataan dari Langkah 2 selesai tanpa kesalahan, lakukan transaksi.
Pernyataan SQL yang digunakan untuk membuat, menerapkan, dan mengembalikan transaksi dapat dimasukkan secara manual saat menulis skrip SQL atau membuat prosedur tersimpan, atau melalui cara terprogram menggunakan ADO.NET atau kelas di System.Transactions
namespace. Dalam tutorial ini kami hanya akan memeriksa pengelolaan transaksi menggunakan ADO.NET. Dalam tutorial di masa mendatang kita akan melihat cara menggunakan prosedur tersimpan di Lapisan Akses Data, pada saat itu kita akan menjelajahi pernyataan SQL untuk membuat, menggulung balik, dan melakukan transaksi.
Catatan
Kelas TransactionScope
di System.Transactions
namespace memungkinkan pengembang untuk secara terprogram membungkus serangkaian pernyataan dalam cakupan transaksi dan menyertakan dukungan untuk transaksi kompleks yang melibatkan beberapa sumber, seperti dua database yang berbeda atau bahkan jenis penyimpanan data heterogen, seperti database Microsoft SQL Server, database Oracle, dan layanan Web. Saya telah memutuskan untuk menggunakan transaksi ADO.NET untuk tutorial ini alih-alih TransactionScope
kelas karena ADO.NET lebih spesifik untuk transaksi database dan, dalam banyak kasus, jauh lebih sedikit sumber daya intensif. Selain itu, dalam skenario TransactionScope
tertentu kelas menggunakan Koordinator Transaksi Terdistribusi Microsoft (MSDTC). Masalah konfigurasi, implementasi, dan performa yang mengelilingi MSDTC menjadikannya topik yang agak khusus dan canggih dan di luar cakupan tutorial ini.
Saat bekerja dengan penyedia SqlClient di ADO.NET, transaksi dimulai melalui panggilan ke SqlConnection
, yang mengembalikan BeginTransaction
objek. Pernyataan modifikasi data yang membuat transaksi ditempatkan dalam blok try...catch
. Jika kesalahan terjadi dalam pernyataan di try
blok, eksekusi akan ditransfer ke catch
blok tempat transaksi dapat digulung balik melalui SqlTransaction
metodeRollback
. Jika semua pernyataan berhasil diselesaikan, panggilan ke SqlTransaction
metodeCommit
di akhir try
blok melakukan transaksi. Cuplikan kode berikut menggambarkan pola ini. Lihat Mempertahankan Konsistensi Database dengan Transaksi.
// Create the SqlTransaction object
SqlTransaction myTransaction = SqlConnectionObject.BeginTransaction();
try
{
/*
* ... Perform the database transaction�s data modification statements...
*/
// If we reach here, no errors, so commit the transaction
myTransaction.Commit();
}
catch
{
// If we reach here, there was an error, so rollback the transaction
myTransaction.Rollback();
throw;
}
Secara default, TableAdapters dalam Himpunan Data Yang Dititik tidak menggunakan transaksi. Untuk memberikan dukungan untuk transaksi, kita perlu menambah kelas TableAdapter untuk menyertakan metode tambahan yang menggunakan pola di atas untuk melakukan serangkaian pernyataan modifikasi data dalam cakupan transaksi. Di Langkah 2 kita akan melihat cara menggunakan kelas parsial untuk menambahkan metode ini.
Langkah 1: Membuat Halaman Web Bekerja dengan Data Batch
Sebelum kita mulai menjelajahi cara menambah DAL untuk mendukung transaksi database, mari kita luangkan waktu sejenak terlebih dahulu untuk membuat halaman web ASP.NET yang akan kita butuhkan untuk tutorial ini dan ketiganya setelahnya. Mulailah dengan menambahkan folder baru bernama BatchData
lalu tambahkan halaman ASP.NET berikut, mengaitkan setiap halaman dengan Site.master
halaman master.
Default.aspx
Transactions.aspx
BatchUpdate.aspx
BatchDelete.aspx
BatchInsert.aspx
Gambar 1: Tambahkan Halaman ASP.NET untuk Tutorial Terkait SqlDataSource
Seperti halnya folder lain, Default.aspx
akan menggunakan SectionLevelTutorialListing.ascx
Kontrol Pengguna untuk mencantumkan tutorial di dalam bagiannya. Oleh karena itu, tambahkan Kontrol Pengguna ini ke Default.aspx
dengan menyeretnya dari Penjelajah Solusi ke tampilan Desain halaman.
Gambar 2: Tambahkan SectionLevelTutorialListing.ascx
Kontrol Pengguna ke Default.aspx
(Klik untuk melihat gambar ukuran penuh)
Terakhir, tambahkan keempat halaman ini sebagai entri ke Web.sitemap
file. Secara khusus, tambahkan markup berikut setelah Kustomisasi Peta <siteMapNode>
Situs :
<siteMapNode title="Working with Batched Data"
url="~/BatchData/Default.aspx"
description="Learn how to perform batch operations as opposed to
per-row operations.">
<siteMapNode title="Adding Support for Transactions"
url="~/BatchData/Transactions.aspx"
description="See how to extend the Data Access Layer to support
database transactions." />
<siteMapNode title="Batch Updating"
url="~/BatchData/BatchUpdate.aspx"
description="Build a batch updating interface, where each row in a
GridView is editable." />
<siteMapNode title="Batch Deleting"
url="~/BatchData/BatchDelete.aspx"
description="Explore how to create an interface for batch deleting
by adding a CheckBox to each GridView row." />
<siteMapNode title="Batch Inserting"
url="~/BatchData/BatchInsert.aspx"
description="Examine the steps needed to create a batch inserting
interface, where multiple records can be created at the
click of a button." />
</siteMapNode>
Setelah memperbarui Web.sitemap
, luangkan waktu sejenak untuk melihat situs web tutorial melalui browser. Menu di sebelah kiri sekarang menyertakan item untuk bekerja dengan tutorial data batch.
Gambar 3: Peta Situs Sekarang Menyertakan Entri untuk Tutorial Bekerja dengan Data Batch
Langkah 2: Memperbarui Lapisan Akses Data untuk Mendukung Transaksi Database
Seperti yang kita bahas kembali di tutorial pertama, Membuat Lapisan Akses Data, Himpunan Data Yang Dieksa di DAL kami terdiri dari DataTables dan TableAdapters. DataTable menyimpan data saat TableAdapters menyediakan fungsionalitas untuk membaca data dari database ke dalam DataTables, untuk memperbarui database dengan perubahan yang dibuat pada DataTables, dan sebagainya. Ingat bahwa TableAdapters menyediakan dua pola untuk memperbarui data, yang saya sebut sebagai Batch Update dan DB-Direct. Dengan pola Pembaruan Batch, TableAdapter melewati Himpunan Data, DataTable, atau kumpulan DataRows. Data ini dijumlahkan dan untuk setiap baris yang disisipkan, dimodifikasi, atau dihapus, InsertCommand
, UpdateCommand
, atau DeleteCommand
dijalankan. Dengan pola DB-Direct, TableAdapter malah meneruskan nilai kolom yang diperlukan untuk menyisipkan, memperbarui, atau menghapus satu rekaman. Metode pola DB Direct kemudian menggunakan nilai yang diteruskan untuk menjalankan pernyataan , , InsertCommand
atau UpdateCommand
yang sesuaiDeleteCommand
.
Terlepas dari pola pembaruan yang digunakan, metode yang dihasilkan secara otomatis TableAdapters tidak menggunakan transaksi. Secara default setiap sisipan, pembaruan, atau penghapusan yang dilakukan oleh TableAdapter diperlakukan sebagai operasi diskrit tunggal. Misalnya, bayangkan pola DB-Direct digunakan oleh beberapa kode di BLL untuk menyisipkan sepuluh rekaman ke dalam database. Kode ini akan memanggil metode TableAdapter s Insert
sepuluh kali. Jika lima sisipan pertama berhasil, tetapi yang keenam menghasilkan pengecualian, lima rekaman pertama yang disisipkan akan tetap berada dalam database. Demikian pula, jika pola Pembaruan Batch digunakan untuk melakukan penyisipan, pembaruan, dan penghapusan ke baris yang disisipkan, dimodifikasi, dan dihapus dalam DataTable, jika beberapa modifikasi pertama berhasil tetapi yang kemudian mengalami kesalahan, modifikasi sebelumnya yang selesai akan tetap ada di database.
Dalam skenario tertentu, kami ingin memastikan atomitas di serangkaian modifikasi. Untuk mencapai hal ini, kita harus memperluas TableAdapter secara manual dengan menambahkan metode baru yang menjalankan InsertCommand
, , UpdateCommand
dan DeleteCommand
di bawah payung transaksi. Dalam Membuat Lapisan Akses Data, kami melihat menggunakan kelas parsial untuk memperluas fungsionalitas DataTables dalam Himpunan Data Yang Dititik. Teknik ini juga dapat digunakan dengan TableAdapters.
Himpunan Data Northwind.xsd
Bertitik terletak di App_Code
subfolder folder DAL
. Buat subfolder di DAL
folder bernama TransactionSupport
dan tambahkan file kelas baru bernama ProductsTableAdapter.TransactionSupport.cs
(lihat Gambar 4). File ini akan menyimpan implementasi parsial dari ProductsTableAdapter
yang mencakup metode untuk melakukan modifikasi data menggunakan transaksi.
Gambar 4: Tambahkan Folder Bernama TransactionSupport
dan File Kelas Bernama ProductsTableAdapter.TransactionSupport.cs
Masukkan kode berikut ke ProductsTableAdapter.TransactionSupport.cs
dalam file:
using System;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
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;
namespace NorthwindTableAdapters
{
public partial class ProductsTableAdapter
{
private SqlTransaction _transaction;
private SqlTransaction Transaction
{
get
{
return this._transaction;
}
set
{
this._transaction = value;
}
}
public void BeginTransaction()
{
// Open the connection, if needed
if (this.Connection.State != ConnectionState.Open)
this.Connection.Open();
// Create the transaction and assign it to the Transaction property
this.Transaction = this.Connection.BeginTransaction();
// Attach the transaction to the Adapters
foreach (SqlCommand command in this.CommandCollection)
{
command.Transaction = this.Transaction;
}
this.Adapter.InsertCommand.Transaction = this.Transaction;
this.Adapter.UpdateCommand.Transaction = this.Transaction;
this.Adapter.DeleteCommand.Transaction = this.Transaction;
}
public void CommitTransaction()
{
// Commit the transaction
this.Transaction.Commit();
// Close the connection
this.Connection.Close();
}
public void RollbackTransaction()
{
// Rollback the transaction
this.Transaction.Rollback();
// Close the connection
this.Connection.Close();
}
}
}
Kata partial
kunci dalam deklarasi kelas di sini menunjukkan kepada pengkompilasi bahwa anggota yang ditambahkan di dalamnya akan ditambahkan ke ProductsTableAdapter
kelas di NorthwindTableAdapters
namespace layanan.
using System.Data.SqlClient
Perhatikan pernyataan di bagian atas file. Karena TableAdapter dikonfigurasi untuk menggunakan penyedia SqlClient, secara internal menggunakan SqlDataAdapter
objek untuk mengeluarkan perintahnya ke database. Akibatnya, kita perlu menggunakan SqlTransaction
kelas untuk memulai transaksi dan kemudian menerapkannya atau menggulungnya kembali. Jika Anda menggunakan penyimpanan data selain Microsoft SQL Server, Anda harus menggunakan penyedia yang sesuai.
Metode ini menyediakan blok penyusun yang diperlukan untuk memulai, memutar kembali, dan melakukan transaksi. Mereka ditandai public
, memungkinkan mereka untuk digunakan dari dalam ProductsTableAdapter
, dari kelas lain di DAL, atau dari lapisan lain dalam arsitektur, seperti BLL.
BeginTransaction
membuka internal SqlConnection
TableAdapter (jika diperlukan), memulai transaksi dan menetapkannya ke Transaction
properti, dan melampirkan transaksi ke objek internal SqlDataAdapter
SqlCommand
.
CommitTransaction
dan RollbackTransaction
panggil Transaction
objek s Commit
dan Rollback
metode, masing-masing, sebelum menutup objek internal Connection
.
Langkah 3: Menambahkan Metode untuk Memperbarui dan Menghapus Data Di Bawah Payung Transaksi
Dengan metode ini selesai, kami siap untuk menambahkan metode ke ProductsDataTable
atau BLL yang melakukan serangkaian perintah di bawah payung transaksi. Metode berikut menggunakan pola Pembaruan Batch untuk memperbarui ProductsDataTable
instans menggunakan transaksi. Ini memulai transaksi dengan memanggil BeginTransaction
metode dan kemudian menggunakan try...catch
blok untuk mengeluarkan pernyataan modifikasi data. Jika panggilan ke Adapter
metode objek s Update
menghasilkan pengecualian, eksekusi akan ditransfer ke catch
blok tempat transaksi akan digulung balik dan pengecualian dilemparkan kembali. Ingat bahwa metode mengimplementasikan Update
pola Batch Update dengan menghitung baris yang disediakan ProductsDataTable
dan melakukan yang diperlukan InsertCommand
, UpdateCommand
, dan DeleteCommand
s. Jika salah satu perintah ini menghasilkan kesalahan, transaksi digulung balik, membatalkan modifikasi sebelumnya yang dilakukan selama masa pakai transaksi.
Update
Jika pernyataan selesai tanpa kesalahan, transaksi dilakukan secara keseluruhan.
public int UpdateWithTransaction(Northwind.ProductsDataTable dataTable)
{
this.BeginTransaction();
try
{
// Perform the update on the DataTable
int returnValue = this.Adapter.Update(dataTable);
// If we reach here, no errors, so commit the transaction
this.CommitTransaction();
return returnValue;
}
catch
{
// If we reach here, there was an error, so rollback the transaction
this.RollbackTransaction();
throw;
}
}
UpdateWithTransaction
Tambahkan metode ke ProductsTableAdapter
kelas melalui kelas parsial di ProductsTableAdapter.TransactionSupport.cs
. Atau, metode ini dapat ditambahkan ke kelas Lapisan ProductsBLL
Logika Bisnis dengan beberapa perubahan sindikasi kecil. Yaitu, kata kunci ini dalam this.BeginTransaction()
, , dan this.CommitTransaction()
perlu diganti dengan this.RollbackTransaction()
(ingat bahwa Adapter
adalah nama properti dalam Adapter
jenis ProductsBLL
ProductsTableAdapter
).
Metode ini UpdateWithTransaction
menggunakan pola Pembaruan Batch, tetapi serangkaian panggilan DB-Direct juga dapat digunakan dalam cakupan transaksi, seperti yang ditunjukkan metode berikut. Metode DeleteProductsWithTransaction
ini menerima sebagai input List<T>
jenis int
, yang merupakan metode yang ProductID
akan dihapus. Metode ini memulai transaksi melalui panggilan ke BeginTransaction
dan kemudian, di try
blok, melakukan iterasi melalui daftar yang disediakan yang memanggil metode pola Delete
DB-Direct untuk setiap ProductID
nilai. Jika salah satu panggilan gagal Delete
, kontrol ditransfer ke catch
blok tempat transaksi digulung balik dan pengecualian dilemparkan kembali. Jika semua panggilan berhasil Delete
, maka transaksi dilakukan. Tambahkan metode ini ke ProductsBLL
kelas .
public void DeleteProductsWithTransaction
(System.Collections.Generic.List<int> productIDs)
{
// Start the transaction
Adapter.BeginTransaction();
try
{
// Delete each product specified in the list
foreach (int productID in productIDs)
{
Adapter.Delete(productID);
}
// Commit the transaction
Adapter.CommitTransaction();
}
catch
{
// There was an error - rollback the transaction
Adapter.RollbackTransaction();
throw;
}
}
Menerapkan Transaksi di Beberapa TableAdapters
Kode terkait transaksi yang diperiksa dalam tutorial ini memungkinkan beberapa pernyataan terhadap ProductsTableAdapter
diperlakukan sebagai operasi atomik. Tetapi bagaimana jika beberapa modifikasi pada tabel database yang berbeda perlu dilakukan secara atomik? Misalnya, saat menghapus kategori, kami mungkin pertama-tama ingin menetapkan ulang produknya saat ini ke beberapa kategori lain. Kedua langkah ini menetapkan ulang produk dan menghapus kategori harus dijalankan sebagai operasi atomik.
ProductsTableAdapter
Tetapi hanya mencakup metode untuk memodifikasi Products
tabel dan CategoriesTableAdapter
hanya menyertakan metode untuk memodifikasi Categories
tabel. Jadi bagaimana transaksi dapat mencakup kedua TableAdapters?
Salah satu opsinya adalah menambahkan metode ke CategoriesTableAdapter
metode bernama DeleteCategoryAndReassignProducts(categoryIDtoDelete, reassignToCategoryID)
dan meminta metode tersebut memanggil prosedur tersimpan yang keduanya menetapkan ulang produk dan menghapus kategori dalam cakupan transaksi yang ditentukan dalam prosedur tersimpan. Kita akan melihat cara memulai, menerapkan, dan memutar kembali transaksi dalam prosedur tersimpan dalam tutorial mendatang.
Opsi lain adalah membuat kelas pembantu di DAL yang berisi DeleteCategoryAndReassignProducts(categoryIDtoDelete, reassignToCategoryID)
metode . Metode ini akan membuat instans CategoriesTableAdapter
dan ProductsTableAdapter
lalu mengatur dua properti TableAdapters Connection
ini ke instans yang sama SqlConnection
. Pada saat itu, salah satu dari dua TableAdapters akan memulai transaksi dengan panggilan ke BeginTransaction
. Metode TableAdapters untuk menetapkan ulang produk dan menghapus kategori akan dipanggil dalam try...catch
blok dengan transaksi yang dilakukan atau digulung balik sesuai kebutuhan.
Langkah 4: MenambahkanUpdateWithTransaction
Metode ke Lapisan Logika Bisnis
Di Langkah 3 kami menambahkan UpdateWithTransaction
metode ke ProductsTableAdapter
dalam DAL. Kita harus menambahkan metode yang sesuai ke BLL. Meskipun Lapisan Presentasi dapat memanggil langsung ke DAL untuk memanggil UpdateWithTransaction
metode , tutorial ini telah berusaha untuk menentukan arsitektur berlapis yang mengisolasi DAL dari Lapisan Presentasi. Oleh karena itu, kami harus melanjutkan pendekatan ini.
ProductsBLL
Buka file kelas dan tambahkan metode bernama UpdateWithTransaction
yang hanya memanggil ke metode DAL yang sesuai. Sekarang harus ada dua metode baru di ProductsBLL
: UpdateWithTransaction
, yang baru saja Anda tambahkan, dan DeleteProductsWithTransaction
, yang ditambahkan di Langkah 3.
public int UpdateWithTransaction(Northwind.ProductsDataTable products)
{
return Adapter.UpdateWithTransaction(products);
}
public void DeleteProductsWithTransaction
(System.Collections.Generic.List<int> productIDs)
{
// Start the transaction
Adapter.BeginTransaction();
try
{
// Delete each product specified in the list
foreach (int productID in productIDs)
Adapter.Delete(productID);
// Commit the transaction
Adapter.CommitTransaction();
}
catch
{
// There was an error - rollback the transaction
Adapter.RollbackTransaction();
throw;
}
}
Catatan
Metode ini tidak menyertakan atribut yang DataObjectMethodAttribute
ditetapkan ke sebagian besar metode lain di ProductsBLL
kelas karena kami akan memanggil metode ini langsung dari kelas kode halaman ASP.NET di belakang. Ingat yang DataObjectMethodAttribute
digunakan untuk menandai metode apa yang akan muncul di wizard Konfigurasi Sumber Data ObjectDataSource dan di bawah tab apa (SELECT, UPDATE, INSERT, atau DELETE). Karena GridView tidak memiliki dukungan bawaan untuk pengeditan atau penghapusan batch, kita harus memanggil metode ini secara terprogram daripada menggunakan pendekatan deklaratif bebas kode.
Langkah 5: Memperbarui Data Database secara Atomik dari Lapisan Presentasi
Untuk mengilustrasikan efek yang dimiliki transaksi saat memperbarui batch rekaman, mari kita buat antarmuka pengguna yang mencantumkan semua produk dalam GridView dan menyertakan kontrol Web Tombol yang, saat diklik, menetapkan ulang nilai produk CategoryID
. Secara khusus, penetapan ulang kategori akan berlangsung sehingga beberapa produk pertama diberi nilai yang valid CategoryID
sementara yang lain dengan sengaja diberi nilai yang tidak ada CategoryID
. Jika kita mencoba memperbarui database dengan produk yang CategoryID
tidak cocok dengan kategori CategoryID
yang ada, pelanggaran batasan kunci asing akan terjadi dan pengecualian akan dinaikkan. Apa yang akan kita lihat dalam contoh ini adalah bahwa saat menggunakan transaksi, pengecualian yang dimunculkan dari pelanggaran batasan kunci asing akan menyebabkan perubahan valid CategoryID
sebelumnya digulung balik. Namun, ketika tidak menggunakan transaksi, modifikasi pada kategori awal akan tetap ada.
Mulailah dengan membuka Transactions.aspx
halaman di BatchData
folder dan seret GridView dari Kotak Alat ke Perancang.
ID
Atur ke Products
dan, dari tag pintarnya, ikat ke ObjectDataSource baru bernama ProductsDataSource
. Konfigurasikan ObjectDataSource untuk menarik datanya dari ProductsBLL
metode kelas.GetProducts
Ini akan menjadi GridView baca-saja, jadi atur daftar drop-down di tab PERBARUI, SISIPKAN, dan HAPUS ke (Tidak Ada) dan klik Selesai.
Gambar 5: Gambar 5: Konfigurasikan ObjectDataSource untuk Menggunakan ProductsBLL
Metode Kelas (GetProducts
Klik untuk melihat gambar ukuran penuh)
Gambar 6: Atur Daftar Drop-Down di Tab PERBARUI, SISIPKAN, dan HAPUS ke (Tidak Ada) (Klik untuk melihat gambar ukuran penuh)
Setelah menyelesaikan wizard Konfigurasi Sumber Data, Visual Studio akan membuat BoundFields dan CheckBoxField untuk bidang data produk. Hapus semua bidang ini kecuali untuk ProductID
, , ProductName
CategoryID
, dan dan CategoryName
ganti nama ProductName
properti dan CategoryName
BoundFields HeaderText
menjadi Produk dan Kategori, masing-masing. Dari tag pintar, centang opsi Aktifkan Halaman. Setelah melakukan modifikasi ini, markup deklaratif GridView dan ObjectDataSource akan terlihat seperti berikut ini:
<asp:GridView ID="Products" runat="server" AllowPaging="True"
AutoGenerateColumns="False" DataKeyNames="ProductID"
DataSourceID="ProductsDataSource">
<Columns>
<asp:BoundField DataField="ProductID" HeaderText="ProductID"
InsertVisible="False" ReadOnly="True"
SortExpression="ProductID" />
<asp:BoundField DataField="ProductName" HeaderText="Product"
SortExpression="ProductName" />
<asp:BoundField DataField="CategoryID" HeaderText="CategoryID"
SortExpression="CategoryID" />
<asp:BoundField DataField="CategoryName" HeaderText="Category"
SortExpression="CategoryName" />
</Columns>
</asp:GridView>
<asp:ObjectDataSource ID="ProductsDataSource" runat="server"
OldValuesParameterFormatString="original_{0}"
SelectMethod="GetProducts" TypeName="ProductsBLL">
</asp:ObjectDataSource>
Selanjutnya, tambahkan tiga kontrol Web Tombol di atas GridView. Atur properti Teks Tombol pertama ke Refresh Grid, yang kedua ke Ubah Kategori (WITH TRANSACTION), dan yang ketiga ke Modifikasi Kategori (TANPA TRANSAKSI) .
<p>
<asp:Button ID="RefreshGrid" runat="server" Text="Refresh Grid" />
</p>
<p>
<asp:Button ID="ModifyCategoriesWithTransaction" runat="server"
Text="Modify Categories (WITH TRANSACTION)" />
</p>
<p>
<asp:Button ID="ModifyCategoriesWithoutTransaction" runat="server"
Text="Modify Categories (WITHOUT TRANSACTION)" />
</p>
Pada titik ini tampilan Desain di Visual Studio akan terlihat mirip dengan cuplikan layar yang ditampilkan di Gambar 7.
Gambar 7: Halaman Berisi Tampilan Kisi dan Kontrol Web Tiga Tombol (Klik untuk melihat gambar ukuran penuh)
Buat penanganan aktivitas untuk masing-masing dari tiga peristiwa Tombol dan Click
gunakan kode berikut:
protected void RefreshGrid_Click(object sender, EventArgs e)
{
Products.DataBind();
}
protected void ModifyCategoriesWithTransaction_Click(object sender, EventArgs e)
{
// Get the set of products
ProductsBLL productsAPI = new ProductsBLL();
Northwind.ProductsDataTable products = productsAPI.GetProducts();
// Update each product's CategoryID
foreach (Northwind.ProductsRow product in products)
{
product.CategoryID = product.ProductID;
}
// Update the data using a transaction
productsAPI.UpdateWithTransaction(products);
// Refresh the Grid
Products.DataBind();
}
protected void ModifyCategoriesWithoutTransaction_Click(object sender, EventArgs e)
{
// Get the set of products
ProductsBLL productsAPI = new ProductsBLL();
Northwind.ProductsDataTable products = productsAPI.GetProducts();
// Update each product's CategoryID
foreach (Northwind.ProductsRow product in products)
{
product.CategoryID = product.ProductID;
}
// Update the data WITHOUT using a transaction
NorthwindTableAdapters.ProductsTableAdapter productsAdapter =
new NorthwindTableAdapters.ProductsTableAdapter();
productsAdapter.Update(products);
// Refresh the Grid
Products.DataBind();
}
Handler peristiwa Tombol Click
refresh hanya mengikat ulang data ke GridView dengan memanggil Products
metode GridView DataBind
.
Penanganan aktivitas kedua menetapkan ulang produk CategoryID
dan menggunakan metode transaksi baru dari BLL untuk melakukan pembaruan database di bawah payung transaksi. Perhatikan bahwa setiap produk CategoryID
secara segan-segan diatur ke nilai yang sama dengan ProductID
. Ini akan berfungsi dengan baik untuk beberapa produk pertama, karena produk tersebut memiliki ProductID
nilai yang terjadi untuk memetakan ke yang valid CategoryID
. Tetapi setelah ProductID
mulai terlalu besar, tumpang tindih ProductID
kebetulan ini dan CategoryID
tidak lagi berlaku.
Penanganan aktivitas ketiga Click
memperbarui produk CategoryID
dengan cara yang sama, tetapi mengirim pembaruan ke database menggunakan ProductsTableAdapter
metode default Update
s. Metode ini Update
tidak membungkus rangkaian perintah dalam transaksi, sehingga perubahan tersebut dilakukan sebelum kesalahan pelanggaran batasan kunci asing pertama yang ditemui akan bertahan.
Untuk menunjukkan perilaku ini, kunjungi halaman ini melalui browser. Awalnya Anda akan melihat halaman pertama data seperti yang ditunjukkan pada Gambar 8. Selanjutnya, klik tombol Ubah Kategori (DENGAN TRANSAKSI). Ini akan menyebabkan postback dan mencoba memperbarui semua nilai produk CategoryID
, tetapi akan mengakibatkan pelanggaran batasan kunci asing (lihat Gambar 9).
Gambar 8: Produk Ditampilkan dalam Tampilan Kisi yang Dapat Di-Pageable (Klik untuk melihat gambar ukuran penuh)
Gambar 9: Menetapkan Ulang Kategori Menghasilkan Pelanggaran Batasan Kunci Asing (Klik untuk melihat gambar ukuran penuh)
Sekarang tekan tombol Kembali browser Anda lalu klik tombol Refresh Grid. Setelah me-refresh data, Anda akan melihat output yang sama persis seperti yang ditunjukkan pada Gambar 8. Artinya, meskipun beberapa produk CategoryID
diubah menjadi nilai hukum dan diperbarui dalam database, produk tersebut digulirkan kembali ketika pelanggaran batasan kunci asing terjadi.
Sekarang coba klik tombol Ubah Kategori (TANPA TRANSAKSI). Ini akan mengakibatkan kesalahan pelanggaran batasan kunci asing yang sama (lihat Gambar 9), tetapi kali ini produk yang nilainya CategoryID
diubah menjadi nilai hukum tidak akan digulung balik. Tekan tombol Kembali browser Anda lalu tombol Refresh Grid. Seperti yang ditunjukkan Gambar 10, CategoryID
dari delapan produk pertama telah ditetapkan kembali. Misalnya, di Gambar 8, Chang memiliki CategoryID
1, tetapi pada Gambar 10 telah ditetapkan kembali menjadi 2.
Gambar 10: Beberapa Nilai Produk CategoryID
Diperbarui Sementara Yang Lain Tidak (Klik untuk melihat gambar ukuran penuh)
Ringkasan
Secara default, metode TableAdapter s tidak membungkus pernyataan database yang dijalankan dalam cakupan transaksi, tetapi dengan sedikit pekerjaan kita dapat menambahkan metode yang akan membuat, menerapkan, dan memutar kembali transaksi. Dalam tutorial ini kita membuat tiga metode seperti itu ProductsTableAdapter
di kelas : BeginTransaction
, CommitTransaction
, dan RollbackTransaction
. Kami melihat cara menggunakan metode ini bersama dengan try...catch
blok untuk membuat serangkaian pernyataan modifikasi data atomik. Secara khusus, kami membuat UpdateWithTransaction
metode dalam ProductsTableAdapter
, yang menggunakan pola Batch Update untuk melakukan modifikasi yang diperlukan pada baris yang disediakan ProductsDataTable
. Kami juga menambahkan DeleteProductsWithTransaction
metode ke ProductsBLL
kelas di BLL, yang menerima List
nilai ProductID
sebagai inputnya dan memanggil metode Delete
pola DB-Direct untuk setiap ProductID
. Kedua metode dimulai dengan membuat transaksi dan kemudian menjalankan pernyataan modifikasi data dalam blok try...catch
. Jika terjadi pengecualian, transaksi digulung balik, jika tidak, maka akan dilakukan.
Langkah 5 menggambarkan efek pembaruan batch transaksional versus pembaruan batch yang diabaikan untuk menggunakan transaksi. Dalam tiga tutorial berikutnya kita akan membangun pada fondasi yang diletakkan dalam tutorial ini dan membuat antarmuka pengguna untuk melakukan pembaruan batch, penghapusan, dan sisipan.
Selamat Pemrograman!
Bacaan lebih lanjut
Untuk informasi selengkapnya tentang topik yang dibahas dalam tutorial ini, lihat sumber daya berikut:
-
Transaksi Menjadi Mudah:
System.Transactions
- TransactionScope dan DataAdapters
- Menggunakan Transaksi Database Oracle di .NET
Tentang Penulis
Scott Mitchell, penulis tujuh buku ASP/ASP.NET dan pendiri 4GuysFromRolla.com, telah bekerja sama dengan teknologi Microsoft Web sejak 1998. Scott bekerja sebagai konsultan, pelatih, dan penulis independen. Buku terbarunya adalah Sams Teach Yourself ASP.NET 2.0 dalam 24 Jam. Dia dapat dijangkau di mitchell@4GuysFromRolla.com.
Terima kasih khusus untuk
Seri tutorial ini ditinjau oleh banyak peninjau yang bermanfaat. Peninjau utama untuk tutorial ini adalah Dave Gardner, Hilton Giesenow, dan Teresa Murphy. Tertarik untuk meninjau artikel MSDN saya yang akan datang? Jika demikian, hubungi saya di mitchell@4GuysFromRolla.com.