Komponen DataAdapter merupakan komponen yang digunakan sebagai "kurir" untuk commit semua perubahan data baik itu insert, update, delete yang terjadi di DataSet ke tabel yang ada di database. State untuk Insert,Update,Delete (IUD) diambil dari object dataset, karena setiap kali user melakukan perubahan di dataset saat itu juga row state versionnya berubah sesuai dengan aksi IUD.
Secara default di ado.net 1.x data adapter commit semua perubahan yang terjadi di dataset ke database untuk setiap record dengan masing masing statenya. Artinya kalau kita punya 1000 record di dataset dan semua record tsb datanya dirubah untuk masing-masing aksi IUD, maka 1000 kali pula data adapter melakukan round trip ke database untuk commit perubahan-perubahan tsb. Bayangkan kalau recordnya berjumlah puluhan ribu atau lebih dari itu.
Sebenarnya di ado.net 2.0 data adapter sudah menyediakan properti baru untuk menghindari jumlah round trip sebanyak jumlah perubahan record yang terjadi. Properti tsb yaitu UpdateBatchSize. Dengan pengaturan jumlah update batch size maka kita bisa tentukan jumlah record yang akan di update dalam satu waktu. Misalnya kalau kita punya 1000 record di data set dengan semua record tsb mempunyai state row versionnya change maka kita bisa tentukan misalnya dalam sekali round trip itu sekaligus commit perubahan untuk 100 record. Kalau kita bandingkan time processing nya maka perbedaannya bisa 3 x lipat lbh cepat.
Dalam artikel ini saya akan membuat contoh aplikasi sederhana untuk melakukan batch update size yang kita tentukan sendiri, secara default nilai batch update size nya yaitu 1. Asumsikan saya punya tabel TestPerformance dengan tiga kolom dan jumlah recordnya ada 1000. Kemudian tambahkan component SqlDataAdapter dari toolbox. Tools yang saya gunakan yaitu VS 2005, jadi anda harus tambahkan secara manual componentnya ke toolbox.
Untuk melihat proses yang dilakukan oleh data adapter ketika update semua perubahan ke database, kita gunakan event RowUpdating dan RowUpdated. Event RowUpdating terjadi sebelum RowUpdated. Dari event RowUpdated bisa dilihat pengaruh dari perubahan properti Update Batch Size. Untuk lebih jelasnya kita lihat code berikut (anda bisa download source filenya) :
1: Imports System.Data.SqlClient
3: Public Class batchUpdate
5: Private Sub batchUpdate_Load(ByVal sender As System.Object, _
6: ByVal e As System.EventArgs) Handles MyBase.Load
7: SqlDataAdapter1.Fill(DsTestBatchUpdate.TestPerformance)
10: Private Sub SqlDataAdapter1_RowUpdating(ByVal sender As Object, _
11: ByVal e As System.Data.SqlClient.SqlRowUpdatingEventArgs) _
12: Handles SqlDataAdapter1.RowUpdating
13: Console.WriteLine("Row value : " _
14: & e.Command.Parameters.Item(1).Value.ToString & _
18: Private Sub SqlDataAdapter1_RowUpdated(ByVal sender As Object, _
19: ByVal e As System.Data.SqlClient.SqlRowUpdatedEventArgs) _
20: Handles SqlDataAdapter1.RowUpdated
21: Console.WriteLine("Row value : " _
22: & e.Row.Item(1).ToString & " in RowUpdated")
23: Console.WriteLine("Records Affected : " _
24: & e.RecordsAffected.ToString & " in RowUpdated")
27: Private Sub btnUpdate_Click(ByVal sender As System.Object, _
28: ByVal e As System.EventArgs) Handles btnUpdate.Click
29: SqlDataAdapter1.SelectCommand.UpdatedRowSource = _
31: SqlDataAdapter1.UpdateCommand.UpdatedRowSource = _
33: SqlDataAdapter1.InsertCommand.UpdatedRowSource = _
35: SqlDataAdapter1.DeleteCommand.UpdatedRowSource = _
37: SqlDataAdapter1.UpdateBatchSize = 1
39: Dim dtAwal, dtAkhir As Date
40: Dim tsDiff As New TimeSpan
43: For i As Integer = 1 To 1000
44: Dim rowUpdate As DataRow = _
45: DsTestBatchUpdate.TestPerformance.Rows.Find(i)
46: rowUpdate("col2") = i + 1
48: SqlDataAdapter1.Update( _
49: DsTestBatchUpdate.TestPerformance.GetChanges)
51: tsDiff = dtAkhir.Subtract(dtAwal)
52: Console.WriteLine(tsDiff.TotalMilliseconds & ".ms")
54: DataGrid1.DataSource = Nothing
55: DataGrid1.DataSource = DsTestBatchUpdate.TestPerformance
58: Private Sub btnUpdateBatch_Click(ByVal sender As System.Object, _
59: ByVal e As System.EventArgs) Handles btnUpdateBatch.Click
60: SqlDataAdapter1.SelectCommand.UpdatedRowSource = _
62: SqlDataAdapter1.UpdateCommand.UpdatedRowSource = _
64: SqlDataAdapter1.InsertCommand.UpdatedRowSource = _
66: SqlDataAdapter1.DeleteCommand.UpdatedRowSource = _
68: SqlDataAdapter1.UpdateBatchSize = 100
70: Dim dtAwal, dtAkhir As Date
71: Dim tsDiff As New TimeSpan
74: For i As Integer = 1 To 1000
75: Dim rowUpdate As DataRow = _
76: DsTestBatchUpdate.TestPerformance.Rows.Find(i)
77: rowUpdate("col2") = i + 1
79: SqlDataAdapter1.Update( _
80: DsTestBatchUpdate.TestPerformance.GetChanges)
82: tsDiff = dtAkhir.Subtract(dtAwal)
83: Console.WriteLine(tsDiff.TotalMilliseconds & ".ms")
85: DataGrid1.DataSource = Nothing
86: DataGrid1.DataSource = DsTestBatchUpdate.TestPerformance
Simulasi code di atas dilakukan untuk tes performance update data. Tabel yang digunakan sudah berisi 1000 record, dan semua record saya update hanya untuk kolom "col2" saja. Update Batch Size nya saya set ke 100, artinya dala satu kali round trip ke database server akan melakukan updating sekaligus 100 record. Anda bisa lihat perbedaannya di console window, sekaligus melihat proses yang dilakukan oleh data adapter ketika melakukan updating data. Records Affected akan selalu bernilai 1 untuk setiap kali update dengan batch size 1, dan untuk update dengan menggunakan batch size 100 akan bernilai 100.
Berikut cuplikan dari output console window.
Untuk Batch Size = 1 :
Row value : 999 in RowUpdating
Row value : 999 in RowUpdated
Records Affected : 1 in RowUpdated
Row value : 1000 in RowUpdating
Row value : 1000 in RowUpdated
Records Affected : 1 in RowUpdated
Row value : 1001 in RowUpdating
Row value : 1001 in RowUpdated
Records Affected : 1 in RowUpdated
19898,6128.ms
Untuk Batch size 100 :
Row value : 997 in RowUpdating
Row value : 998 in RowUpdating
Row value : 999 in RowUpdating
Row value : 1000 in RowUpdating
Row value : 1001 in RowUpdating
Row value : 1001 in RowUpdated
Records Affected : 100 in RowUpdated
6389,1872.ms