Bagikan melalui


Penyisipan Batch (C#)

oleh Scott Mitchell

Unduh PDF

Pelajari cara menyisipkan beberapa rekaman database dalam satu operasi. Di Lapisan Antarmuka Pengguna, kami memperluas GridView untuk memungkinkan pengguna memasukkan beberapa rekaman baru. Di Lapisan Akses Data, kami membungkus beberapa operasi Sisipkan dalam transaksi untuk memastikan bahwa semua penyisipan berhasil atau semua penyisipan digulung balik.

Pendahuluan

Dalam tutorial Pembaruan Batch , kami melihat penyesuaian kontrol GridView untuk menyajikan antarmuka tempat beberapa rekaman dapat diedit. Pengguna yang mengunjungi halaman dapat membuat serangkaian perubahan lalu, dengan satu klik tombol, melakukan pembaruan batch. Untuk situasi di mana pengguna biasanya memperbarui banyak rekaman dalam sekali jalan, antarmuka seperti itu dapat menyimpan klik yang tak terhitung jumlahnya dan pengalihan konteks keyboard-ke-mouse jika dibandingkan dengan fitur pengeditan per baris default yang pertama kali dijelajahi kembali dalam tutorial Gambaran Umum Menyisipkan, Memperbarui, dan Menghapus Data .

Konsep ini juga dapat diterapkan saat menambahkan rekaman. Bayangkan bahwa di sini di Northwind Traders kami biasanya menerima pengiriman dari pemasok yang berisi sejumlah produk untuk kategori tertentu. Sebagai contoh, kami mungkin menerima pengiriman enam produk teh dan kopi yang berbeda dari Tokyo Traders. Jika pengguna memasukkan enam produk satu per satu melalui kontrol DetailsView, mereka harus memilih banyak nilai yang sama berulang kali: mereka harus memilih kategori yang sama (Minuman), pemasok yang sama (Tokyo Traders), nilai yang dihentikan yang sama (Salah), dan unit yang sama pada nilai pesanan (0). Entri data berulang ini tidak hanya memakan waktu, tetapi rentan terhadap kesalahan.

Dengan sedikit pekerjaan, kita dapat membuat antarmuka penyisipan batch yang memungkinkan pengguna memilih pemasok dan kategori sekali, memasukkan serangkaian nama produk dan harga unit, lalu mengklik tombol untuk menambahkan produk baru ke database (lihat Gambar 1). Saat setiap produk ditambahkan, bidang ProductName dan UnitPrice datanya diberi nilai yang dimasukkan di Kotak Teks, sementara nilai CategoryID dan SupplierID ditetapkan dari DropDownLists di bagian atas formulir. Nilai Discontinued dan UnitsOnOrder diatur ke nilai tetap false dan 0 secara berturut-turut.

Antarmuka Penyisipan Tumpukan

Gambar 1: Antarmuka Penyisipan Batch (Klik untuk melihat gambar ukuran penuh)

Dalam tutorial ini kita akan membuat halaman yang mengimplementasikan antarmuka penyisipan batch yang ditunjukkan pada Gambar 1. Seperti dua tutorial sebelumnya, kami akan membungkus penyisipan dalam cakupan transaksi untuk memastikan atomitas. Mari kita mulai!

Langkah 1: Membuat Antarmuka Tampilan

Tutorial ini akan terdiri dari satu halaman yang dibagi menjadi dua wilayah: wilayah tampilan dan wilayah penyisipan. Antarmuka tampilan, yang akan kita buat dalam langkah ini, menunjukkan produk dalam GridView dan menyertakan tombol berjudul Proses Pengiriman Produk. Ketika tombol ini diklik, antarmuka tampilan diganti dengan antarmuka penyisipan, yang ditampilkan dalam Gambar 1. Antarmuka tampilan kembali setelah tombol Tambahkan Produk dari Pengiriman atau Batal diklik. Kita akan membuat antarmuka penyisipan di Langkah 2.

Saat membuat halaman yang memiliki dua antarmuka, hanya satu yang terlihat pada satu waktu, setiap antarmuka biasanya ditempatkan dalam kontrol Web Panel, yang berfungsi sebagai kontainer untuk kontrol lain. Oleh karena itu, halaman kami akan memiliki dua kontrol Panel satu untuk setiap antarmuka.

Mulailah dengan membuka BatchInsert.aspx halaman di BatchData folder dan seret Panel dari Kotak Alat ke Perancang (lihat Gambar 2). Atur properti Panel ID ke DisplayInterface. Saat menambahkan Panel ke Perancang, properti Height dan Width diatur masing-masing ke 50px dan 125px. Hapus nilai properti ini dari jendela Properti.

Seret Panel dari Kotak Alat ke Perancang

Gambar 2: Seret Panel dari Kotak Alat ke Perancang (Klik untuk melihat gambar ukuran penuh)

Selanjutnya, seret kontrol Tombol dan GridView ke panel. Atur properti Tombol ke IDProcessShipment dan propertinya Text ke Proses Pengiriman Produk. Atur properti GridView ke IDProductsGrid dan, dari tag pintarnya, ikat ke ObjectDataSource baru bernama ProductsDataSource. Konfigurasikan ObjectDataSource untuk menarik datanya dari ProductsBLL metode kelas.GetProducts Karena GridView ini hanya digunakan untuk menampilkan data, atur daftar drop-down di tab PERBARUI, SISIPKAN, dan HAPUS ke (Tidak Ada). Klik Selesai untuk menyelesaikan wizard Konfigurasi Sumber Data.

Menampilkan Data yang Dikembalikan dari Metode GetProducts Kelas ProductsBLL

Gambar 3: Menampilkan Data yang Dikembalikan dari Metode ProductsBLL Kelas GetProducts (Klik untuk melihat gambar ukuran penuh)

Atur daftar Drop-Down di tab PERBARUI, SISIPKAN, dan HAPUS menjadi (Tidak Ada)

Gambar 4: Atur Daftar Drop-Down di Tab PERBARUI, SISIPKAN, dan HAPUS ke (Tidak Ada) (Klik untuk melihat gambar ukuran penuh)

Setelah menyelesaikan wizard ObjectDataSource, Visual Studio akan menambahkan BoundFields dan CheckBoxField untuk bidang data produk. Hapus semua kecuali ProductName, CategoryName, SupplierName, UnitPrice, dan Discontinued bidang. Jangan ragu untuk membuat penyesuaian estetika. Saya memutuskan untuk memformat UnitPrice bidang sebagai nilai mata uang, menyusun ulang bidang, dan mengganti nama beberapa nilai bidang HeaderText . Konfigurasikan juga GridView untuk menyertakan dukungan penomoran dan pengurutan dengan mencentang kotak centang Aktifkan Halaman dan Aktifkan Pengurutan di tag pintar GridView.

Setelah menambahkan kontrol Panel, Tombol, GridView, dan ObjectDataSource dan menyesuaikan bidang GridView, markup deklaratif halaman Anda akan terlihat mirip dengan yang berikut ini:

<asp:Panel ID="DisplayInterface" runat="server">
    <p>
        <asp:Button ID="ProcessShipment" runat="server" 
            Text="Process Product Shipment" /> 
    </p>
    <asp:GridView ID="ProductsGrid" runat="server" AllowPaging="True" 
        AllowSorting="True" AutoGenerateColumns="False" 
        DataKeyNames="ProductID" DataSourceID="ProductsDataSource">
        <Columns>
            <asp:BoundField DataField="ProductName" HeaderText="Product" 
                SortExpression="ProductName" />
            <asp:BoundField DataField="CategoryName" HeaderText="Category" 
                ReadOnly="True" SortExpression="CategoryName" />
            <asp:BoundField DataField="SupplierName" HeaderText="Supplier" 
                ReadOnly="True" SortExpression="SupplierName" />
            <asp:BoundField DataField="UnitPrice" DataFormatString="{0:c}" 
                HeaderText="Price" HtmlEncode="False" 
                SortExpression="UnitPrice">
                <ItemStyle HorizontalAlign="Right" />
            </asp:BoundField>
            <asp:CheckBoxField DataField="Discontinued" HeaderText="Discontinued" 
                SortExpression="Discontinued">
                <ItemStyle HorizontalAlign="Center" />
            </asp:CheckBoxField>
        </Columns>
    </asp:GridView>
    <asp:ObjectDataSource ID="ProductsDataSource" runat="server" 
        OldValuesParameterFormatString="original_{0}"
        SelectMethod="GetProducts" TypeName="ProductsBLL">
    </asp:ObjectDataSource>
</asp:Panel>

Perhatikan bahwa markup untuk Tombol dan GridView muncul dalam tag pembuka dan penutupan <asp:Panel> . Karena kontrol ini berada di DisplayInterface dalam Panel, kita dapat menyembunyikannya hanya dengan mengatur properti Panel Visible ke false. Langkah 3 membahas cara mengubah properti panel secara programatik sebagai respons terhadap klik tombol untuk menampilkan satu antarmuka sambil menyembunyikan yang lain.

Luangkan waktu sejenak untuk melihat kemajuan kami melalui browser. Seperti yang ditunjukkan Gambar 5, Anda akan melihat tombol Pengiriman Produk Proses di atas GridView yang mencantumkan produk sepuluh sekaligus.

GridView Mendaftarkan Produk dan Menawarkan Kemampuan Pengurutan serta Penomoran Halaman

Gambar 5: GridView Mencantumkan Produk dan Menawarkan Kemampuan Sortir dan Halaman (Klik untuk melihat gambar ukuran penuh)

Langkah 2: Membuat Antarmuka Penyisipan

Dengan antarmuka tampilan selesai, kami siap untuk membuat antarmuka penyisipan. Untuk tutorial ini, mari kita buat antarmuka penyisipan yang meminta satu pemasok dan nilai kategori dan kemudian memungkinkan pengguna untuk memasukkan hingga lima nama produk dan nilai harga satuan. Dengan antarmuka ini, pengguna dapat menambahkan satu hingga lima produk baru yang semuanya memiliki kategori dan pemasok yang sama, tetapi memiliki nama dan harga produk yang unik.

Mulailah dengan menyeret Panel dari Kotak Alat ke Perancang, dan menempatkannya di bawah Panel DisplayInterface yang sudah ada. Atur ID properti Panel yang baru ditambahkan ini ke InsertingInterface dan atur propertinya Visible ke false. Kami akan menambahkan kode yang mengatur InsertingInterface properti Panel Visible ke true di Langkah 3. Bersihkan juga nilai properti Height dan Width pada Panel.

Selanjutnya, kita perlu membuat antarmuka penyisipan yang ditampilkan kembali di Gambar 1. Antarmuka ini dapat dibuat melalui berbagai teknik HTML, tetapi kita akan menggunakan yang cukup mudah: tabel empat kolom tujuh baris.

Nota

Saat memasukkan markup untuk elemen HTML <table> , saya lebih suka menggunakan tampilan Sumber. Meskipun Visual Studio memang memiliki alat untuk menambahkan <table> elemen melalui Perancang, Perancang tampaknya terlalu bersedia untuk menyuntikkan pengaturan style tanpa diminta ke dalam markup. Setelah saya membuat <table> markup, saya biasanya kembali ke Perancang untuk menambahkan kontrol Web dan mengatur propertinya. Saat membuat tabel dengan kolom dan baris yang telah ditentukan sebelumnya, saya lebih suka menggunakan HTML statis daripada kontrol Web Tabel karena kontrol Web apa pun yang ditempatkan dalam kontrol Web Tabel hanya dapat diakses menggunakan FindControl("controlID") pola . Namun, saya menggunakan kontrol Web Tabel untuk tabel berukuran dinamis (yang baris atau kolomnya didasarkan pada beberapa database atau kriteria yang ditentukan pengguna), karena kontrol Web Tabel dapat dibangun secara terprogram.

Masukkan markup berikut di dalam tag <asp:Panel> di InsertingInterface Panel.

<table class="DataWebControlStyle" cellspacing="0">
    <tr class="BatchInsertHeaderRow">
        <td class="BatchInsertLabel">Supplier:</td>
        <td></td>
        <td class="BatchInsertLabel">Category:</td>
        <td></td>
    </tr>
    <tr class="BatchInsertRow">
        <td class="BatchInsertLabel">Product:</td>
        <td></td>
        <td class="BatchInsertLabel">Price:</td>
        <td></td>
    </tr>
    <tr class="BatchInsertAlternatingRow">
        <td class="BatchInsertLabel">Product:</td>
        <td></td>
        <td class="BatchInsertLabel">Price:</td>
        <td></td>
    </tr>
    <tr class="BatchInsertRow">
        <td class="BatchInsertLabel">Product:</td>
        <td></td>
        <td class="BatchInsertLabel">Price:</td>
        <td></td>
    </tr>
    <tr class="BatchInsertAlternatingRow">
        <td class="BatchInsertLabel">Product:</td>
        <td></td>
        <td class="BatchInsertLabel">Price:</td>
        <td></td>
    </tr>
    <tr class="BatchInsertRow">
        <td class="BatchInsertLabel">Product:</td>
        <td></td>
        <td class="BatchInsertLabel">Price:</td>
        <td></td>
    </tr>
    <tr class="BatchInsertFooterRow">
        <td colspan="4">
        </td>
    </tr>
</table>

Markup ini <table> belum menyertakan kontrol Web apa pun, kami akan menambahkannya sesaat. Perhatikan bahwa setiap elemen <tr> berisi pengaturan kelas CSS tertentu: BatchInsertHeaderRow untuk baris header di mana DropDownList pemasok dan kategori akan ditempatkan; BatchInsertFooterRow untuk baris footer di mana Tombol Tambahkan Produk dari Pengiriman dan Batalkan akan berada; dan nilai bergantian BatchInsertRow dan BatchInsertAlternatingRow untuk baris-baris yang akan berisi kontrol TextBox untuk produk dan harga satuan. Saya telah membuat kelas CSS yang sesuai dalam Styles.css file untuk memberikan antarmuka penyisipan tampilan yang mirip dengan kontrol GridView dan DetailsView yang telah kami gunakan di seluruh tutorial ini. Kelas CSS ini ditunjukkan di bawah ini.

/*** Styles for ~/BatchData/BatchInsert.aspx tutorial ***/
.BatchInsertLabel
{
    font-weight: bold;
    text-align: right;
}
.BatchInsertHeaderRow td
{
    color: White;
    background-color: #900;
    padding: 11px;
}
.BatchInsertFooterRow td
{
    text-align: center;
    padding-top: 5px;
}
.BatchInsertRow
{
}
.BatchInsertAlternatingRow
{
    background-color: #fcc;
}

Dengan markup ini dimasukkan, kembali ke tampilan Desain. Ini <table> akan ditampilkan sebagai tabel empat kolom tujuh baris di Perancang, seperti diilustrasikan pada Gambar 6.

Antarmuka Penyisipan Terdiri dari Tabel Empat Kolom, Seven-Row

Gambar 6: Antarmuka Penyisipan Terdiri dari Empat Kolom, Seven-Row Tabel (Klik untuk melihat gambar ukuran penuh)

Kami sekarang siap untuk menambahkan kontrol Web ke antarmuka penyisipan. Seret dua DropDownList dari Kotak Alat ke masing-masing sel yang sesuai dalam tabel, satu guna pemasok dan satu guna kategori.

Atur properti DropDownList ID pemasok ke Suppliers dan ikat ke ObjectDataSource baru bernama SuppliersDataSource. Konfigurasikan ObjectDataSource baru untuk mengambil datanya dari metode kelas SuppliersBLL dan atur daftar drop-down tab UPDATE ke (Tidak Ada). Klik Selesai untuk menyelesaikan wizard.

Konfigurasi ObjectDataSource untuk Menggunakan Metode GetSuppliers dari Kelas SuppliersBLL

Gambar 7: Konfigurasikan ObjectDataSource untuk Menggunakan Metode SuppliersBLL Kelas GetSuppliers (Klik untuk melihat gambar penuh)

Suppliers Minta DropDownList menampilkan CompanyName bidang data dan gunakan SupplierID bidang data sebagai ListItem nilainya.

Tampilkan Bidang Data CompanyName dan Gunakan SupplierID sebagai Nilai

Gambar 8: Tampilkan CompanyName Bidang Data dan Gunakan SupplierID sebagai Nilai (Klik untuk melihat gambar ukuran penuh)

Beri nama DropDownList Categories kedua dan ikat ke ObjectDataSource baru bernama CategoriesDataSource. Konfigurasikan CategoriesDataSource ObjectDataSource untuk menggunakan metode CategoriesBLL kelas GetCategories; sesuaikan daftar drop-down di tab PERBARUI dan HAPUS ke (Tidak Ada) dan klik Selesai untuk menuntaskan wizard. Terakhir, minta DropDownList menampilkan CategoryName bidang data dan gunakan CategoryID sebagai nilai.

Setelah kedua DropDownList ini ditambahkan dan terikat ke ObjectDataSources yang dikonfigurasi dengan tepat, layar Anda akan terlihat mirip dengan Gambar 9.

Baris Header Sekarang Berisi Daftar DropDown Pemasok dan Kategori

Gambar 9: Baris Header Sekarang Berisi Suppliers dan Categories DropDownLists (Klik untuk melihat gambar ukuran penuh)

Kita sekarang perlu membuat TextBoxes untuk mengumpulkan nama dan harga untuk setiap produk baru. Seret kontrol TextBox dari Kotak Alat ke Perancang untuk masing-masing dari lima baris nama produk dan harga. Atur ID properti Kotak Teks ke ProductName1, , UnitPrice1, ProductName2UnitPrice2, ProductName3, UnitPrice3, dan sebagainya.

Tambahkan CompareValidator setelah setiap kotak teks harga satuan, mengatur properti ControlToValidate ke nilai yang sesuai ID. Juga atur properti Operator ke GreaterThanEqual, ValueToCompare ke 0, dan Type ke Currency. Pengaturan ini menginstruksikan CompareValidator untuk memastikan bahwa harga, jika dimasukkan, adalah nilai mata uang yang valid yang lebih besar dari atau sama dengan nol. Atur Text properti ke *, dan ErrorMessage ke Harga harus lebih besar dari atau sama dengan nol. Selain itu, silakan hilangkan simbol mata uang apa pun.

Nota

Antarmuka penyisipan tidak menyertakan kontrol RequiredFieldValidator apa pun, meskipun ProductName bidang dalam Products tabel database tidak mengizinkan NULL nilai. Ini karena kami ingin membiarkan pengguna memasukkan hingga lima produk. Misalnya, jika pengguna memberikan nama produk dan harga satuan untuk tiga baris pertama, membiarkan dua baris terakhir kosong, kami hanya menambahkan tiga produk baru ke sistem. Karena ProductName diperlukan, bagaimanapun, kita perlu memeriksa secara terprogram untuk memastikan bahwa jika harga satuan dimasukkan bahwa nilai nama produk yang sesuai disediakan. Kami akan mengatasi pemeriksaan ini di Langkah 4.

Saat memvalidasi input pengguna, CompareValidator melaporkan data yang tidak valid jika nilai berisi simbol mata uang. Tambahkan $ di depan setiap harga satuan TextBoxes untuk berfungsi sebagai isjin visual yang menginstruksikan pengguna untuk menghilangkan simbol mata uang saat memasukkan harga.

Terakhir, tambahkan kontrol ValidationSummary ke dalam InsertingInterface Panel, atur propertinya ShowMessageBox ke true dan atur propertinya ShowSummary ke false. Dengan pengaturan ini, jika pengguna memasukkan nilai harga unit yang tidak valid, tanda bintang akan muncul di samping kontrol TextBox yang menyinggung dan ValidationSummary akan menampilkan kotak pesan sisi klien yang menunjukkan pesan kesalahan yang kami tentukan sebelumnya.

Pada titik ini, layar Anda akan terlihat mirip dengan Gambar 10.

Antarmuka Penyisipan Sekarang Mencakup Kotak Teks untuk Nama dan Harga Produk

Gambar 10: Antarmuka Penyisipan Sekarang Menyertakan Kotak Teks untuk Nama dan Harga Produk (Klik untuk melihat gambar ukuran penuh)

Selanjutnya kita perlu menambahkan tombol Tambahkan Produk dari Pengiriman dan Batalkan ke baris footer. Seret dua kontrol Tombol dari Kotak Alat ke footer antarmuka penyisipan data, lalu atur properti Tombol ID ke AddProducts dan properti CancelButton dan Text masing-masing ke Tambahkan Produk dari Pengiriman dan Batalkan. Selain itu, atur CancelButton properti kontrol ke CausesValidationfalse.

Terakhir, kita perlu menambahkan kontrol Web Label yang akan menampilkan pesan status untuk dua antarmuka. Misalnya, ketika pengguna berhasil menambahkan pengiriman produk baru, kami ingin kembali ke antarmuka tampilan dan menampilkan pesan konfirmasi. Namun, jika pengguna memberikan harga untuk produk baru tetapi meninggalkan nama produk, kita perlu menampilkan pesan peringatan karena ProductName bidang diperlukan. Karena kita memerlukan pesan ini untuk ditampilkan untuk kedua antarmuka, letakkan di bagian atas halaman di luar Panel.

Seret kontrol Label Web dari Kotak Alat ke bagian atas halaman di Perancang. Atur ID properti ke StatusLabel, hapus Text properti, dan atur Visible properti dan EnableViewState ke false. Seperti yang telah kita lihat dalam tutorial sebelumnya, mengatur properti EnableViewState ke false memungkinkan kita untuk secara terprogram mengubah nilai-nilai properti Label dan mengembalikannya secara otomatis ke nilai default pada postback berikutnya. Ini menyederhanakan kode untuk menampilkan pesan status sebagai respons terhadap beberapa tindakan pengguna yang menghilang pada postback berikutnya. Terakhir, atur StatusLabel kontrol CssClass properti ke Peringatan, yang merupakan nama kelas CSS yang ditentukan dalam Styles.css yang menampilkan teks dalam font besar, miring, tebal, merah.

Gambar 11 memperlihatkan Visual Studio Designer setelah Label ditambahkan dan dikonfigurasi.

Tempatkan Kontrol StatusLabel di Atas Kontrol Dua Panel

Gambar 11: Tempatkan StatusLabel Kontrol di Atas Kontrol Dua Panel (Klik untuk melihat gambar ukuran penuh)

Langkah 3: Beralih Antara Tampilan dan Menyisipkan Antarmuka

Pada titik ini kami telah menyelesaikan markup untuk tampilan dan menyisipkan antarmuka kami, tetapi kami masih tersisa dengan dua tugas:

  • Beralih antara tampilan dan menyisipkan antarmuka
  • Menambahkan produk dalam pengiriman ke database

Saat ini, antarmuka tampilan terlihat tetapi antarmuka penyisipan disembunyikan. Ini karena properti DisplayInterface Panel Visible diatur ke true (nilai default), sementara properti InsertingInterface Panel Visible diatur ke false. Untuk beralih di antara dua antarmuka, kita hanya perlu mengalihkan setiap nilai properti kontrol Visible .

Kami ingin berpindah dari antarmuka tampilan ke antarmuka penyisipan saat tombol Proses Pengiriman Produk diklik. Oleh karena itu, buat pengendali peristiwa untuk peristiwa Button Click ini yang berisi kode berikut:

protected void ProcessShipment_Click(object sender, EventArgs e)
{
    DisplayInterface.Visible = false;
    InsertingInterface.Visible = true;
}

Kode ini hanya menyembunyikan DisplayInterface Panel dan menunjukkan InsertingInterface Panel.

Selanjutnya, buat penanganan aktivitas untuk kontrol Tambahkan Produk dari Pengiriman dan Batalkan Tombol di antarmuka penyisipan. Ketika salah satu Tombol ini diklik, kita perlu kembali ke antarmuka tampilan. Buat Click penanganan aktivitas untuk kedua kontrol Tombol sehingga mereka memanggil ReturnToDisplayInterface, metode yang akan kita tambahkan sesaat. Selain menyembunyikan InsertingInterface Panel dan menampilkan DisplayInterface Panel, ReturnToDisplayInterface metode ini perlu mengembalikan kontrol Web ke status pra-pengeditannya. Ini melibatkan pengaturan properti DropDownLists SelectedIndex ke 0 dan menghapus Text properti kontrol TextBox.

Nota

Pertimbangkan apa yang mungkin terjadi jika kami tidak mengembalikan kontrol ke status pra-pengeditan sebelum kembali ke antarmuka tampilan. Pengguna dapat mengklik tombol Proses Pengiriman Produk, memasukkan produk dari pengiriman, lalu klik Tambahkan Produk dari Pengiriman. Ini akan menambahkan produk dan mengembalikan pengguna ke antarmuka tampilan. Pada titik ini pengguna mungkin ingin menambahkan pengiriman lain. Setelah mengklik tombol Pengiriman Produk Proses, mereka akan kembali ke antarmuka penyisipan tetapi pilihan DropDownList dan nilai TextBox masih akan diisi dengan nilai sebelumnya.

protected void AddProducts_Click(object sender, EventArgs e)
{
    // TODO: Save the products
    // Revert to the display interface
    ReturnToDisplayInterface();
}
protected void CancelButton_Click(object sender, EventArgs e)
{
    // Revert to the display interface
    ReturnToDisplayInterface();
}
const int firstControlID = 1;
const int lastControlID = 5;
private void ReturnToDisplayInterface()
{
    // Reset the control values in the inserting interface
    Suppliers.SelectedIndex = 0;
    Categories.SelectedIndex = 0;
    for (int i = firstControlID; i <= lastControlID; i++)
    {
        ((TextBox)InsertingInterface.FindControl("ProductName" + i.ToString())).Text =
            string.Empty;
        ((TextBox)InsertingInterface.FindControl("UnitPrice" + i.ToString())).Text = 
            string.Empty;
    }
    DisplayInterface.Visible = true;
    InsertingInterface.Visible = false;
}

Kedua Click penangan acara hanya memanggil metode ReturnToDisplayInterface, meskipun kita akan kembali ke penangan acara Tambahkan Produk dari Pengiriman Click di Langkah 4 dan menambahkan kode untuk menyimpan produk-produk. ReturnToDisplayInterface dimulai dengan mengembalikan Suppliers dan Categories DropDownLists ke opsi pertamanya. Dua konstanta firstControlID dan lastControlID menandai nilai indeks kontrol awal dan akhir yang digunakan untuk penamaan TextBoxes nama produk dan harga satuan di antarmuka penyisipan, dan digunakan dalam batas for perulangan yang mengatur properti Text dari kontrol TextBox agar kembali ke string kosong. Terakhir, properti Panel Visible diatur ulang sehingga antarmuka penyisipan disembunyikan dan antarmuka tampilan ditampilkan.

Luangkan waktu sejenak untuk menguji halaman ini di browser. Ketika pertama kali mengunjungi halaman, Anda akan melihat antarmuka tampilan seperti yang ditunjukkan pada Gambar 5. Klik tombol Proses Pengiriman Produk. Halaman akan memuat ulang, dan Anda sekarang akan melihat antarmuka penyisipan seperti yang ditunjukkan pada Gambar 12. Mengklik tombol Tambahkan Produk dari Pengiriman atau Batal mengembalikan Anda ke antarmuka tampilan.

Nota

Saat melihat antarmuka penyisipan, luangkan waktu sejenak untuk menguji CompareValidators pada kolom teks harga satuan. Anda akan melihat peringatan kotak pesan sisi klien saat mengklik tombol Tambahkan Produk dari Pengiriman dengan nilai mata uang atau harga yang tidak valid dengan nilai kurang dari nol.

Antarmuka Penyisipan Ditampilkan Setelah Mengklik Tombol Proses Pengiriman Produk

Gambar 12: Antarmuka Penyisipan Ditampilkan Setelah Mengklik Tombol Proses Pengiriman Produk (Klik untuk melihat gambar ukuran penuh)

Langkah 4: Menambahkan Produk

Semua yang tersisa untuk tutorial ini adalah menyimpan produk ke database di penanganan aktivitas Tambahkan Produk dari Tombol Click Pengiriman. Ini dapat dicapai dengan membuat ProductsDataTable dan menambahkan ProductsRow instans untuk setiap nama produk yang disediakan. Setelah ProductsRow ini ditambahkan, kami akan melakukan panggilan ke metode kelas ProductsBLL s UpdateWithTransaction dengan mengoperkan ProductsDataTable. Ingat bahwa metode UpdateWithTransaction, yang dibuat sebelumnya dalam tutorial Pembungkusan Modifikasi Database dalam Transaksi, meneruskan ProductsDataTable ke ProductsTableAdapter metode s UpdateWithTransaction. Dari sana, transaksi ADO.NET dimulai, dan TableAdapter mengeluarkan pernyataan INSERT ke database untuk setiap ProductsRow yang ditambahkan dalam DataTable. Dengan asumsi semua produk ditambahkan tanpa kesalahan, transaksi dilakukan, jika tidak, itu digulung balik.

Kode untuk penanganan aktivitas Tambahkan Produk dari Tombol Click Pengiriman juga perlu melakukan sedikit pemeriksaan kesalahan. Karena tidak ada RequiredFieldValidators yang digunakan dalam antarmuka penyisipan, pengguna dapat memasukkan harga untuk produk sambil menghilangkan namanya. Karena nama produk diperlukan, kita perlu memperingatkan pengguna dan tidak melanjutkan dengan penyisipan jika kondisi seperti itu terungkap. Kode penanganan aktivitas lengkap Click mengikuti:

protected void AddProducts_Click(object sender, EventArgs e)
{
    // Make sure that the UnitPrice CompareValidators report valid data...
    if (!Page.IsValid)
        return;
    // Add new ProductsRows to a ProductsDataTable...
    Northwind.ProductsDataTable products = new Northwind.ProductsDataTable();
    for (int i = firstControlID; i <= lastControlID; i++)
    {
        // Read in the values for the product name and unit price
        string productName = ((TextBox)InsertingInterface.FindControl
            ("ProductName" + i.ToString())).Text.Trim();
        string unitPrice = ((TextBox)InsertingInterface.FindControl
            ("UnitPrice" + i.ToString())).Text.Trim();
        // Ensure that if unitPrice has a value, so does productName
        if (unitPrice.Length > 0 && productName.Length == 0)
        {
            // Display a warning and exit this event handler
            StatusLabel.Text = "If you provide a unit price you must also " +
                "include the name of the product.";
            StatusLabel.Visible = true;
            return;
        }
        // Only add the product if a product name value is provided
        if (productName.Length > 0)
        {
            // Add a new ProductsRow to the ProductsDataTable
            Northwind.ProductsRow newProduct = products.NewProductsRow();
            // Assign the values from the web page
            newProduct.ProductName = productName;
            newProduct.SupplierID = Convert.ToInt32(Suppliers.SelectedValue);
            newProduct.CategoryID = Convert.ToInt32(Categories.SelectedValue);
            if (unitPrice.Length > 0)
                newProduct.UnitPrice = Convert.ToDecimal(unitPrice);
            // Add any "default" values
            newProduct.Discontinued = false;
            newProduct.UnitsOnOrder = 0;
            products.AddProductsRow(newProduct);
        }
    }
    // If we reach here, see if there were any products added
    if (products.Count > 0)
    {
        // Add the new products to the database using a transaction
        ProductsBLL productsAPI = new ProductsBLL();
        productsAPI.UpdateWithTransaction(products);
        // Rebind the data to the grid so that the products just added are displayed
        ProductsGrid.DataBind();
        // Display a confirmation (don't use the Warning CSS class, though)
        StatusLabel.CssClass = string.Empty;
        StatusLabel.Text = string.Format(
            "{0} products from supplier {1} have been added and filed under " + 
            "category {2}.", products.Count, Suppliers.SelectedItem.Text, 
            Categories.SelectedItem.Text);
        StatusLabel.Visible = true;
        // Revert to the display interface
        ReturnToDisplayInterface();
    }
    else
    {
        // No products supplied!
        StatusLabel.Text = "No products were added. Please enter the product " + 
            "names and unit prices in the textboxes.";
        StatusLabel.Visible = true;
    }
}

Penanganan aktivitas dimulai dengan memastikan bahwa Page.IsValid properti mengembalikan nilai true. Jika mengembalikan false, maka itu berarti satu atau beberapa CompareValidator melaporkan data yang tidak valid; dalam kasus seperti itu kami tidak ingin mencoba memasukkan produk yang dimasukkan, karena hal tersebut akan menyebabkan pengecualian ketika mencoba menetapkan nilai harga unit yang dimasukkan pengguna ke properti ProductsRowUnitPrice.

Selanjutnya, instans baru ProductsDataTable dibuat (products). Perulangan for digunakan untuk melakukan iterasi melalui TextBoxes nama produk dan harga satuan, sementara atribut Text dibaca ke dalam variabel lokal productName dan unitPrice. Jika pengguna telah memasukkan nilai untuk harga satuan tetapi tidak untuk nama produk yang sesuai, StatusLabel menampilkan pesan Jika Anda memberikan harga satuan, Anda juga harus menyertakan nama produk dan penanganan acara dihentikan.

Jika nama produk telah disediakan, instans baru ProductsRow dibuat dengan menggunakan metode ProductsDataTable s NewProductsRow. Properti baru instance ProductsRow ini diatur ke TextBox nama produk saat ini, sementara properti ProductName dan SupplierID ditetapkan ke properti CategoryID dari DropDownLists di header antarmuka penyisipan. Jika pengguna memasukkan nilai untuk harga produk, nilai tersebut ditetapkan ke properti milik instans ProductsRowUnitPrice; jika tidak demikian, properti akan dibiarkan tidak ditetapkan, yang akan menghasilkan nilai NULL untuk UnitPrice dalam database. Akhirnya, properti Discontinued dan UnitsOnOrder ditetapkan ke nilai yang dikodekan secara permanen false dan 0 secara berturut-turut.

Setelah properti ditetapkan ke instans ProductsRow, instans tersebut ditambahkan ke ProductsDataTable.

Pada penyelesaian for perulangan, kami memeriksa apakah ada produk yang telah ditambahkan. Pengguna dapat, bagaimanapun juga, telah mengklik opsi Tambahkan Produk dari Pengiriman sebelum memasukkan nama atau harga produk apa pun. Jika setidaknya ada satu produk dalam ProductsDataTable, metode kelas ProductsBLLUpdateWithTransaction dipanggil. Selanjutnya, data di-rebound ke ProductsGrid GridView sehingga produk yang baru ditambahkan akan muncul di antarmuka tampilan. StatusLabel diperbarui untuk menampilkan pesan konfirmasi dan ReturnToDisplayInterface dipanggil, sehingga menyembunyikan antarmuka penyisipan dan menampilkan antarmuka tampilan.

Jika tidak ada produk yang dimasukkan, antarmuka penyisipan tetap ditampilkan tetapi pesan Tidak ada produk yang ditambahkan. Masukkan nama produk dan harga satuan di kotak teks ditampilkan.

Gambar 13, 14, dan 15 menunjukkan antarmuka penyisipan dan tampilan sedang beraksi. Pada Gambar 13, pengguna telah memasukkan nilai harga satuan tanpa nama produk yang sesuai. Gambar 14 menunjukkan antarmuka tampilan setelah tiga produk baru berhasil ditambahkan, sementara Gambar 15 menunjukkan dua produk yang baru ditambahkan di GridView (yang ketiga ada di halaman sebelumnya).

Nama Produk Diperlukan Saat Memasukkan Harga Satuan

Gambar 13: Nama Produk Diperlukan Saat Memasukkan Harga Satuan (Klik untuk melihat gambar ukuran penuh)

Tiga Sayuran Baru Telah Ditambahkan untuk Pemasok Mayumi s

Gambar 14: Tiga Sayuran Baru Telah Ditambahkan untuk Pemasok Mayumi (Klik untuk melihat gambar ukuran penuh)

Produk Baru Dapat Ditemukan di Halaman Terakhir GridView

Gambar 15: Produk Baru Dapat Ditemukan di Halaman Terakhir Dari GridView (Klik untuk melihat gambar ukuran penuh)

Nota

Logika penyisipan batch yang digunakan dalam tutorial ini mengemas penyisipan dalam cakupan transaksi. Untuk memverifikasi ini, sengaja memasukkan kesalahan pada tingkat database. Misalnya, daripada menetapkan properti instans ProductsRow baru CategoryID ke nilai yang dipilih di Categories DropDownList, tetapkan ke nilai seperti i * 5. Berikut i adalah pengindeks perulangan dan memiliki nilai mulai dari 1 hingga 5. Oleh karena itu, ketika menambahkan dua produk atau lebih dalam sisipan batch, produk pertama akan memiliki nilai yang valid CategoryID (5), tetapi produk berikutnya akan memiliki CategoryID nilai yang tidak cocok dengan CategoryID nilai dalam Categories tabel. Dampak akhirnya adalah bahwa meskipun yang pertama INSERT akan berhasil, yang berikutnya akan gagal dengan pelanggaran batasan foreign key. Karena sisipan batch bersifat atomik, yang pertama INSERT akan dibatalkan, mengembalikan database ke keadaannya sebelum proses penyisipan batch dimulai.

Ringkasan

Selama ini dan dua tutorial sebelumnya, kami telah membuat antarmuka yang memungkinkan untuk memperbarui, menghapus, dan menyisipkan batch data, yang semuanya menggunakan dukungan transaksi yang kami tambahkan ke Lapisan Akses Data dalam tutorial Membungkus Modifikasi Database dalam Transaksi. Untuk skenario tertentu, antarmuka pengguna pemrosesan batch tersebut sangat meningkatkan efisiensi pengguna akhir dengan mengurangi jumlah klik, postback, dan sakelar konteks keyboard-ke-mouse, sambil juga mempertahankan integritas data yang mendasarinya.

Tutorial ini melengkapi tampilan kami dalam bekerja dengan data batch. Set tutorial berikutnya mengeksplorasi berbagai skenario Lapisan Akses Data tingkat lanjut, termasuk menggunakan prosedur tersimpan dalam metode TableAdapter s, mengonfigurasi pengaturan tingkat koneksi dan perintah di DAL, mengenkripsi string koneksi, dan banyak lagi!

Selamat Pemrograman!

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.

Ucapan terima kasih khusus kepada

Seri tutorial ini ditinjau oleh banyak peninjau yang bermanfaat. Peninjau utama untuk tutorial ini adalah Hilton Giesenow dan S ren Jacob Lauritsen. Tertarik untuk meninjau artikel MSDN saya yang akan datang? Jika demikian, hubungi saya di mitchell@4GuysFromRolla.com.