Memanggil stored procedure MS SQL dari DAL merupakan hal yang biasa dan banyak sekali dijumpai contoh-contohnya. Namun memanggil stored procedure Sybase cukup agak tricky, setidaknya untuk saya pribadi. Pada awalnya saya berfikir memanggil Stored Procedure pasti polanya sama aja untuk database manapun tapi ternyata tidak. Untuk lebih meresapi apa yang telah saya tulis diatas mari disimak potongan source code di bawah ini:
public void ADD(GAC_OFFICES_BO obj)
{
DbCommand cmd = DB.GetStoredProcCommand("{call SP_GAC_OFFICES_ADD(?, ?, ?, ?, ?, ?, ?, ?)}");
DB.AddInParameter(cmd,
"OFFICE_CODE", DbType.String, obj.OFFICE_CODE);DB.AddInParameter(cmd, "OFFICE_NAME", DbType.String, obj.OFFICE_NAME);
DB.AddInParameter(cmd,
"MODE", DbType.String, obj.MODE);DB.AddInParameter(cmd, "ACTIVE_FLAG", DbType.String, obj.ACTIVE_FLAG);
DB.AddInParameter(cmd,
"CREATED_BY", DbType.String, obj.CREATED_BY);DB.AddInParameter(cmd, "CREATED_DATE", DbType.DateTime, obj.CREATED_DATE);
DB.AddInParameter(cmd,
"UPDATED_BY", DbType.String, obj.UPDATED_BY);DB.AddInParameter(cmd, "UPDATED_DATE", DbType.DateTime, obj.UPDATED_DATE);
DB.ExecuteNonQuery(cmd);
}
Diatas adalah sebuah method yang berguna untuk menambahkan data ke database. Method tersebut memanggil sebuah stored procedure yang bernama SP_GAC_OFFICES_ADD dengan inputan parameter sebanyak delapan buah. Dapat dilihat, Stored Procedure dipanggil dengan cara menggunakan kurung kurawal, kata "call", nama Stored Procedure dan kemudian simbol tanda tanya. Banyak simbol tanda tanya yang digunakan adalah sejumlah parameter dari stored procedure yang bersangkutan.
Cara menambahkan parameter hanya memiliki sedikit perbedaan yaitu tidak digunakannya simbol "a keong (@)" didepan nama parameter.
buat saya, perbedaan ini telah membuat saya sedikit "headache" ketika membuat POC dan sebagai kenang-kenangan maka saya tuliskan di blog ini :-)
note:
Objek DB adalah objek dari kelas
Microsoft.Practices.EnterpriseLibrary.Data.Database
like the title said, "IGW816: Exceptional Experience"
different people from different country working together for one goal :-)
Stewart Herbert
Eva Navratil Freitag
Ilias Avramidis
Kanagarajan
Ashan B. Silva
thank you for everything
good bye "Spicy Spirit of 6" smile.... :-)
Meneruskan artikel sebelumnya tentang custom membership provider, maka kali ini saya akan coba tuliskan sekilas tentang custom role provider. Implementasi dari custom role provider kurang lebih sama dengan implementasi custom membership provider yaitu melalui tiga langkah mudah yaitu: membuat kelas turunan, meng-override method dan terakhir adalah konfigurasi web.config.
1. Membuat kelas turunan
untuk custom role provider ini, kelas yang akan dibuat diturunkan dari kelas RoleProvider.
namespace Provider
{
public class SybaseRoleProvider : RoleProvider
{
}
}
note: penamaan kelas turunan adalah bebas, saya menggunakan "Sybase" karena client menginginkan saya meng-custom role and membership dengan menggunakan Sybase sebagai beck-end. Awalan "Sybase" akan mengingatkan bahwa beck-end yang hendak digunakan adalah Sybase.
2. Meng-override method GetRolesForUser
Method GetRolesForUser akan mengambil roles dari seorang user dengan menggunakan informasi username yang diinputkan. Isi dari method ini adalah akses ke database yang akan mengembalikan nama-nama roles yang dimiliki oleh seorang user berdasarkan username nya.
public override string[] GetRolesForUser(string username)
{
}
keluaran dari method GetRolesForUser adalah array string yaitu nama-nama roles yang dimilki oleh user tertentu.
3. Konfigurasi web.config
langkah terakhir adalah konfigurasi web.config
<roleManager enabled="true" defaultProvider="Provider.SybaseRoleProvider">
<
providers><clear/>
<
add applicationName="/" connectionStringName="ConnectionString" name="Provider.SybaseRoleProvider" type="Provider.SybaseRoleProvider"/></providers>
</
roleManager>
and finish :-)
HTH
Custom MembershipProvider diperlukan ketika aplikasi yang dikembangkan akan tidak menggunakan default provider untuk membership. Default provider yang digunakan adalah SqlMembershipProvider. Adapun pembuatan custom MembershipProvider sangat sederhana yaitu cukup meng-override method ValidateUser dari kelas MembershipProvider. Berikut adalah tiga langkah mudah pembuatan custom MembershipProvider:
1. Membuat sebuah kelas yang diturunkan dari kelas MembershipProvider
Membuat custom MembershipProvider berarti membuat sebuah kelas baru yang diturunkan dari kelas MembershipProvider.
namespace Provider
{
public
class MyCustomMembershipProvider : MembershipProvider{ public override bool ValidateUser(string username, string password)
{
// code untuk validasi user goes here
}
}
}
2. Meng-override method ValidateUser
Setelah kerangka kelas dibuat, langkah berikutnya adalah mengisikan code untuk mengoverride method ValidateUser. note: method lainnya dapat dioverride sesuai kebutuhan sehingga tidak harus semua method dari kelas MembershipProvider di override.
public override bool ValidateUser(string username, string password)
{
USERS_BO user = new USERS_BO();
user =
USERS_MGR.GETUSERSBYNAME(username);if (user != null)
{
if (user.PASSWORD != null)
{
string dbPassword = user.PASSWORD;
bool status = dbPassword.Equals(password);return status;
}
else
{
return false;
}
}
else
{
return false;
}
}
isi code diatas sangat sederhana, yaitu membandingkan password yang dimasukan oleh user di login screen dengan password yang sudah disimpan didalam database untuk user tertentu (yang diindikasikan melalui username).
3. Konfigurasi di web.config
and the last step nya adalah melakukan sedikit konfigurasi di web.config. Konfigurasi dilakukan agar aplikasi kita mengenali dan kemudian menggunakan custom MembershipProvider yang telah dibuat. adapun konfigurasi yang dilakukan adalah cukup menambahkan code seperti berikut:
<membership defaultProvider="Provider.MyCustomMembershipProvider">
<
providers><clear/>
<
add name="Provider.MyCustomMembershipProvider" type="Provider.MyCustomMembershipProvider" applicationName="/" connectionStringName="ConnectionString"/></providers>
</
membership>
Dapat dilihat, konfigurasi yang dilakukan adalah "memperkenalkan" custom MembershipProvider pada aplikasi dengan cara menuliskan nama kelas si custom MembershipProvider yang diawali dengan nama namespacenya.
done :-)
Dalam day to day programming saya banyak menggunakan function javascript alert. Misalnya untuk memberitahu user bahwa proses yang dia kerjakan berhasil atau tidak.
try
{
//code untuk menyimpan data ke database
ClientScript.RegisterStartupScript(typeof(string), "Success", "alert('Data saved succesfully.');", true);
}
catch (Exception)
{
ClientScript.RegisterStartupScript(typeof(string), "Fail", "alert('Data not saved.');", true);
}
Namun masalah muncul ketika saya menggunakan Updatepanel, yaitu function alert tidak bekerja sebagaimana mestinya. Beruntung saya menemukan blognya Scott Klueppel dan mendapatkan solusi dari blog tersebut.
Solusinya adalah menggantikan ClientScript.RegisterStartupScript dengan ScriptManager.RegisterStartupScript jadi:
ClientScript.RegisterStartupScript(typeof(string), "Success", "alert('Data saved succesfully.');", true);
diganti dengan
ScriptManager.RegisterStartupScript(this.updatePanel, typeof(string), "Success", "alert('Data saved succesfully.');", true);
note: updatePanel adalah nama UpdatePanel yang digunakan.
thanks scott!!!
Pengalaman skin dive pertama saya adalah di pantai anyer bersama temen-temen dari SIAWARE8. Skin dive nya tidak terlalu menarik namun anak-anak SIAWARE8 nya sangat asik. Ok, mudah-mudahan skin dive di pantai "Layered Application" bisa lebih menarik ;-)
BO (Bussines Object)
Pada layer BO berkumpul banyak kelas yang menggambarkan sebuah record dari sebuah tabel. Kelasnya hanya berisi code get dan set yang akan mengisi dan mengambil nilai sebuah properties. Propertiesnya merupakan kolom-kolom dari tabel yang hendak di petakan menjadi BO. Misalkan ada tabel seperti dibawah:

