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
Opsi halaman default kontrol presentasi data tidak cocok saat bekerja dengan data dalam jumlah besar, karena kontrol sumber data yang mendasar mengambil semua rekaman, meskipun hanya subkumpulan data yang ditampilkan. Dalam keadaan seperti itu, kita harus beralih ke halaman kustom.
Pendahuluan
Seperti yang kita bahas dalam tutorial sebelumnya, penomor dapat diimplementasikan dengan salah satu dari dua cara:
- Halaman Default dapat diimplementasikan hanya dengan memeriksa opsi Aktifkan Halaman di tag pintar kontrol Web data; namun, setiap kali melihat halaman data, ObjectDataSource mengambil semua rekaman, meskipun hanya subset yang ditampilkan di halaman
- Halaman Kustom meningkatkan performa halaman default dengan mengambil hanya rekaman dari database yang perlu ditampilkan untuk halaman data tertentu yang diminta oleh pengguna; namun, penomor kustom melibatkan sedikit lebih banyak upaya untuk diterapkan daripada penomor default
Karena kemudahan implementasi, periksa kotak centang dan Anda selesai! halaman default adalah opsi yang menarik. Pendekatan naifnya dalam mengambil semua catatan, meskipun, menjadikannya pilihan yang tidak masuk akal ketika penomoran melalui data dalam jumlah yang cukup besar atau untuk situs dengan banyak pengguna bersamaan. Dalam keadaan seperti itu, kita harus beralih ke halaman kustom untuk menyediakan sistem yang responsif.
Tantangan penomor kustom adalah dapat menulis kueri yang mengembalikan kumpulan rekaman yang tepat yang diperlukan untuk halaman data tertentu. Untungnya, Microsoft SQL Server 2005 menyediakan kata kunci baru untuk hasil peringkat, yang memungkinkan kami menulis kueri yang dapat mengambil subset rekaman yang tepat secara efisien. Dalam tutorial ini kita akan melihat cara menggunakan kata kunci SQL Server 2005 baru ini untuk mengimplementasikan halaman kustom dalam kontrol GridView. Meskipun antarmuka pengguna untuk penomor kustom identik dengan itu untuk halaman default, melangkah dari satu halaman ke halaman berikutnya menggunakan halaman kustom bisa menjadi beberapa urutan besarnya lebih cepat daripada halaman default.
Catatan
Perolehan performa yang tepat dipamerkan oleh penomoran halaman kustom tergantung pada jumlah total rekaman yang dipatuhi dan beban yang ditempatkan di server database. Di akhir tutorial ini kita akan melihat beberapa metrik kasar yang menampilkan manfaat dalam performa yang diperoleh melalui penomor kustom.
Langkah 1: Memahami Proses Halaman Kustom
Saat penomoran melalui data, rekaman yang tepat ditampilkan di halaman bergantung pada halaman data yang diminta dan jumlah rekaman yang ditampilkan per halaman. Misalnya, bayangkan bahwa kami ingin halaman melalui 81 produk, menampilkan 10 produk per halaman. Saat melihat halaman pertama, kami menginginkan produk 1 hingga 10; ketika melihat halaman kedua kita akan tertarik pada produk 11 hingga 20, dan sebagainya.
Ada tiga variabel yang menentukan rekaman apa yang perlu diambil dan bagaimana antarmuka halaman harus dirender:
- Indeks Baris Mulai indeks baris pertama di halaman data yang akan ditampilkan; indeks ini dapat dihitung dengan mengalikan indeks halaman dengan rekaman yang akan ditampilkan per halaman dan menambahkannya. Misalnya, saat halaman melalui rekaman 10 per satu, untuk halaman pertama (yang indeks halamannya adalah 0), Indeks Baris Mulai adalah 0 * 10 + 1, atau 1; untuk halaman kedua (yang indeks halamannya adalah 1), Indeks Baris Mulai adalah 1 * 10 + 1, atau 11.
- Baris Maksimum jumlah maksimum rekaman yang akan ditampilkan per halaman. Variabel ini disebut sebagai baris maksimum karena untuk halaman terakhir mungkin ada lebih sedikit rekaman yang dikembalikan daripada ukuran halaman. Misalnya, ketika halaman melalui 81 produk 10 rekaman per halaman, halaman kesembilan dan terakhir hanya akan memiliki satu catatan. Namun, tidak ada halaman yang akan menampilkan lebih banyak rekaman daripada nilai Baris Maksimum.
- Total Catatan Menghitung jumlah total rekaman yang di-paged through. Meskipun variabel ini tidak diperlukan untuk menentukan rekaman apa yang akan diambil untuk halaman tertentu, variabel ini menentukan antarmuka halaman. Misalnya, jika ada 81 produk yang di-paged through, antarmuka paging tahu untuk menampilkan sembilan nomor halaman di antarmuka pengguna halaman.
Dengan halaman default, Indeks Baris Mulai dihitung sebagai produk indeks halaman dan ukuran halaman ditambah satu, sedangkan Baris Maksimum hanyalah ukuran halaman. Karena halaman default mengambil semua rekaman dari database saat merender halaman data apa pun, indeks untuk setiap baris diketahui, sehingga membuat pemindahan ke baris Indeks Baris Mulai menjadi tugas sepele. Selain itu, Jumlah Rekaman Total tersedia dengan mudah, karena hanya jumlah rekaman dalam DataTable (atau objek apa pun yang digunakan untuk menyimpan hasil database).
Mengingat variabel Indeks Baris Mulai dan Baris Maksimum, implementasi penomoran halaman kustom hanya boleh mengembalikan subset rekaman yang tepat yang dimulai pada Indeks Baris Mulai dan hingga Jumlah Baris Maksimum dari rekaman setelah itu. Penomor kustom memberikan dua tantangan:
- Kita harus dapat mengaitkan indeks baris secara efisien dengan setiap baris di seluruh data yang di-paged through sehingga kita dapat mulai mengembalikan rekaman pada Indeks Baris Mulai yang ditentukan
- Kita perlu menyediakan jumlah total rekaman yang di-paged through
Dalam dua langkah berikutnya kita akan memeriksa skrip SQL yang diperlukan untuk merespons kedua tantangan ini. Selain skrip SQL, kita juga perlu menerapkan metode di DAL dan BLL.
Langkah 2: Mengembalikan Jumlah Total Rekaman yang Di-Paged Through
Sebelum kita memeriksa cara mengambil subset rekaman yang tepat untuk halaman yang ditampilkan, mari kita lihat terlebih dahulu cara mengembalikan jumlah total rekaman yang di-paged through. Informasi ini diperlukan untuk mengonfigurasi antarmuka pengguna halaman dengan benar. Jumlah total rekaman yang dikembalikan oleh kueri SQL tertentu dapat diperoleh dengan menggunakan COUNT
fungsi agregat. Misalnya, untuk menentukan jumlah total rekaman dalam Products
tabel, kita bisa menggunakan kueri berikut:
SELECT COUNT(*)
FROM Products
Mari kita tambahkan metode ke DAL kita yang mengembalikan informasi ini. Secara khusus, kita akan membuat metode DAL yang disebut TotalNumberOfProducts()
yang menjalankan pernyataan yang ditunjukkan SELECT
di atas.
Mulailah dengan membuka file Himpunan Northwind.xsd
Data Yang Dititik di App_Code/DAL
folder . Selanjutnya, klik kanan pada ProductsTableAdapter
di Perancang dan pilih Tambahkan Kueri. Seperti yang telah kita lihat dalam tutorial sebelumnya, ini akan memungkinkan kita untuk menambahkan metode baru ke DAL yang, ketika dipanggil, akan menjalankan pernyataan SQL tertentu atau prosedur tersimpan. Seperti metode TableAdapter kami dalam tutorial sebelumnya, untuk yang satu ini memilih untuk menggunakan pernyataan SQL ad-hoc.
Gambar 1: Menggunakan Pernyataan Ad-Hoc SQL
Pada layar berikutnya kita dapat menentukan jenis kueri apa yang akan dibuat. Karena kueri ini akan mengembalikan satu, nilai skalar jumlah total rekaman dalam Products
tabel memilih SELECT
opsi yang mengembalikan nilai singe.
Gambar 2: Mengonfigurasi Kueri untuk Menggunakan Pernyataan SELECT yang Mengembalikan Nilai Tunggal
Setelah menunjukkan jenis kueri yang akan digunakan, selanjutnya kita harus menentukan kueri.
Gambar 3: Gunakan KUERI SELECT COUNT(*) FROM Products
Terakhir, tentukan nama untuk metode . Seperti yang disebutkan di dalamnya, mari kita gunakan TotalNumberOfProducts
.
Gambar 4: Beri nama Metode DAL TotalNumberOfProducts
Setelah mengklik Selesai, wizard akan menambahkan TotalNumberOfProducts
metode ke DAL. Metode pengembalian skalar dalam DAL mengembalikan jenis nullable, jika hasil dari kueri SQL adalah NULL
. Kueri kami COUNT
, bagaimanapun, akan selalu mengembalikan nilai nonNULL
; terlepas dari itu, metode DAL mengembalikan bilangan bulat null.
Selain metode DAL, kita juga membutuhkan metode di BLL.
ProductsBLL
Buka file kelas dan tambahkan TotalNumberOfProducts
metode yang hanya memanggil ke metode DAL sTotalNumberOfProducts
:
public int TotalNumberOfProducts()
{
return Adapter.TotalNumberOfProducts().GetValueOrDefault();
}
Metode DAL s TotalNumberOfProducts
mengembalikan bilangan bulat null; namun, kami telah membuat ProductsBLL
metode kelas s TotalNumberOfProducts
sehingga mengembalikan bilangan bulat standar. Oleh karena itu, kita harus memiliki ProductsBLL
metode kelas s TotalNumberOfProducts
mengembalikan bagian nilai dari bilangan bulat null yang dikembalikan oleh metode DAL s TotalNumberOfProducts
. Panggilan untuk GetValueOrDefault()
mengembalikan nilai bilangan bulat null, jika ada; jika bilangan bulat null adalah null
, namun, nilai bilangan bulat default, 0.
Langkah 3: Mengembalikan Subset Rekaman yang Tepat
Tugas kami berikutnya adalah membuat metode di DAL dan BLL yang menerima variabel Indeks Baris Mulai dan Baris Maksimum yang dibahas sebelumnya dan mengembalikan rekaman yang sesuai. Sebelum kita melakukannya, mari kita lihat terlebih dahulu skrip SQL yang diperlukan. Tantangan yang dihadapi kita adalah bahwa kita harus dapat menetapkan indeks secara efisien ke setiap baris di seluruh hasil yang di-paged through sehingga kita dapat mengembalikan hanya rekaman tersebut yang dimulai di Indeks Baris Mulai (dan hingga jumlah rekaman Rekaman Maksimum).
Ini bukan tantangan jika sudah ada kolom dalam tabel database yang berfungsi sebagai indeks baris. Pada pandangan pertama kita mungkin berpikir bahwa Products
bidang tabel ProductID
sudah cukup, karena produk pertama memiliki ProductID
1, yang kedua 2, dan sebagainya. Namun, menghapus produk meninggalkan celah dalam urutan, membatalkan pendekatan ini.
Ada dua teknik umum yang digunakan untuk mengaitkan indeks baris secara efisien dengan data ke halaman, sehingga memungkinkan subset rekaman yang tepat untuk diambil:
ROW_NUMBER()
SQL Server 2005 s baru ke SQL Server 2005,ROW_NUMBER()
kata kunci mengaitkan peringkat dengan setiap rekaman yang dikembalikan berdasarkan beberapa pemesanan. Peringkat ini dapat digunakan sebagai indeks baris untuk setiap baris.Menggunakan variabel tabel dan
SET ROWCOUNT
pernyataanSET ROWCOUNT
digunakan untuk menentukan berapa banyak total rekaman yang harus diproses kueri sebelum mengakhiri; variabel tabel adalah variabel T-SQL lokal yang dapat menyimpan data tabular, mirip dengan tabel sementara. Pendekatan ini bekerja sama baiknya dengan Microsoft SQL Server 2005 dan SQL Server 2000 (sedangkanROW_NUMBER()
pendekatan hanya berfungsi dengan SQL Server 2005).Idenya di sini adalah membuat variabel tabel yang memiliki
IDENTITY
kolom dan kolom untuk kunci utama tabel yang datanya sedang di-paged through. Selanjutnya, konten tabel yang datanya sedang di-paged through dibuang ke dalam variabel tabel, sehingga mengaitkan indeks baris berurutan (melaluiIDENTITY
kolom) untuk setiap rekaman dalam tabel. Setelah variabel tabel diisi,SELECT
pernyataan pada variabel tabel, digabungkan dengan tabel yang mendasarinya, dapat dijalankan untuk menarik keluar rekaman tertentu. PernyataanSET ROWCOUNT
ini digunakan untuk secara cerdas membatasi jumlah rekaman yang perlu dibuang ke dalam variabel tabel.Efisiensi pendekatan ini didasarkan pada nomor halaman yang diminta, karena
SET ROWCOUNT
nilai ditetapkan nilai Indeks Baris Mulai ditambah Baris Maksimum. Ketika penomoran melalui halaman bernomor rendah seperti beberapa halaman pertama data, pendekatan ini sangat efisien. Namun, ini menunjukkan performa seperti halaman default saat mengambil halaman di dekat akhir.
Tutorial ini mengimplementasikan penomor kustom menggunakan ROW_NUMBER()
kata kunci. Untuk informasi selengkapnya tentang menggunakan variabel dan SET ROWCOUNT
teknik tabel, lihat Paging Secara Efisien Melalui Data Dalam Jumlah Besar.
Kata ROW_NUMBER()
kunci yang terkait dengan peringkat dengan setiap rekaman yang dikembalikan melalui pengurutan tertentu menggunakan sintaks berikut:
SELECT columnList,
ROW_NUMBER() OVER(orderByClause)
FROM TableName
ROW_NUMBER()
mengembalikan nilai numerik yang menentukan peringkat untuk setiap rekaman sehubungan dengan pengurutan yang ditunjukkan. Misalnya, untuk melihat peringkat untuk setiap produk, diurutkan dari yang paling mahal hingga yang paling murah, kita dapat menggunakan kueri berikut:
SELECT ProductName, UnitPrice,
ROW_NUMBER() OVER(ORDER BY UnitPrice DESC) AS PriceRank
FROM Products
Gambar 5 memperlihatkan hasil kueri ini saat dijalankan melalui jendela kueri di Visual Studio. Perhatikan bahwa produk dipesan berdasarkan harga, bersama dengan peringkat harga untuk setiap baris.
Gambar 5: Peringkat Harga Disertakan untuk Setiap Rekaman yang Dikembalikan
Catatan
ROW_NUMBER()
hanyalah salah satu dari banyak fungsi peringkat baru yang tersedia di SQL Server 2005. Untuk diskusi yang lebih menyeluruh tentang ROW_NUMBER()
, bersama dengan fungsi peringkat lainnya, baca Mengembalikan Hasil Berpangkat dengan Microsoft SQL Server 2005.
Saat memberi peringkat hasil berdasarkan kolom yang ditentukan ORDER BY
dalam OVER
klausa (UnitPrice
, dalam contoh di atas), SQL Server harus mengurutkan hasilnya. Ini adalah operasi cepat jika ada indeks berkluster di atas kolom hasil yang diurutkan oleh, atau jika ada indeks yang mencakup, tetapi bisa lebih mahal jika tidak. Untuk membantu meningkatkan performa untuk kueri yang cukup besar, pertimbangkan untuk menambahkan indeks non-kluster untuk kolom tempat hasil diurutkan. Lihat Fungsi dan Performa Peringkat di SQL Server 2005 untuk melihat pertimbangan performa yang lebih rinci.
Informasi peringkat yang dikembalikan oleh ROW_NUMBER()
tidak dapat langsung digunakan dalam WHERE
klausa. Namun, tabel turunan dapat digunakan untuk mengembalikan hasilnya ROW_NUMBER()
, yang kemudian dapat muncul dalam WHERE
klausa. Misalnya, kueri berikut menggunakan tabel turunan untuk mengembalikan kolom ProductName dan UnitPrice, bersama dengan ROW_NUMBER()
hasilnya, lalu menggunakan klausul WHERE
untuk hanya mengembalikan produk yang peringkat harganya antara 11 dan 20:
SELECT PriceRank, ProductName, UnitPrice
FROM
(SELECT ProductName, UnitPrice,
ROW_NUMBER() OVER(ORDER BY UnitPrice DESC) AS PriceRank
FROM Products
) AS ProductsWithRowNumber
WHERE PriceRank BETWEEN 11 AND 20
Memperluas konsep ini sedikit lebih jauh, kita dapat menggunakan pendekatan ini untuk mengambil halaman data tertentu mengingat nilai Indeks Baris Mulai dan Baris Maksimum yang diinginkan:
SELECT PriceRank, ProductName, UnitPrice
FROM
(SELECT ProductName, UnitPrice,
ROW_NUMBER() OVER(ORDER BY UnitPrice DESC) AS PriceRank
FROM Products
) AS ProductsWithRowNumber
WHERE PriceRank > <i>StartRowIndex</i> AND
PriceRank <= (<i>StartRowIndex</i> + <i>MaximumRows</i>)
Catatan
Seperti yang akan kita lihat nanti dalam tutorial ini, StartRowIndex
yang disediakan oleh ObjectDataSource diindeks mulai dari nol, sedangkan nilai yang ROW_NUMBER()
dikembalikan oleh SQL Server 2005 diindeks mulai dari 1. Oleh karena itu, WHERE
klausul mengembalikan rekaman tersebut di mana PriceRank
secara ketat lebih besar dari StartRowIndex
dan kurang dari atau sama dengan StartRowIndex
+ MaximumRows
.
Sekarang setelah kita membahas bagaimana ROW_NUMBER()
dapat digunakan untuk mengambil halaman data tertentu mengingat nilai Indeks Baris Mulai dan Baris Maksimum, kita sekarang perlu menerapkan logika ini sebagai metode dalam DAL dan BLL.
Saat membuat kueri ini, kita harus memutuskan urutan di mana hasilnya akan diberi peringkat; mari kita urutkan produk berdasarkan namanya dalam urutan alfabet. Ini berarti bahwa dengan implementasi penomoran halaman kustom dalam tutorial ini kita tidak akan dapat membuat laporan halaman kustom daripada yang juga dapat diurutkan. Namun, dalam tutorial berikutnya, kita akan melihat bagaimana fungsionalitas tersebut dapat disediakan.
Di bagian sebelumnya kami membuat metode DAL sebagai pernyataan SQL ad-hoc. Sayangnya, pengurai T-SQL di Visual Studio yang digunakan oleh wizard TableAdapter tidak menyukai sintaks yang OVER
digunakan oleh ROW_NUMBER()
fungsi . Oleh karena itu, kita harus membuat metode DAL ini sebagai prosedur tersimpan. Pilih Penjelajah Server dari menu Tampilan (atau tekan Ctrl+Alt+S) dan perluas simpul NORTHWND.MDF
. Untuk menambahkan prosedur tersimpan baru, klik kanan pada simpul Prosedur Tersimpan dan pilih Tambahkan Prosedur Tersimpan Baru (lihat Gambar 6).
Gambar 6: Tambahkan Prosedur Tersimpan Baru untuk Paging Melalui Produk
Prosedur tersimpan ini harus menerima dua parameter input bilangan bulat - dan dan menggunakan @startRowIndex
fungsi yang diurutkan oleh @maximumRows
bidang , hanya mengembalikan baris yang lebih besar dari yang ditentukan ROW_NUMBER()
dan kurang dari atau sama dengan ProductName
@startRowIndex
@startRowIndex
s. + @maximumRow
Masukkan skrip berikut ke dalam prosedur tersimpan baru lalu klik ikon Simpan untuk menambahkan prosedur tersimpan ke database.
CREATE PROCEDURE dbo.GetProductsPaged
(
@startRowIndex int,
@maximumRows int
)
AS
SELECT ProductID, ProductName, SupplierID, CategoryID, QuantityPerUnit,
UnitPrice, UnitsInStock, UnitsOnOrder, ReorderLevel, Discontinued,
CategoryName, SupplierName
FROM
(
SELECT ProductID, ProductName, SupplierID, CategoryID, QuantityPerUnit,
UnitPrice, UnitsInStock, UnitsOnOrder, ReorderLevel, Discontinued,
(SELECT CategoryName
FROM Categories
WHERE Categories.CategoryID = Products.CategoryID) AS CategoryName,
(SELECT CompanyName
FROM Suppliers
WHERE Suppliers.SupplierID = Products.SupplierID) AS SupplierName,
ROW_NUMBER() OVER (ORDER BY ProductName) AS RowRank
FROM Products
) AS ProductsWithRowNumbers
WHERE RowRank > @startRowIndex AND RowRank <= (@startRowIndex + @maximumRows)
Setelah membuat prosedur tersimpan, luangkan waktu sejenak untuk mengujinya. Klik kanan pada GetProductsPaged
nama prosedur tersimpan di Server Explorer dan pilih opsi Jalankan. Visual Studio kemudian akan meminta parameter input, @startRowIndex
dan @maximumRow
s (lihat Gambar 7). Coba nilai yang berbeda dan periksa hasilnya.
@startRowIndex dan @maximumRows Parameter" />
Gambar 7: Masukkan Nilai untuk @startRowIndex parameter dan @maximumRows
Setelah memilih nilai parameter input ini, jendela Output akan menampilkan hasilnya. Gambar 8 menunjukkan hasil saat meneruskan 10 untuk @startRowIndex
parameter dan @maximumRows
.
Gambar 8: Rekaman yang Akan Muncul di Halaman Kedua Data dikembalikan (Klik untuk melihat gambar ukuran penuh)
Dengan prosedur tersimpan ini dibuat, kami siap untuk membuat ProductsTableAdapter
metode . Buka Himpunan Northwind.xsd
Data Yang Dititik, klik kanan di ProductsTableAdapter
, dan pilih opsi Tambahkan Kueri. Alih-alih membuat kueri menggunakan pernyataan SQL ad-hoc, buat menggunakan prosedur tersimpan yang ada.
Gambar 9: Buat Metode DAL Menggunakan Prosedur Tersimpan yang Ada
Selanjutnya, kami diminta untuk memilih prosedur tersimpan yang akan dipanggil. Pilih prosedur tersimpan GetProductsPaged
dari daftar drop-down.
Gambar 10: Pilih Prosedur Tersimpan GetProductsPaged dari Daftar Drop-Down
Layar berikutnya kemudian menanyakan jenis data apa yang dikembalikan oleh prosedur tersimpan: data tabular, satu nilai, atau tanpa nilai. Karena prosedur tersimpan GetProductsPaged
dapat mengembalikan beberapa rekaman, menunjukkan bahwa ia mengembalikan data tabular.
Gambar 11: Menunjukkan bahwa Prosedur Tersimpan Mengembalikan Data Tabular
Terakhir, tunjukkan nama metode yang ingin Anda buat. Seperti tutorial kami sebelumnya, lanjutkan dan buat metode menggunakan Isi DataTable dan Kembalikan DataTable. Beri nama metode FillPaged
pertama dan yang kedua GetProductsPaged
.
Gambar 12: Beri Nama Metode FillPaged dan GetProductsPaged
Selain membuat metode DAL untuk mengembalikan halaman produk tertentu, kita juga perlu menyediakan fungsionalitas tersebut di BLL. Seperti metode DAL, metode GetProductsPaged BLL harus menerima dua input bilangan bulat untuk menentukan Indeks Baris Mulai dan Baris Maksimum, dan harus mengembalikan hanya rekaman yang termasuk dalam rentang yang ditentukan. Buat metode BLL seperti itu di kelas ProductsBLL yang hanya memanggil ke dalam metode GetProductsPaged DAL, seperti:
[System.ComponentModel.DataObjectMethodAttribute(
System.ComponentModel.DataObjectMethodType.Select, false)]
public Northwind.ProductsDataTable GetProductsPaged(int startRowIndex, int maximumRows)
{
return Adapter.GetProductsPaged(startRowIndex, maximumRows);
}
Anda dapat menggunakan nama apa pun untuk parameter input metode BLL, tetapi, seperti yang akan kita lihat segera, memilih untuk menggunakan startRowIndex
dan maximumRows
menyimpan kami dari sedikit pekerjaan tambahan saat mengonfigurasi ObjectDataSource untuk menggunakan metode ini.
Langkah 4: Mengonfigurasi ObjectDataSource untuk Menggunakan Halaman Kustom
Dengan metode BLL dan DAL untuk mengakses subset rekaman tertentu selesai, kami siap untuk membuat kontrol GridView yang halaman melalui rekaman yang mendasarnya menggunakan halaman kustom. Mulailah dengan membuka EfficientPaging.aspx
halaman di PagingAndSorting
folder, tambahkan GridView ke halaman, dan konfigurasikan untuk menggunakan kontrol ObjectDataSource baru. Dalam tutorial kami sebelumnya, kami sering memiliki ObjectDataSource yang dikonfigurasi untuk menggunakan ProductsBLL
metode kelas s GetProducts
. Namun, kali ini, kita ingin menggunakan metode sebagai gantinya GetProductsPaged
, karena GetProducts
metode mengembalikan semua produk dalam database sedangkan GetProductsPaged
hanya mengembalikan subset rekaman tertentu.
Gambar 13: Konfigurasikan ObjectDataSource untuk Menggunakan Metode GetProductsPaged Kelas ProductsBLL
Karena kita membuat GridView baca-saja, luangkan waktu sejenak untuk mengatur daftar drop-down metode di tab INSERT, UPDATE, dan DELETE ke (None).
Selanjutnya, wizard ObjectDataSource meminta sumber GetProductsPaged
metode dan startRowIndex
maximumRows
nilai parameter input. Parameter input ini sebenarnya akan diatur oleh GridView secara otomatis, jadi cukup biarkan sumber diatur ke Tidak Ada dan klik Selesai.
Gambar 14: Biarkan Sumber Parameter Input sebagai Tidak Ada
Setelah menyelesaikan wizard ObjectDataSource, GridView akan berisi BoundField atau CheckBoxField untuk setiap bidang data produk. Jangan ragu untuk menyesuaikan tampilan GridView sesuai keinginan Anda. Saya telah memilih untuk hanya ProductName
menampilkan , , CategoryName
, SupplierName
QuantityPerUnit
, dan UnitPrice
BoundFields. Selain itu, konfigurasikan GridView untuk mendukung halaman dengan mencentang kotak centang Aktifkan Halaman di tag pintarnya. Setelah perubahan ini, markup deklaratif GridView dan ObjectDataSource akan terlihat mirip dengan yang berikut ini:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataKeyNames="ProductID" DataSourceID="ObjectDataSource1" AllowPaging="True">
<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"
SortExpression="SupplierName" />
<asp:BoundField DataField="QuantityPerUnit" HeaderText="Qty/Unit"
SortExpression="QuantityPerUnit" />
<asp:BoundField DataField="UnitPrice" DataFormatString="{0:c}"
HeaderText="Price" HtmlEncode="False" SortExpression="UnitPrice" />
</Columns>
</asp:GridView>
<asp:ObjectDataSource ID="ObjectDataSource1" runat="server"
OldValuesParameterFormatString="original_{0}" SelectMethod="GetProductsPaged"
TypeName="ProductsBLL">
<SelectParameters>
<asp:Parameter Name="startRowIndex" Type="Int32" />
<asp:Parameter Name="maximumRows" Type="Int32" />
</SelectParameters>
</asp:ObjectDataSource>
Namun, jika Anda mengunjungi halaman melalui browser, GridView bukanlah tempat untuk ditemukan.
Gambar 15: GridView Tidak Ditampilkan
GridView hilang karena ObjectDataSource saat ini menggunakan 0 sebagai nilai untuk GetProductsPaged
startRowIndex
parameter input dan maximumRows
. Oleh karena itu, kueri SQL yang dihasilkan tidak mengembalikan rekaman dan oleh karena itu GridView tidak ditampilkan.
Untuk memperbaikinya, kita perlu mengonfigurasi ObjectDataSource untuk menggunakan halaman kustom. Ini dapat dicapai dalam langkah-langkah berikut:
-
Atur properti ObjectDataSource
EnablePaging
ketrue
ini menunjukkan ke ObjectDataSource bahwa properti tersebut harus diteruskan keSelectMethod
dua parameter tambahan: satu untuk menentukan Indeks Baris Mulai (StartRowIndexParameterName
), dan satu untuk menentukan Baris Maksimum (MaximumRowsParameterName
). -
Atur ObjectDataSource s
StartRowIndexParameterName
danMaximumRowsParameterName
Properti Sesuai denganStartRowIndexParameterName
properti danMaximumRowsParameterName
menunjukkan nama parameter input yangSelectMethod
diteruskan ke untuk tujuan penomoran kustom. Secara default, nama parameter ini adalahstartIndexRow
danmaximumRows
, itulah sebabnya, saat membuatGetProductsPaged
metode di BLL, saya menggunakan nilai-nilai ini untuk parameter input. Jika Anda memilih untuk menggunakan nama parameter yang berbeda untuk metode BLL s seperti dan , misalnya Anda perlu mengatur Properti danGetProductsPaged
ObjectDataSource yangstartIndex
sesuai (seperti startIndex untukmaxRows
dan maxRows untukStartRowIndexParameterName
).MaximumRowsParameterName
StartRowIndexParameterName
MaximumRowsParameterName
-
Atur Properti ObjectDataSource ke
SelectCountMethod
Nama Metode yang Mengembalikan Jumlah Total Rekaman yang Di-Paged Through (TotalNumberOfProducts
) mengingat bahwaProductsBLL
metode kelas sTotalNumberOfProducts
mengembalikan jumlah total rekaman yang di-paged melalui menggunakan metode DAL yang menjalankanSELECT COUNT(*) FROM Products
kueri. Informasi ini diperlukan oleh ObjectDataSource untuk merender antarmuka halaman dengan benar. -
startRowIndex
Hapus elemen danmaximumRows
<asp:Parameter>
dari ObjectDataSource s Declarative Markup saat mengonfigurasi ObjectDataSource melalui wizard, Visual Studio secara otomatis menambahkan dua<asp:Parameter>
elemen untukGetProductsPaged
parameter input metode s. Dengan mengaturEnablePaging
ketrue
, parameter ini akan diteruskan secara otomatis; jika parameter juga muncul dalam sintaks deklaratif, ObjectDataSource akan mencoba meneruskan empat parameter keGetProductsPaged
metode dan dua parameter ke metode .TotalNumberOfProducts
Jika Anda lupa menghapus elemen-elemen ini<asp:Parameter>
, saat mengunjungi halaman melalui browser, Anda akan mendapatkan pesan kesalahan seperti: ObjectDataSource 'ObjectDataSource1' tidak dapat menemukan metode non-generik 'TotalNumberOfProducts' yang memiliki parameter: startRowIndex, maximumRows.
Setelah membuat perubahan ini, sintaks deklaratif ObjectDataSource akan terlihat seperti berikut ini:
<asp:ObjectDataSource ID="ObjectDataSource1" runat="server"
OldValuesParameterFormatString="original_{0}" TypeName="ProductsBLL"
SelectMethod="GetProductsPaged" EnablePaging="True"
SelectCountMethod="TotalNumberOfProducts">
</asp:ObjectDataSource>
Perhatikan bahwa EnablePaging
properti dan SelectCountMethod
telah diatur dan <asp:Parameter>
elemen telah dihapus. Gambar 16 memperlihatkan cuplikan layar jendela Properti setelah perubahan ini dibuat.
Gambar 16: Untuk Menggunakan Halaman Kustom, Konfigurasikan Kontrol ObjectDataSource
Setelah membuat perubahan ini, kunjungi halaman ini melalui browser. Anda akan melihat 10 produk terdaftar, dipesan menurut abjad. Luangkan waktu sejenak untuk menelusuri data satu halaman pada satu waktu. Meskipun tidak ada perbedaan visual dari perspektif pengguna akhir antara halaman default dan halaman kustom, halaman kustom lebih efisien melalui sejumlah besar data karena hanya mengambil rekaman yang perlu ditampilkan untuk halaman tertentu.
Gambar 17: Data, Diurutkan berdasarkan Nama Produk, adalah Halaman Menggunakan Halaman Kustom (Klik untuk melihat gambar ukuran penuh)
Catatan
Dengan halaman kustom, nilai jumlah halaman yang dikembalikan oleh ObjectDataSource SelectCountMethod
disimpan dalam status tampilan GridView. Variabel PageIndex
GridView lainnya , , EditIndex
SelectedIndex
DataKeys
koleksi, dan sebagainya disimpan dalam status kontrol, yang dipertahankan terlepas dari nilai properti GridView.EnableViewState
PageCount
Karena nilai dipertahankan di seluruh postback menggunakan status tampilan, saat menggunakan antarmuka halaman yang menyertakan tautan untuk membawa Anda ke halaman terakhir, sangat penting bahwa status tampilan GridView diaktifkan. (Jika antarmuka halaman Anda tidak menyertakan tautan langsung ke halaman terakhir, maka Anda dapat menonaktifkan status tampilan.)
Mengklik tautan halaman terakhir menyebabkan postback dan menginstruksikan GridView untuk memperbarui propertinya PageIndex
. Jika tautan halaman terakhir diklik, GridView menetapkan propertinya PageIndex
ke nilai yang kurang dari propertinya PageCount
. Dengan status tampilan dinonaktifkan, PageCount
nilai hilang di seluruh postback dan PageIndex
ditetapkan sebagai gantinya nilai bilangan bulat maksimum. Selanjutnya, GridView mencoba menentukan indeks baris awal dengan mengalikan PageSize
properti dan PageCount
. Ini menghasilkan karena produk melebihi ukuran bilangan bulat maksimum yang OverflowException
diizinkan.
Menerapkan Penomoran dan Pengurutan Kustom
Implementasi halaman kustom kami saat ini mengharuskan urutan data di-paged melalui ditentukan secara statis saat membuat prosedur tersimpan GetProductsPaged
. Namun, Anda mungkin telah mencatat bahwa tag pintar GridView berisi kotak centang Aktifkan Pengurutan selain opsi Aktifkan Penomoran Halaman. Sayangnya, menambahkan dukungan pengurutan ke GridView dengan implementasi penomoran halaman kustom kami saat ini hanya akan mengurutkan rekaman pada halaman data yang saat ini dilihat. Misalnya, jika Anda mengonfigurasi GridView untuk juga mendukung penomoran halaman dan kemudian, saat melihat halaman pertama data, mengurutkan menurut nama produk dalam urutan menurut, itu akan membalikkan urutan produk di halaman 1. Seperti yang ditunjukkan Gambar 18, seperti yang ditunjukkan Carnarvon Tigers sebagai produk pertama saat mengurutkan dalam urutan alfabet terbalik, yang mengabaikan 71 produk lain yang mengejar Carnarvon Tigers, menurut abjad; hanya rekaman tersebut pada halaman pertama yang dipertimbangkan dalam pengurutan.
Gambar 18: Hanya Data yang Ditampilkan di Halaman Saat Ini yang Diurutkan (Klik untuk melihat gambar ukuran penuh)
Pengurutan hanya berlaku untuk halaman data saat ini karena pengurutan terjadi setelah data diambil dari metode BLL s GetProductsPaged
, dan metode ini hanya mengembalikan rekaman tersebut untuk halaman tertentu. Untuk menerapkan pengurutan dengan benar, kita perlu meneruskan ekspresi pengurutan ke GetProductsPaged
metode sehingga data dapat diberi peringkat dengan tepat sebelum mengembalikan halaman data tertentu. Kita akan melihat cara mencapai ini dalam tutorial berikutnya.
Menerapkan Halaman Kustom dan Menghapus
Jika Anda mengaktifkan fungsionalitas penghapusan di GridView yang datanya di-page menggunakan teknik penomoran halaman kustom, Anda akan menemukan bahwa saat menghapus rekaman terakhir dari halaman terakhir, GridView menghilang daripada dengan tepat mengurangi GridView.PageIndex
Untuk mereprodusi bug ini, aktifkan penghapusan untuk tutorial yang baru saja kita buat. Buka halaman terakhir (halaman 9), di mana Anda akan melihat satu produk karena kami melakukan paging melalui 81 produk, 10 produk pada satu waktu. Hapus produk ini.
Setelah menghapus produk terakhir, GridView harus secara otomatis masuk ke halaman kedelapan, dan fungsionalitas tersebut dipamerkan dengan halaman default. Namun, dengan penomoran halaman kustom, setelah menghapus produk terakhir itu di halaman terakhir, GridView menghilang dari layar sama sekali. Alasan tepat mengapa ini terjadi sedikit di luar cakupan tutorial ini; lihat Menghapus Rekaman Terakhir di Halaman Terakhir dari GridView dengan Halaman Kustom untuk detail tingkat rendah tentang sumber masalah ini. Singkatnya karena urutan langkah-langkah berikut yang dilakukan oleh GridView saat tombol Hapus diklik:
- Menghapus rekaman
- Dapatkan rekaman yang sesuai untuk ditampilkan untuk yang ditentukan
PageIndex
danPageSize
- Periksa untuk memastikan bahwa
PageIndex
tidak melebihi jumlah halaman data di sumber data; jika ya, secara otomatis mengurangi properti GridView sPageIndex
- Ikat halaman data yang sesuai ke GridView menggunakan rekaman yang diperoleh di Langkah 2
Masalah berasal dari fakta bahwa di Langkah 2 yang PageIndex
digunakan saat mengambil rekaman yang akan ditampilkan masih PageIndex
merupakan halaman terakhir yang catatan tunggalnya baru saja dihapus. Oleh karena itu, di Langkah 2, tidak ada rekaman yang dikembalikan karena halaman terakhir data tersebut tidak lagi berisi rekaman apa pun. Kemudian, di Langkah 3, GridView menyadari bahwa propertinya PageIndex
lebih besar dari jumlah total halaman di sumber data (karena kami telah menghapus rekaman terakhir di halaman terakhir) dan karena itu mengurangi propertinya PageIndex
. Di Langkah 4 GridView mencoba mengikat dirinya sendiri ke data yang diambil di Langkah 2; namun, di Langkah 2 tidak ada rekaman yang dikembalikan, oleh karena itu menghasilkan GridView kosong. Dengan halaman default, masalah ini tidak muncul karena di Langkah 2 semua rekaman diambil dari sumber data.
Untuk memperbaikinya, kami memiliki dua opsi. Yang pertama adalah membuat penanganan aktivitas untuk penanganan aktivitas GridView RowDeleted
yang menentukan berapa banyak rekaman yang ditampilkan di halaman yang baru saja dihapus. Jika hanya ada satu rekaman, maka catatan yang baru saja dihapus pasti yang terakhir dan kita perlu mengurangi GridView s PageIndex
. Tentu saja, kami hanya ingin memperbarui PageIndex
jika operasi penghapusan benar-benar berhasil, yang dapat ditentukan dengan memastikan bahwa e.Exception
properti adalah null
.
Pendekatan ini berfungsi karena memperbarui PageIndex
setelah Langkah 1 tetapi sebelum Langkah 2. Oleh karena itu, pada Langkah 2, kumpulan rekaman yang sesuai dikembalikan. Untuk mencapai hal ini, gunakan kode seperti berikut:
protected void GridView1_RowDeleted(object sender, GridViewDeletedEventArgs e)
{
// If we just deleted the last row in the GridView, decrement the PageIndex
if (e.Exception == null && GridView1.Rows.Count == 1)
// we just deleted the last row
GridView1.PageIndex = Math.Max(0, GridView1.PageIndex - 1);
}
Solusi alternatif adalah membuat penanganan aktivitas untuk peristiwa ObjectDataSource dan RowDeleted
mengatur AffectedRows
properti ke nilai 1. Setelah menghapus rekaman di Langkah 1 (tetapi sebelum mengambil kembali data di Langkah 2), GridView memperbarui propertinya PageIndex
jika satu atau beberapa baris terpengaruh oleh operasi. Namun, AffectedRows
properti tidak diatur oleh ObjectDataSource dan oleh karena itu langkah ini dihilangkan. Salah satu cara untuk menjalankan langkah ini adalah dengan mengatur AffectedRows
properti secara manual jika operasi penghapusan berhasil diselesaikan. Ini dapat dicapai menggunakan kode seperti berikut:
protected void ObjectDataSource1_Deleted(
object sender, ObjectDataSourceStatusEventArgs e)
{
// If we get back a Boolean value from the DeleteProduct method and it's true,
// then we successfully deleted the product. Set AffectedRows to 1
if (e.ReturnValue is bool && ((bool)e.ReturnValue) == true)
e.AffectedRows = 1;
}
Kode untuk kedua penanganan peristiwa ini dapat ditemukan di kelas code-behind contoh EfficientPaging.aspx
.
Membandingkan Performa Halaman Default dan Kustom
Karena halaman kustom hanya mengambil rekaman yang diperlukan, sedangkan halaman default mengembalikan semua rekaman untuk setiap halaman yang ditampilkan, jelas bahwa penomor kustom lebih efisien daripada halaman default. Tetapi berapa banyak yang lebih efisien adalah penomor kustom? Perolehan performa seperti apa yang dapat dilihat dengan berpindah dari penomoran halaman default ke penomoran kustom?
Sayangnya, tidak ada satu ukuran yang sesuai dengan semua jawaban di sini. Perolehan performa tergantung pada sejumlah faktor, dua yang paling menonjol adalah jumlah rekaman yang di-paged through dan beban yang ditempatkan di server database dan saluran komunikasi antara server web dan server database. Untuk tabel kecil hanya dengan beberapa lusin rekaman, perbedaan performa mungkin dapat diabaikan. Untuk tabel besar, dengan ribuan hingga ratusan ribu baris, meskipun, perbedaan performanya akut.
Artikel saya, "Custom Paging in ASP.NET 2.0 with SQL Server 2005," berisi beberapa pengujian performa yang saya jalankan untuk menunjukkan perbedaan performa antara kedua teknik penomoran ini saat penomor melalui tabel database dengan 50.000 rekaman. Dalam pengujian ini saya memeriksa waktu untuk menjalankan kueri di tingkat SQL Server (menggunakan SQL Profiler) dan di halaman ASP.NET menggunakan fitur pelacakan ASP.NET. Perlu diingat bahwa pengujian ini dijalankan pada kotak pengembangan saya dengan satu pengguna aktif, dan oleh karena itu tidak ilmiah dan tidak menipu pola beban situs web biasa. Terlepas dari itu, hasilnya menggambarkan perbedaan relatif dalam waktu eksekusi untuk halaman default dan kustom saat bekerja dengan data dalam jumlah yang cukup besar.
Rata-rata Durasi (dtk) | Membaca | |
---|---|---|
Default Paging SQL Profiler | 1.411 | 383 |
Paging Kustom SQL Profiler | 0,002 | 29 |
Pelacakan ASP.NET Halaman Default | 2.379 | N/A |
Jejak ASP.NET Halaman Kustom | 0.029 | N/A |
Seperti yang Anda lihat, mengambil halaman data tertentu rata-rata memerlukan 354 bacaan lebih sedikit dan diselesaikan dalam waktu yang singkat. Pada halaman ASP.NET, halaman kustom dapat dirender mendekati 1/100th dari waktu yang diperlukan saat menggunakan halaman default.
Ringkasan
Halaman default adalah cinch untuk mengimplementasikan hanya centang pada kotak centang Aktifkan Halaman di tag pintar kontrol Web data tetapi kesederhanaan tersebut dikenakan biaya performa. Dengan halaman default, ketika pengguna meminta halaman data apa pun, semua rekaman dikembalikan, meskipun hanya sebagian kecil dari mereka yang dapat ditampilkan. Untuk memerangi overhead performa ini, ObjectDataSource menawarkan penahapan kustom opsi halaman alternatif.
Meskipun penomor kustom meningkat pada masalah performa halaman default dengan hanya mengambil rekaman yang perlu ditampilkan, lebih terlibat untuk menerapkan penomor kustom. Pertama, kueri harus ditulis yang dengan benar (dan efisien) mengakses subset rekaman tertentu yang diminta. Ini dapat dicapai dengan sejumlah cara; yang kami periksa dalam tutorial ini adalah menggunakan fungsi baru ROW_NUMBER()
SQL Server 2005 untuk memberi peringkat hasil, dan kemudian mengembalikan hanya hasil yang peringkatnya termasuk dalam rentang tertentu. Selain itu, kita perlu menambahkan sarana untuk menentukan jumlah total rekaman yang di-paged through. Setelah membuat metode DAL dan BLL ini, kita juga perlu mengonfigurasi ObjectDataSource sehingga dapat menentukan berapa banyak total rekaman yang di-paged through dan dapat meneruskan nilai Indeks Baris Mulai dan Baris Maksimum dengan benar ke BLL.
Saat menerapkan penomoran kustom memang memerlukan sejumlah langkah dan tidak hampir sesingkat penomoran default, penomoran halaman kustom adalah kebutuhan ketika penomoran melalui data dalam jumlah yang cukup besar. Seperti yang ditunjukkan oleh hasil pemeriksaan, halaman kustom dapat menumpahkan detik dari waktu render halaman ASP.NET dan dapat meringankan beban di server database dengan satu ore lebih banyak pesanan besarnya.
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.