Using DataLoadOptions for Immediate Loading in LINQ to SQL
mmmmm jelasinnya mulai dari mana ya....
oke kita mulai aja dari konsep Lazy Evaluating di LINQ, seperti yang udah banyak orang tahu kalo sebenernya Query/Ekspresi di LINQ tidak akan dieksekusi sampai kita membutuhkannya. Contohnya dalam kode dibawah ini :
namespace ecek2x
{
class Program
{
static bool tulisHasil(string hasil)
{
Console.WriteLine("Isinya "+hasil);
return true;
}
static void Main(string[] args)
{
string []kumpulan = {"satu","dua","tiga"};
var hasil = from tulisan in kumpulan
where tulisHasil(tulisan)
select tulisan;
}
}
}
okeh coba tebak apa keluaran dari kode diatas?
(ting-tong... kalo geeks pasti diotaknya lagi mencoba mengkompile baris diatas dengan csc :-p)
yak 100 untuk yang jawab gak ngeluarin apa-apa. hal ini karena efek dari Lazy Evaluating tadi, karena toh emang kalo kita lihat di kode diatas variabel hasil emang gak dipake dimana-mana jadi jelas kalau query yang ada pun tidak akan dieksekusi. Namun tentunya hasilnya akan berbeda jika kita menambahkan baris dibawah ini pada akhir prosedur Main :
Console.WriteLine(hasil.First());
maka hasil keluaran dari program diatas adalah :
baris pertama ditulis saat query dijalankan, sedangkan barisan kedua ditulis saat kita menuliskan nilai pertama dari koleksi. Okeh nangkep kan konsep Lazy Evaluating? Jadi intinya kalo kita nulis query, query tersebut gak akan dievaluasi sampai diperlukan. Nah permasalahan ini terkadang menjadi sedikit merepotkan saat berhubungan dengan basis data (LINQ to SQL). contoh kasusnya adalah pada kode dibawah ini :
1: static void Main(string[] args)
2: { 3: DataClasses1DataContext data = new DataClasses1DataContext();
4: data.Log = Console.Out;
5: foreach (var jabatan in data.Roles)
6: { 7: Console.WriteLine(jabatan.RoleName);
8: foreach (var pegawai in jabatan.Employees)
9: Console.WriteLine(pegawai.Name);
10: }
11: }
oh iya kode diatas ditulis setelah membuat sebuah DataContext dengan relasi seperti dibawah ini :
Jadi antara Role dan Employee ada hubungan one to many, sehingga tentunya pada baris ke 5 sebuah Query SQL akan dieksekusi untuk memperoleh data dari table Role, kemudian pada baris ke 8 pun sebuah Query SQL akan dieksekusi untuk memperoleh data dari table Employee untuk Role yang bersesuaian. Sehingga jika ada 5 tuple/row pada tabel maka baris ke 8 akan diulang sebanyak 5 kali, sehingga apa artinya? artinya adalah kita akan melakukan 5 kali query ke basis data. Untuk mengujinya anda bisa coba mengeksekusi kode diatas dan lihat hasilnya, maka di jendela aplikasi kira-kira akan nampak seperti ini :
Tentunya jika ada 1000 row maka akan ada 1000 kali query ke basis data. MMM kayaknya agak buang-buang bandwidth ya? maka dari itu sebagai alternatif kita bisa menggunakan yang namanya DataLoadOptions, dengan menggunakan DataLoadOptions maka kita dapat menspesifikasikan agar data yang berasosiasi juga diambil dari basis data meskipun belum akan digunakan. Untuk contoh diatas misalnya kita ingin mengambil data Employee meskipun kita tidak akan langsung menggunakannya maka tambahkan kode dibawah ini diantara baris ke 3 dan 4 :
DataLoadOptions DLO = new DataLoadOptions();
DLO.LoadWith<Role>(o => o.Employees);
data.LoadOptions = DLO;
Kode diatas akan memerintahkan agar setiap kali ada Query yang menyangkut objek Role maka jangan lupa untuk juga mengambil Employee yang terkait, sehingga perubahan yang terjadi adalah jika sebelumnya setiap menuliskan nama Employee akan dilakukan query ke basis data sekarang hal tersebut tidak akan dilakukan lagi karena data Employee telah ikut diambil saat kita mengambil data Role. Maka kalau kita jalankan kode yang telah dimodifikasi efeknya adalah :
terlihat kalau tidak lagi dilakukan Query ke basis data ketika kita akan menuliskan nama dari Employee dan kalau anda jeli maka pada saat awal dilakukan query yang juga mengambil data Employee dari basis data. Okeh segitu aja dulu bagi ilmunya, gua mo bikin perbaikan sidang dulu, tanggal 13 February 2008 ini deadline.
cheers.....