maka kelas BO yang bersesuaian dengan tabel diatas adalah seperti berikut:

dapat dilihat bahwa kelas BO hanya berisi get dan set.
DAL (Data Access Layer)
Lapisan DAL berisi kelas-kelas yang mengandung code-code yang mengakses database secara langsung. Disinilah tempat yang paling baik untuk memanggil stored procedure yang ada di database. Pada DAL, saya membuat sebuah kelas yang akan dijadikan induk bagi semua kelas yang berada di DAL. si induk ini hanya bertugas membuat object database dengan menggunakan informasi connection string dari web.config. Why? agar proses pembuatan object database hanya dilakukan di satu tempat, jadi ketika ada perubahan informasi connection string kita hanya akan melakukan perubahan di satu tempat saja, tidak di semua kelas DAL. Berikut adalah contoh kelas induk di DAL yang saya beri nama kelas DAL:

dan berikut adalah kelas di DAL yang diturunkan dari kelas induk diatas:

Dapat dilihat bahwa kelas yang terdapat di lapisan BO digunakan disini. Method GETALLEMPLOYEE memanggil stored procedure DEMO_EMP_GET_ALL(). Dan karena yang akan dikembalikan oleh SP tersebut adalah banyak record, maka digunakanlah List dari BO untuk menangkap kembalian dari SP.
BLL (Bussiness Logic Layer)
Kelas-kelas di BLL akan memanggil method-method yang terdapat di DAL. berikut adalah contohnya:

