1) menulis ini di sebuah module :
Public con as new ADODB.Connection
Public rs as new ADODB.Recordset
trus bikin di Sub Main
Public Sub Main()
con.connectionstring = "...."
con.open
rs.activeconnection = con
...
dst...
...
End Sub
2) menulis ini di masing-masing form :
Private con as new ADODB.Connection
Private rs as new ADODB.Recordset
trus di form load :
Private Sub Form_Load()
con.connectionstring = "...."
con.open
rs.activeconnection = con
End Sub
n di form unload :
Private Sub Form_Unload()
rs.close
con.close
set rs = Nothing
set con = Nothing
End Sub
3) Nulis ini di masing-masing form :
Private con as new ADODB.Connection
trus object database dibuka di form load
Private Sub Form_Load()
con.connectionstring = "...."
con.open
End Sub
tapi object recordset baru dideklarasikan di procedure ketika dia dibutuhkan, seperti pas misalnya di CmdSave_Click()
Private Sub CmdSave_Click()
dim rs as new ADODB.Recordset
rs.activeconnection = con
rs.cursorlocation = adUseClient
rs.open "SELECT * FROM blabla"
... code n looping ditulis di sini...
rs.close
set rs = nothing
End Sub
menurut temen2 mana yang lebih efektif antara (1) (2) atau (3) ? ato ada yang punya gaya penulisan sendiri? dari sisi kecepatan gimana ?
oia, gaya create-object pas dibutuhin thox seperti di contoh nomor 3 itu aku baru nemuin. aku belum sempat benchmark... menurut kalian efisien nggak ? walau dari sisi typing mungkin agak banyak ngulang2 ngetik code...
ndox wrote :
----------------------------------------------------------------------------------------------
kalo aku mending pake yang nomer 1 aja. jadi kalo ada kesalahan cuma ngedit satu kali, gak usah berkali-kali. ngirit ngetik...
----------------------------------------------------------------------------------------------
TERNYATA...
cara paling efektif utk deklarasikan ADODB.Connection adalah di
public variabel di modules.
alasannya, klo kmu pasang di masing-masing form, ntar pas njalanin satu aplikasi mu dengan banyak form akan menghasilkan banyak connection ID. artinya, server akan menganggap banyak concurrent connection dalam satu waktu. dan apesnya, kadang ada DBMS yang (klo nggak disetting-setting) yang membatasi max_connection dengan angka yang kecil sekali. u know what I mean laah... ^_^ perwalian stiki beberapa semester yang lalu (bukan yg kemaren) sempet bermasalah dengan max-connection...
nggak percaya?
coba bikin aplikasi dengan 3 form, trus di masing2 form nya deklarasikan
Code: |
Private db as new adodb.connection |
Gimana dengan ADODB.recordset?
cara paling safety utk mempergunakan object ADODB.recordset itu, TERNYATA kmu deklarasikan bukan di module (as public), ato di local form... tapi kmu construct di dalam masing2 procedure (sub/function).
alasannya?
variabel recordset itu merupakan variabel array of record untuk nampung output dari query select. Dia bisa menampung no result set, 1 record, 2, ato jutaan...
nah, klo misalnya kmu taroh di global, bayangkan, kapan variabel tampung itu akan di dispose dari memory? tentu ketika aplikasi kmu terminate... nah pas aplikasi sedang jalan n kmu nge-load recordset (query select) berkali2? tu alokasi memory masih nyangkut tuh sblum kmu exit dari aplikasimu.
ga percaya?
coba kmu bikin satu form, kasih grid (terserah), trus bikin query select yang kira2 menghasilkan output 1000 record. codenya kira2 gini deh :
Code: |
'--- di module diasumsikan dah ada Public db as new adodb.connection '--- n diasumsikan object db udah di open successfully '--- nah skrg di salah satu form nih codenya : Dim rs as new adodb.recordset, sSQL as string, i as integer private sub command1_click() listview1.listitems.clear sSQL = "SELECT * FROM Customers" if rs.state <> adStateClosed then rs.close rs.open sSQL, db if rs.recordcount > 0 then for i = 1 to rs.recordcount call IsiListView(listview1, rs(0),rs(1),rs(2),rs(3),rs(4)) rs.movenext next i end if rs.close end sub |
yaa kira2 gtu lah
klo kmu ngga punya database yang berukuran medium tsb, kmu bs pinjam database northwind bawaan nya access, sql server, ato bawaannya vb. search aja pake F3..
nah trus, sebelum kmu jalankan aplikasi mu itu..., sekalian jalanin juga Task Manager (ctrl+alt+del) n masuk ke tab processes. (tu window slalu always on top kan?). persiapan selesai, trus cb kmu jalanin aplikasi mu itu... tekan tombol Command1. trus liat di Task Manager. Memory Usage utk aplikasi mu nambah kan. trus coba kmu tekan lagi Command1 nya. berkali-kali kalo perlu... apa hasilnya ? mem usage bakal nambah terus n nambah terus....
baguskah itu? tentu tidak...
Oke-oke..., klo gtu, menurut Anda, mana cara yang ideal deh?
1. spt postingan ku di atas, gunakan Public declaration utk masang object ADODB.Connection... - taroh lah di salah satu module...
Code: |
Public db as new ADODB.Connection |
kmu langsung construct dgn ngasih keyword new jg nggak apapa...
2. lakukan peng-open-an connection cukup sekali pada Sub Main atau form load di form utama mu... (tentu stlh ngeset connectionstring yang bener n beberapa atribut macam cursorlocation, locktype, dll)...
Code: |
Sub Main() db.ConnectionString = "Provider=SQLOLEDB.1; blablabla" db.CursorLocation = adUseClient db.open end sub |
3. JANGAN LUPA close connection pada form utama di events unload. klo nggak, DBMS kadang juga nganggap koneksi masih aktif walo aplikasi mu udah ditutup (sebelum DBMS nge-ping smua client-nya apa masih bener2 aktif ato dalam kondisi idle)
Code: |
Sub Form_Unload() if db.state <> adStateClosed then db.close set db = nothing end sub |
code set db = nothing ini adalah cara VB utk destroy object (destructor). tanpa ini, variabel db mu hanya dalam kondisi pause. ngga di free beneran...
4. Utk ngirim query yg ngga mbalikin resultset (INSERT/UPDATE/DELETE), pake object connection. Jangan pake recordset.
Code: |
db.execute("INSERT INTO blablabla..... |
5. utk ngirim query yang mbalikin resultset (SELECT), JUGA PAKAILAH OBJECT CONNECTION...
lho?
nggak salah tha iki ?
bener, bro!
utk ngirim query SELECT, alangkah baiknya klo kmu pake db.execute juga... utk nampungnya baru silakan pake recordset...
contoh codenya gini, biar jelas
Code: |
Private sub Command1_click() dim i as integer dim rs as ADODB.recordset '--> perhatikan, ngga ada 'NEW' d sini sSQL = "SELECT * FROM Customers" set rs = db.execute(sSQL) '--> rs baru di-construct d sini.. if rs.recordcount > 0 then for i = 1 to rs.recordcount 'retreive lah nilai rs ke variabel/grid/etc d sini.... rs.movenext next i end if rs.close '--> tutup object recordset stlh smua nilainya dah ' dikasihkan ke variabel/grid/etc. di state ini, kita dah ' nggak butuh object recordset lagi... set rs = nothing '--> stelah ditutup, buang lah jauh2 dari memory... end sub |
bgitu...
nilai efisiensinya di mana tuh?
object recordset itu dependen banget ama object connection. klo kmu pernah pake gaya rs.open, tentu kmu ga asing dengan syntax model gini :
rs.open sSQL, db
rs.close
ya kan?
apa sih parameter kedua dari rs.open setelah query? active connection...
artinya apa?
walaupun kmu pake rs.open, kmu tetep memanggil ulang properti n state dari object connection mu (db)... dengan syntax kmu spt itu, artinya kmu MENDATANGKAN dua object bersamaan. inisialisasi rs, dan memanggil kembali db... wuih,.. rame banget...
dengan model set rs = db.execute(sSQL), kronologinya bgini :
kmu kirimkan sql query SELECT mu via db.execute. stlh diproses sama DBMS, dia bakal mbalikin hasil query ke object db. yup. pada state ini, object db UDAH BERISI record-record hasil query SELECT mu itu tadi... tapi permasalahannya, record2 tsb belum di-parsing. blum di-array-kan. jadinya ngga bisa dipake utk di assign ke variabel... nah, utk memanfaatkan kumpulan data tsb, maka hasil .execute itu tadi di-assign ke object recordset... dan perintah SET rs = db.execute secara otomatis akan meng-construct object rs itu sendiri dengan resultset.. klo kmu dulu pernah belajar delphi d kampus (aku nggak) kmu mungkin pernah kebingungan pas manfaatin komponen ADOConnection1 yang musti kmu link-link kan dengan dataset segala... nah itu prinsipnya sama... ya kya gtu tadi kronologinya...
TRUS, setelah ini mau apa?
terus terang, saat ini *pas aku rombak* gaya pemrograman ADO ku dengan model teroptimasi kya gtuan, aplikasi gontortoise ku (ni proyek TA ku yang blon kelar2 dari dulu sampe skrg) jadi semakin lightweight. memory usage kecil di sisi client, beban server makin kecil, dan yang paling penting : aplikasiku yang terdiri dari 110 forms n 88 tabel jadi Wuzz Wuzz... (ngikut istilahnya JAY) walaupun aku developnya pake VB yang terkenal LEMOT executables-nya... (bilang pak Setiawan)
dna_psr_09 wrote :
----------------------------------------------------------------------------------------------
Klo aku mendink setiap kali db dibuka dan sudah selesai dipergunakan mending lagsung si tutup.... itung2 biar g buang2 memori.... kasian kalo kita develop di kompi yang lebih rendah spesifikasinya ....
trus jika digunakan untuk client server tidak terlalu memakan trafic yang terlalu banyak ...
so .....
bila
cn.open
...
...
...
Akhirannya ya
cn.close
memang dalam pengetikan coding lebih panjang dan ribet .....
tapi jika kita memikirkan apa dampaknya jika telah di implementasikan di End User gimana Hayoooo .....
Kacian Kan ...
makasih ......
----------------------------------------------------------------------------------------------
dulu aku pernah jg model gtuan. object connection ku-declare-ku-open-n-ku-close di level routines (sub/function). tp akhirnya aku meninggalkan tu model krn NGGA BS KUPAKE utk apply transaction.. krn jika (misalnya) di command1_click aku bikin transaksi (cn.begintrans) n kuproses DML (insert update delete) trus ku tutup transaksi (if err then cn.rollbacktrans else cn.committrans), APA FUNGSINYA TU section transaction ? blass nggak ada
yang kubicarakan di atas itu sbnrnya adalah optimasi penggunaan object recordset. krn klo kmu conn.open n rs.open thox ngga melakukan S.I.U.D., memory yang kepake "hampir" nggak ada n ngga pernah besar. kapan sih memory yang dipake AKAN menjadi besar? sebenarnya cuman pada 1 state : ketika kmu melakukan "SELECT". cuman itu... apalagi select yang mengembalikan 1juta record (hal yang pemborosan n percum tak bergun). di mana array of record itu ditampung nilainya klo nggak di sisi client? menggunakan adUseServer, jg bukan memecahkan masalah, krn traffic jadi padat. utk retreive satu baris record harus "minta" dulu ke server, trus diulangi utk baris-baris selanjutnya sampai 1 juta kali...
operasi Insert Update Delete, yang nanganin kan server. yang mikir jg server. client cuman ngirim satu untaian SQL dan dia cuman nerima 1 nilai dari hasil pengiriman Insert/Update/Delete tsb : "SQLSTATE", dimana klo 0 dia artinya sukses di-insert/update/delete dan klo bukan 0 dia artinya error. misal :
020000 : terjadi duplicate key.
023000 : delete gagal karena ada data udah dipake di child tables.
042000 : kurang tanda petik satu (') tuh di query mu...
nah, berapa besar variabel yang ditampung rs ketika insert/update/delete ?
kecil banget.... 6byte! di sisi client, tuntutan resource yang besar itu HANYA ketika select. (ini termasuk execute stored procedures yang berisi hasil SELECT lho...)
jadi, pendeklarasian object connection di level routines, local form, global modules, hasilnya ngga akan terlalu kentara di sisi client. klo di level routines, efek di server 'hanya' ConnectionID nya cepet sekali meningkat. tp concurrent connectionnya tetep dianggap 0. sama server akan dianggap ngga ada satu pun client yang connect. lha gimana, wong baru akan nerima koneksi klo tombol di klik, n klo udah selesei mroses, koneksi akan diputus....
klo di level local form, baik connection ID maupun concurrent connectionnya akan meningkat, tergantung jumlah form yang kmu load... di mata server, koneksi yang dijalin dgn gaya beginian, akan tampak banyak user yang connect walo cuman 1 kenyataanya...
sedangkan klo di level modules, statistik connection akan lebih nyata... ada 1 user yang connect, ya ke-detect 1 di server...
berbeda jauh dengan pola pendeklarasian object recordset... di mana performa client akan sangat mempengaruhi performa aplikasi... yaa spt yang ku ulas di atas tuh...
CMIIWW,
Rizky Prihanto
http://www.linkar.co.id
http://www.software-arsitek.web.id
0 comments:
Posting Komentar