BLL hanya memanggil method dari DAL. Kemudian, si BLL akan dipanggil oleh UI, berikut adalah contoh pemanggilan BLL oleh UI:

note: saya membuat BO, DAL dan BLL menggunakan C#, namun UI menggunakan VB.NET. .NET canggih kan :-)
untuk memperdalam, silahkan download DotNetNuke dan install pada mesin kesayangan Anda. setelah itu selamat "menelanjangi" DNN dan selamat terkagum-kagum dengan arsitekturnya :D
that just my two cents.
Melihat code yang campur aduk adalah hal yang memusingkan apalagi code tersebut dibuat oleh programmer lain. Salah satu teknik yang saya lihat cukup berguna adalah sebuah teknik yang disebut layered application. Dari namanya saja sudah dapat diterka yaitu aplikasi yang berlapis, apa siy maxutnya? oke please bear on me.
Secara kasar dapat kita katakan bahwa aplikasi yang dibuat oleh para developer pada intinya adalah menyimpan data ke database dan kemudian menampilkan data yang telah di simpan tersebut. Pada jaman "jahiliyah" dulu biasanya saya menaruh semua code pada sebuah file kelas dan biasanya merupakan code behind dari file aspx. Code yang berhubungan dengan UI saya taro di sana, code yang berhubungan dengan akses data ke database saya taro juga disana, code yang berhubungan dengan bisnis proses saya taro juga disana, pokoknya saya campurkan semuanya. Aplikasi siy bisa berjalan lancar, namun ketika satu minggu kemudian saya lihat kembali itu source code, mendadak kepala ini jadi puyeng.
Beruntung pada masa awal karir profesional, saya bergabung dengan sekelompok developer hebat, arsitek hebat dan projek yang hebat pula. Disitu saya melihat code di pisah-pisahkan berdasarkan fungsi yang diemban oleh si code. Code yang berhubungan dengan data akses dibuat menjadi sebuah projek tersendiri. Code yang berhubungan dengan Bisnis Proses dibuat menjadi sebuah projek sendiri dan tentu saja UI nya juga dibuat menjadi sebuah projek tersendiri. Memang, it a little bit slow at first, tapi kemudian progressnya saya lihat bagus sekali. Let stop talking and let see picture ( i love picture):

Gambar diatas adalah gambar yang tergambar di kepala saya setelah melihat sorce code sebuah solution. Database digunakan untuk menyimpan data aktual. UI digunakan untuk "melihat" dan "memanipulasi" data yang telah tersimpan. DAL adalah sebuah project (yang terdiri dari banyak kelas) yang khusus memiliki fungsi akses data yaitu akses langsung ke database. Disinilah berkumpul code-code yang memanggil stored procedure di database. BLL adalah sebuah project (yang terdiri dari banyak kelas juga) yang khusus mengakses semua code yang berada di DAL. Code-code yang berada di BLL akan digunakan secara langsung oleh UI. BO adalah sebuah project yang terdiri dari kelas-kelas yang menggambarkan sebuah record dari suatu tabel. Ketika DAL memanggil SP yang mengembalikan banyak record maka kelas yang terdapat di BO akan dibungkus menjadi sebuah List. Cukup rapih bukan?
Kelas-kelas yang terdapat dalam project BO dapat digunakan pada setiap lapis (layer). Jadi, DAL dapat menggunakan BO, BLL dapat menggunakan BO dan UI dapat menggunakan BO. Berikut adalah gambar dari sebuah solution explorer yang telah menerapkan konsep layered application:

dan dibawah adalah gambar yang memperlihatkan code dari BLL:

dari code diatas dapat dilihat bahwa kelas BO dibungkus menjadi sebuah List, yang tentu saja dapat dipahami karena method GETALLEMPLOYEE akan mengembalikan banyak record. Dari code diatas juga dapat dilihat bagaimana BLL menggunakan method yang terdapat dalam DAL yang diakses dengan sangat mudah, cukup dengan di-"dot" :-)
Saya mendevelop aplikasi web dengan menggunakan VS2005. Setelah sebelumnya semuanya berjalan lancar, tiba-tiba pas mau nge-debug terjadi sesuatu yang cukup memusingkan. Breakpoint yang saya set di source code tidak "nyangkut-nyangkut". Cukup sangat memusingkan karena de-bugging adalah hal yang sangat principal. setelah googling di internet saya menemukan tips yang kemudian menjadi solusi atas permasalahan saya (banyak banget developer arround the world yang mengalami masalah ini dan banyak banget tips yang disuguhkan).
berikut adalah tips yang menjadi solusi untuk saya:
"reset Internet Explorer"
caranya:
1. Pilih Tools kemudian Internet Options
2. Kemudian pilih tab Advanced dan klik tombol Reset
3. That's it!!!
Beberapa hari ini, saya merasakan jakarta memiliki suhu yang sudah sangat familiar sekali dengan tubuh saya. Yep, beberapa hari ini saya merasakan suhu di jakarta seperti suhu di bandung, sejuk. Mungkin karena seringnya suasana berawan yang diikuti angin kencang dan bahkan diselingi dengan hujan pada siang harinya. Sambil "nyengir" keheranan saya mengatakan pada diri saya sendiri, koq jakarta jadi dingin gini ya, jadi pengen beli "surabi imut" di gerlong, hehehe.
Namun tidak lama setelah itu, sensor trauma dalam diri saya menyala. Saya tiba-tiba teringat pengalaman seru yang cenderung menyebalkan yang pernah saya alami. Beberapa bulan setelah saya menginjakan kaki dijakarta, i've got my first banjir. Hehehe yep, saat itu adalah suatu pagi ketika saya berangkat dari kostan menuju lokasi projek pertama saya di Astra Internasional didaerah sunter jakarta utara. Sepanjang jalan Yos Sudarso saya mendorong motor berplat D kesayangan saya. Si sayang cuman keliatan Stang nya doang, sedangkan dari jok sampai kebawah bener2 nggak keliatan ditelen air banjir, buset!!!. Dengan fikiran yang butek sebutek air banjir, saya mendorong motor saya dari carefour cempaka mas sampai AI sunter. Gila.. saya dorong motor dari jam 7 pagi dan sampai ke AI sekitar jam 11, saya ingat hari itu adalah hari jum'at.
Selepas menikmati sensor traumatic, kemudian insting Geo Science saya bangkit mirip sebuah Event yang pasrah di perdaya oleh sang Handler perkasa. Sang Handler cuman berisi statement Response.Redirect yang mengalihkan perhatian saya pada Prof. The Houw Liong dan metode ANFIS nya. Pak The (dibaca te bukan deu), begitu biasa kami memanggilnya, adalah salah seorang Professor nyentrik kebanggaan orang fisika. Sedangkan ANFIS adalah kependekan dari "Adaptive Neuro-Fuzzy Inference Systems" yang merupakan sebuah metode yang mengkombinasikan artificial neural network dan Fuzzy. Metode ini dikembangkan oleh J.S Roger Jang yang digunakan untuk mengolah informasi "rancu". Saya nggak ada masalah dengan hal2 yang "rancu" yang nggak "precise" ini, karena setahun bermain dengan teori fractal dan non-euclidean geometry menjadikan saya sadar bahwa alam ini "tidak teratur secara teratur". I think its enough with SoftComputing thing and kembali ke laptop, hehehe.
Pak The menggunakan ANFIS untuk memprediksi periode banjir besar dengan menggunakan deret waktu bilangan bintik matahari. Oke, penjelasan ilmiah cukup bisa menenangkan lahir batin plus informasi tambahan tentang tahun-tahun berapa saja yang termasuk periode banjir, namun... hehehe this is where the fun begin, untuk kasus banjir di wilayah indonesia, hujan is not the defining factor, dan saya yakin temen2 dari teknik sipil dan temen2 dari planologi memiliki argumen yang lebih cantik mengenai hal ini. Jangankan diguyur oleh hujan akibat aktifitas matahari maksimum, diguyur oleh hujan normal saja sudah cukup banyak menimbulkan genangan di mana-mana. Saya sempat "nyengir" ketika berjalan di sekitar Sudirman akibat pengamatan sotoy saya tentang sistem drainage disekitar jalan dan berakhir pada bayangan sekelompok kura-kura ninja yang sedang asik berlatih sambil makan pizza di sebuah kota di luar sana. that's just my imagination.
Pengembaraan berakhir ketika ada MSN dari belanda, "Hi Ismail" hehehehe begitulah message yang muncul and i'm going back to work. silent voice in my heart: "Indonesia is a great and a cool country, letak geografis Indonesia mengharuskan Indonesia memiliki sistem tata kota yang super canggih dan sistem Early Warning Systems (EWS) yang outstanding, what can you do for that ismail huh, what can you do ismail" :-)
selamat datang 2008
selamat tinggal 2007
life is cool huh :-)
Kira-kira begitulah teriakan AJAX ketika dia lagi kebingungan.


Asynchronous (independent) postbacks melalui jalur "life cycle" yang sama dengan regular pages. Perbedaan terjadi pada saat rendering. Dengan AJAX, rendering terjadi secara partial yaitu rendering terjadi pada bagian yang berada di UpdatePanel saja. Proses render menggunakan "special format" yang hanya dimengerti oleh JavaScript di client.
Ketika ada interfensi terhadap data yang dikirimkan ke si client (yang dalam bentuk special format itu), maka format yang special tersebut akan rusak dan pada akhirnya si client jadi tidak memahami lagi format data yang diterimanya itu. Proses parsing gagal terjadi dan kemudian munculah error diatas.
Saya menemukan error diatas ketika mengerjakan sebuah module DNN yang terpaksa harus sedikit mengganggu "response stream" sehingga melakukan rendering di luar phase rendering. Luckily, saya menemukan blognya Eilon Lipton yang membahas hal ini dengan sangat bagus sekali. Saya mengikuti sarannya untuk tidak melakukan asynchronous postbacks, tapi melakukan regular postback dengan cara menambahkan PostBackTrigger.
note: DNN akan mendukung AJAX automatically jika ascx yang didaftarkan via module definitions di cek bagian supports partial rendering nya. Dengan men-cek checkbox tersebut maka DNN akan menambahkan scriptmanager dan updatepanel pada module secara "ajaib". saran Eilon yang nomor dua lah yang saya pilih karena alasan yang diungkapkan pada nomor satunya.
Sebuah aplikasi web akan terdiri dari banyak halaman (file .aspx) dalam usaha menampilkan content dari aplikasi web tersebut. Berbeda dengan aplikasi web pada umumnya, sebuah aplikasi web DotNetNuke hanya menggunakan sebuah file aspx saja yaitu file Default.aspx. Ilusi yang terjadi ketika user mengklik menu item untuk berpindah dari satu halaman ke halaman yang lainnya di peroleh dengan suatu teknik yang disebut “Dynamic Page Rendering”. Jadi, meskipun hanya menggunakan sebuah file aspx saja (yaitu Default.aspx), user “seolah-olah” menjelajahi banyak halaman.
Sebuah halaman aplikasi web DotNetNuke terdiri dari satu atau lebih module. Module adalah sebuah entitas fungsional terkecil. Contoh-contoh module adalah: Module Hit counter, Module users online, Module User Account, Module Google Adsense, Module Blog, Module FAQ, Module Feedback, Module e-Commerce dan banyak lagi. Module bisa sangat sederhana dan bisa sangat rumit, bisa sesederhana module hit counter dan bisa serumit module e-Commerce. Truth to be told, module terdiri dari kumpulan file-file ascx yang memanfaatkan API dari DotNetNuke dan ASP.NET. (note: inilah alasan mengapa DotNetNuke disebut sebagai sebuah Framework bukan sekedar CMS biasa).
Informasi tentang sebuah halaman beserta module-module apa saja yang terkandung di halaman tersebut disimpan dalam database. Halaman yang satu dengan halaman yang lain bersifat unik. Sebuah halaman dapat diidentifikasi dan dibedakan dari halaman yang lainnya dengan menggunakan apa yang disebut “tabid” (dibaca: tab-id). Sebuah nilai tabid yang unik hanya untuk sebuah halaman saja. Sama seperti halaman, module-module dalam aplikasi web DotNetNuke diidentifikasi dan dibedakan dengan sebuah nilai unik yang disebut ModuleID. Module-module mana saja yang mengisi sebuah halaman dapat ditentukan dengan mudah karena didalam database, ModuleId dengan tabid memiliki relationship.

Ketika seorang user mengklik sebuah menu item untuk menuju pada sebuah halaman tertentu, proses behind the scene nya adalah:
- File Default.aspx di panggil
- Sebuah querystring dengan parameter tabid dilewatkan ke web server
- Nilai querystring tabid kemudian digunakan oleh DNN database server untuk memperoleh informasi moduleid yang ber-relasi dengan tabid tersebut.
- Informasi yang diperoleh DNN database server kemudian diberikan kepada web server
- Web server kemudian menggunakan informasi yang diperoleh dari database server untuk merender file Default.aspx (dynamic page rendering)
- User memperoleh halaman yang diinginkan.


Note: Fitur HumanFriendlyURL yang dibawa oleh DNN 4.7 akan lebih merampingkan tampilan URL aplikasi DotNetNuke. Tabid tidak akan lagi terlihat di address bar dari web browser. Informasi lebih lanjut mengenai HumanFriendlyURL dapat di lihat di blognya sang master DotNetNuke, Agung Riyadi.
Menghafal page life cycle bukan merupakan hal yang mudah (setidaknya untuk saya), tapi beruntung ada artikel ini di codeproject yang mencoba memberikan ide bagaimana cara menghapal page life cycle melalui singkatan. Di artikel tersebut, page life cycle disingkat menjadi SILVER-U.

S: Start
I: Initialize
L: Load
V: Validate
E: Event handling
R: Render
U: Unload
Start
Pada fase ini properties page di set. Aksi meng-set Master page untuk user tertentu untuk meng-achieve “user preference settings” dapat dilakukan pada fase ini dengan cara menambahkan code pada handler dari event PreInit.
Initialize
Pada fase ini, ID untuk control sudah di generate, namun properties yang lainnya belum ada. Initialization dapat di override dengan menggunakan method OnInit.
Load
Fase ini sangat tepat digunakan untuk memanggil functions dan perform some logic. Pada fase ini control diisi data-data yang diperoleh dari view state dan control state (thanks to LoadViewState event dan LoadPostData event). Penambahan code dapat juga dilakukan pada handler dari event OnLoad karena pada fase inilah event tersebut dibangkitkan.
Validate
Control di validasi dan terdapat event Validate yang dapat digunakan.
Event Handling
Event handling server control terjadi pada fase ini. Modifikasi final dapat dilakukan dengan memanfaatkan event OnPreRender. Event SaveViewState digunakan untuk menyimpan value pada view state object. (note: event SaveViewState hanya akan menyimpan value pada view state object bukan pada control, karena modifikasi final pada control terjadi pada event OnPreRender).
Render
Method Render menggunakan objek HtmlTextWriter sebagai parameter. Objek tersebut digunakan untuk meng-output HTML untuk ditampilkan di browser. Pada fase ini, page akan “memerintahkan” semua object yang dimilikinya untuk me-render dirinya sendiri menjadi HTML.
Unload
Setelah HTML di render, semua object di-disposed yang diawali dengan pemanggilan event OnUnload pada setiap control di page yang kemudian pemanggilan event OnUnload pada page itu sendiri. Pada fase ini aman untuk men-dispose semua object yang masih tersisa (eg: open database connections dan open file streams).
Paging di ASP.NET 2.0 GridView adalah sangat mudah karena ASP.NET 2.0 menyediakan default paging untuk GridView. Dengan men-check checkbox Enable Paging via Smart Tag atau menge-set properties AllowPaging dari si GridView menjadi True maka GridView sudah bisa support paging tanpa code sedikitpun. Namun demikian, kemudahan tersebut harus dibayar oleh berkurangnya performance aplikasi. Hal tersebut dikarenakan, default paging akan selalu mengambil semua records meskipun yang ditampilkan hanya sebagiannya saja (note: GridView akan menyeleksi data yang ditampilkan namun data source tatap akan selalu meretrieve seluruh records). Untuk scenario data yang sangat sedikit, default paging ini akan sangat membantu sekali tapi untuk scenario data yang berjumlah banyak akan berdampak pada turunnya performance. (note: scenario data banyak ini bisa “diakali” dengan teknik “caching data” dengan menggunakan SqlDataSource).
Untuk scenario data yang berjumlah sangat besar diperlukan teknik lain untuk paging ini. Artikel ini akan mencoba untuk sedikit mengulas custom paging dengan menggunakan ObjectDataSource. Ide dari custom paging ini adalah teknik “selective data retrieving” yang dilakukan oleh stored procedure. Dengan menggunakan fitur ROW_NUMBER() dari MS SQL Server 2005, pembuatan stored procedure yang dikhususkan untuk custom paging akan menjadi sangat mudah. Berikut adalah dua hal yang harus dilakukan untuk meng-achieve custom paging:
- Mengkonfigurasi ObjectDataSource agar support custom paging
- Membuat stored procedure yang mendukung custom paging
Konfigurasi ObjectDataSource
ObjectDataSource adalah sebuah data source control yang didesain untuk mengakses data via sebuah object. Si object menyediakan data bisa dari web service, database dan juga bisa dari file XML. ObjectDataSource adalah penghubung antara web control (eg: GridView) dengan data yang disediakan oleh si object. Object yang hendak di bind ke ObjectDataSource harus memiliki method yang dapat mengakses stored procedure yang diperlukan untuk custom paging. Cara paling mudah untuk membuat object semacam ini adalah melalui pembuatan DataSet. TableAdapter dari DataSet memberikan kemudahan untuk mengkases stored procedure yang mana konfigurasinya dapat dilakukan secara visual. Karena konsep layering sudah umum digunakan dalam pembuatan aplikasi web, maka dalam artikel ini akan digunakan sebuah object dari Business Logic Layer (BLL) untuk di-bind ke ObjectDataSource.
Berikut adalah konfigurasi ObjectDataSource yang harus dilakukan untuk mendukung custom paging:
- Set properties TypeName pada object yang hendak di-bind dengan ObjectDataSource.
- Set properties EnablePaging menjadi True.
- Set properties SelectMethod pada method yang mengakses stored procedure untuk custom paging. Note: method tersebut harus berada pada object yang hendak di-bind dengan ObjectDataSource.
- Isikan nama parameter dari method yang digunakan pada properties SelectMethod ke properties StartRowIndexParameterName. Nama parameter yang diisikan adalah parameter yang menginput starting index. Note: stored procedure yang akan dibuat memiliki dua buah parameter, pertama: parameter untuk menginput starting index dan kedua: parameter untuk menginput jumlah records maksimal yang hendak di tampilkan.
- Isikan nama parameter yang menginput jumlah maksimal records yang hendak di paging ke properties MaximumRowsParameterName.
- Set properties SelectCountMethod pada method yang mengakses stored procedure untuk menghitung jumlah total records.
Berikut adalah conteh kode aspx dari ObjectDataSource:
<asp:ObjectDataSource
ID="ObjectDataSource1"
runat="server"
EnablePaging="True"
StartRowIndexParameterName="startRowIndex"
MaximumRowsParameterName="maximumRows"
SelectCountMethod="GetJumlahRecordTerritories"
SelectMethod="GetTerritoriesForPaging"
TypeName="TerritoriesManager">
</asp:ObjectDataSource>
TerritoriesManager adalah nama object BLL yang hendak di-bind ke ObjectDataSource. SelectMethod yang digunakan adalah GetTerritoriesForPaging yang menggunakan dua buah parameter input. SelectCountMethod yang dipilih adalah GetJumlahRecordTerritories. Parameter input yang digunakan pada SelectMethod adalah startRowIndex dan maximumRows.
Membuat stored procedure
Stored procedure yang dibuat sebanyak dua buah. Yaitu GetTerritoriesForPaging dan GetJumlahRecordTerritories. Kedua buah stored procedure tersebut harus dapat diakses via object yang hendak di-bind dengan ObjectDataSource. Berikut adalah script stored procedure GetTerritoriesForPaging:
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
go
CREATE PROCEDURE [dbo].[GetTerritoriesForPaging]
(
@startRowIndex int,
@maximumRows int
)
AS
SET @startRowIndex = @startRowIndex + 1
SELECT
TerritoryID,
TerritoryDescription,
RegionID
FROM
(SELECT
TerritoryID,
TerritoryDescription,
RegionID,
ROW_NUMBER() OVER(ORDER BY TerritoryID) as RowNum
FROM
Territories
) as TerrInfo
WHERE
RowNum
BETWEEN @startRowIndex
AND (@startRowIndex + @maximumRows) - 1
Dapat dilihat bahwa ROW_NUMBER() akan menomori semua record yang telah diurutkan berdasarkan TerritoryID. Meskipun TerritoryID tidak berurutan, ROW_NUMBER() akan memberikan nomor yang berurutan pada setiap record. Nomor record yang berurutan disimpan pada kolom RowNum yang kemudian akan disaring menggunakan klausa WHERE.
Stored procedure yang kedua yang harus dibuat adalah stored procedure untuk menghitung jumlah total record.
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
go
CREATE PROCEDURE [dbo].[GetJumlahRecordTerritories]
AS
SELECT COUNT(*)
FROM Territories
Jumlah total records diperlukan untuk pembuatan index paging.

Pada bagian satu telah dibahas pola fikir dari konsep Event Handling ini. Pembahasan dimulai dari penjelasan apa itu event dan diakhiri dengan bagaimana cara mengkonsumsi event tersebut. Karena delegate memiliki peranan yang sangat penting bagi event handling maka pada bagian satu dibahas juga sedikit mengenai delegate. Proses pelemparan event oleh event sender dan proses penggunaan event oleh event receiver telah digambarkan juga pada bagian satu secara sederhana dan menggunakan contoh.
Sekarang, pada bagian dua ini, akan dicoba untuk memaparkan sedikit konsep yang masih tertinggal di bagian satu. Konsep yang tertinggal itu adalah mengenai transfer data melalui event. Yes, event dapat membawa data.
Sedikit Teori
.NET telah menyediakan sebuah event delegate standar untuk digunakan yaitu delegate System.EventHandler. Delegate System.EventHandler ini menggunakan kelas System.EventArgs sebagai parameter yang akan membawa data.
delegate void EventHandler(object sender, EventArgs e);
Karena data yang dilewatkan melalui event ini akan sangat bervariasi maka pada kasus khusus kelas System.EventArgs tidak digunakan secara langsung. Tetapi, digunakan sebagai base class untuk sebuah kelas sesungguhnya yang sangat merepresentasikan data yang dibutuhkan. Sehingga dapat dikatakan, untuk kebutuhan data tertentu maka diperlukan sebuah kelas custom yang diturunkan langsung dari kelas System.EventArgs.
Jadi pada bab ini ada dua hal yang akan dilakukan:
- Membuat kelas custom yang merupakan kelas turunan dari kelas System.EventArgs. Kelas custom inilah yang akan membawa data via si event. Konvensi penamaan dari kelas custom ini adalah NamaEventEventArgs. Kelas custom ini kemudian akan digunakan menjadi parameter untuk event delegate.
- Membuat event delegate baru dengan menggunakan kelas dari point satu. Event delegate yang baru ini akan mengikuti konvensi penamaan sebagai berikut: “NamaEventEventHandler”. Event delegate yang baru ini akan digunakan untuk membuat sebuah event sehingga event yang terbuat dapat membawa data dari objek kelas custom dari point satu diatas.
Let’s See How “Rubber Meets the Road”
Contoh yang digunakan masih sama seperti contoh pada bagian satu. Method Rename akan memanggil method yang akan membangkitkan event. Hal yang baru dari bagian dua ini adalah definisi kelas custom yang akan diturunkan langsung dari kelas System.EventArgs. Kelas baru tersebut akan menampung data Boolean yang akan mengindikasikan persetujuan untuk merubah nama atau tidak. Sebuah event akan dideklarasikan dengan menggunakan event delegate yang baru.
Berikut adalah kerangka source code yang akan dikembangkan:
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
public partial class EventHandlerWithData : System.Web.UI.Page
{
}
// custom EventArgs class
public class GantiNamaEventArgs : EventArgs
{
}
// custom event delegate
public delegate void GantiNamaEventHandler(object sender, GantiNamaEventArgs e);
public class KelasSumber
{
}
Kelas GantiNamaEventArgs
Kelas ini diturunkan dari kelas System.EventArgs. Kelas GantiNamaEventArgs merupakan kelas custom yang akan membawa data tertentu. Pada contoh kali ini, kelas ini hanya akan membawa data Boolean yang akan mengindikasikan tentang persetujuan perubahan nama.
// custom EventArgs class
public class GantiNamaEventArgs : EventArgs
{
private bool _approved = true;
// constructor
public GantiNamaEventArgs(bool approved)
{
_approved = approved;
}
public bool Approved
{
get
{
return _approved;
}
}
}
Delegate GantiNamaEventHandler
Agar event yang dibuat dapat membawa data yang dibungkus oleh kelas GantiNamaEventArgs, m