LINQ Tuts. Part 2: Dengan contoh yang dapat di download)

LINQ dan Extension Method

Katakanlah kita mempunyai sebuah objek array dengan nama arrayNama. Setelah mendeklarasikan objek array ini, untuk menggunakannya kembali biasanya kita mengetik nama dari array tersebut dan selanjutnya menekan tanda "titik" untuk mengaktfkan intellisense. Pada saat kita menggunakan intellisense akan muncul method-method yang disarankan oleh intellisense.

Gambar 1. Extension Method.

 

Gambar di atas adalah gambar dari sebuah intellisense yang menampilkan method-method yang disarankan untuk operasi apa yang akan kita lakukan. Extension method terindikasi dari tanda panah biru yang menghadap ke bawah. Method Select, Single, Sum, Max dan lain-lain berkaitan erat dengan operasi-operasi menggunakan LINQ dan merupakan operator standar dari operasi LINQ.

 

Contoh penggunaan LINQ dalam kehidupan sehari-hari seorang programmer

Pada tulisan ini, saya ingin menampilkan contoh yang biasa saya gunakan untuk memecahkan berbagai persoalan dengan menggunakan LINQ. Mungkin bagi para pembaca masih terlalu basic, hehehe. Prinsipnya begini, selagi semuanya masih bisa dijadikan object maka bisa diselesaikan dengan menggunakan LINQ. Untuk tahap pertama, saya ingin mencoba melakukan berbagai macam operasi string dengan menggunakan LINQ.

Permasalahan:

Ada sebuah kalimat di dalam textbox. Kalimat itu terdiri atas beberapa kata dan karakter.

  1. Hitunglah jumlah kata, karakter, huruf dan angka dalam kalimat tersebut.
  2. Hitung kata apa yang paling sering muncul, dan berapa jumlahnya
  3. Hitung huruf apa yang paling sering muncul dan berapa jumlahnya
  4. Buatkan sebuah textbox yang gunanya untuk memfilter kata. Nanti pada textbox ini, kita masukkan sebuah kata. Dari kata yang kita masukkan ini, hitunglah dalam kalimat ada berapa kata yang cocok dengan kata yang dimasukkan ini.
  5. Buatlah sebuah datagridview, kemudian lakukan pengelompokan kata dan jumlah kemunculannya, tampilkan di datagridview.
  6. Hampir sama dengan nomor 5, tetapi yang dikelompokkan adalah huruf dan jumlah kemunculannya
  7. Hampir sama dengan nomor 5, tetapi yang dikelompokkan adalah angka dan jumlah kemunculannya.

Jika saya memposisikan sebagai mahasiswa yang baru belajar bahasa program, untuk soal nomor 1 mungkin mudah. Nomor 2 mayanlah. Nomor 3 udah mulai berkeringat. Nomor 4 sudah mulai gelisah, liat kiri kanan. Nomor 5, 6, 7 mungkin dah pingsan di kelas.

Tetapi hal-hal di atas ternyata sangat mudah diselesaikan dengan operasi LINQ.

Untuk soal nomor 1 bagian hitung kata, penyelesaian ala LINQ nya adalah:

Dim kata As String() = txtKalimat.Text.Split(New Char() {}, StringSplitOptions.RemoveEmptyEntries)
Dim jumlahKata As Integer = kata.Count
MessageBox.Show(jumlahKata)

Sebenarnya sintax di atas belum masuk query syntax dari LINQ, tapi menggunakan extension method Count, yang mana method ini masi erat hubungannya dalam operasi-operasi LINQ

Untuk soal nomor 1 bagian hitung char, penyelesaian ala LINQ nya sbb:

Dim jumlahChar As Integer = (From chars In txtKalimat.Text Select chars).Count

Masih termasuk mudahlah ini. Padanannya juga dengan fungsi Length, kita dapat menghitung panjang char dari suatu kalimat.

Untuk soal nomor 1 bagian hitung jumlah huruf (bukan spasi, angka, tanda titik dll), penyelesaian LINQ nya sbb:

Dim huruf = (From kalimat In txtKalimat.Text Where Char.IsLetter(kalimat) Select kalimat).Count

Disini sudah mulai dirasakan enaknya penggunaan LINQ. Kalau cara ga pake LINQ, dalam bayangan saya mungkin melakukan pengulangan terhadap kalimat, terus di cek apakah huruf atau bukan (biasanya sih pengecekan dengan ASCII), jika termasuk huruf, maka tambahkan ke result integer, jika tidak maka tidak ada penambahan. Hmmm.. dah kebayang juga sih ribetnya. Itu masih di case hitung huruf. Kalau hitung angka gimana? ASCII nya ganti lagi. Dengan LINQ, kita hanya modifikasi baris di atas, di bagian Char.IsLetter(kalimat) tinggal kita ganti ke Char.IsDigit(kalimat). Selesai. 🙂

Lanjut ke soal Nomor 2. Kalau cara yang paling awam untuk soal nomor dua adalah, lakukan split, kemudian lakukan looping insert ke database. Selanjutnya lakukan query dengan group by kata. Letakkan di view, lakukan query kedua dengan sintax sql : "select top 1 from namaView order by jumlah descenting". Sudah bisa dibayangkan berapa baris sintax nya…

Dengan LINQ, konsep yang sama bisa diselesaikan seperti berikut:

Dim kata As String() = txtKalimat.Text.Split(New Char(){}, StringSplitOptions.RemoveEmptyEntries)
Dim maxKata = From k In kata Group By k Into Group Select textKata = k, jumlah = Group.Count Order By jumlah Descending
Dim kataTerbanyak = maxKata.First

MessageBox.Show("Kata yang paling banyak muncul adalah: " & kataTerbanyak.textKata & vbCrLf & "Sebanyak :" & kataTerbanyak.jumlah)

Baris pertama melakukan split dari kalimat. Baris kedua lumayan ribet lah.

  1. From k In Kata => masih LINQ biasa
  2. Group By k => melakukan penggrupan seperti pada query di sql
  3. Into Group => biasanya dilakukan ke alias group, atau ke group itu sendiri.
  4. Select textKata = k, jumlah = Group.Count => melakukan select yang terbaru akibat dari penggrupan yang dilakukan sebelumnya.
  5. Order By jumlah Descending => melakukan urutan data dari jumlah yang paling besar ke paling kecil. So coba pembaca bayangkan, sekarang data kita sudah terurut berdasarkan jumlah dari yang besar ke kecil. Sekarang tinggal ambil yang terbesar dari kumpulan data itu, yang berada di urutan pertama. Untuk mengambilnya gunakan method First. Selanjutnya kita tinggal mengakses nama "field", textKata dan jumlah.
  6. Ribet? iya sih, tapi menyelesaikan problem ini dengan 3 atau 4 baris, saya anggap "sesuatu" . :p

Untuk soal nomor 3, dengan LINQ kita selesaikan aja dengan method Where seperti berikut:

Dim hurufLINQ = From l In txtKalimat.Text Where Char.IsLetter(l) Group l By key = l Into Group Select huruf = key, jumlah = Group.Count
Dim hurufTerbanyak = hurufLINQ.First
MessageBox.Show("Huruf yang paling banyak muncul adalah: " & hurufTerbanyak.huruf & vbCrLf & "Sebanyak :" & hurufTerbanyak.jumlah)

Untuk soal nomor 4, prinsipnya sama dengan nomor 3. Hanya menggunakan Where saja, tidak melakukan grouping dulu.

Dim kata As String() = txtKalimat.Text.Split(New Char() {}, StringSplitOptions.RemoveEmptyEntries)
Dim jumlahKata As Integer = (From intkata In kata Where intkata = txtFilter.Text Select intkata).Count
MessageBox.Show(jumlahKata)

Mungkin setelah sampai di problem nomor 4, para pembaca sudah mulai mengerti mengenai pembicaraan kita tentang LINQ ini. Biar ndak bertele-tele dengan pembicaraan saya ini, maka saya sertakan file yang telah saya buat dengan menggunakan visual studio 2008. Termasuk di dalamnya ada pemecahan masalah untuk nomor 5, 6 dan 7. Tambahan lainnya adalah operasi-operasi pada angka. Mencari nilai tertinggi, terendah, jumlah, bilangan ganjil, bilangan genap dll.

Silahkan download dimari: http://www.mediafire.com/?mvejcnic3iobjuq

Dimanakah anda sekarang ini?

1. Sudah mengenal Extension Method

2. Memecahkan masalah pada operasional string dengan menggunakan LINQ to Object.

Harapan saya, sesudah membaca artikel ini, para pembaca mulai tertarik untuk menyelesaikan masalah dengan bantuan LINQ. Pokoknya apapun yang bisa dijadikan object, bisa di selesaikan dengan LINQ.

 

LINQ Tuts. Part 1: Dasar-Dasar LINQ

arsitekturLINQ

Sekilas LINQ

LINQ merupakan singkatan dari Language Integrated Query.  LINQ merupakan fitur yang sudah ada sejak .Net Framework v3.5. Yang menjadi pertanyaan sekarang adalah, mengapa kita mempelajari LINQ? Bagaimana pula nasib T-SQL yang sudah kita mengerti bahkan sudah hafal luar kepala?

Sekarang ini, perkembangan teknologi sudah semakin maju, banyak pilihan manipulasi data, bahkan dalam sebuah aplikasi, kita harus memahami sintaks sql untuk memanipulasi database, selain itu kita juga harus mengerti xpath, xquery dan xslt jika berurusan dengan XML. Lain lagi dengan programmer yang bekerja dengan datasets, yang harus mengerti berbagai macam class dan property yang bisa digunakan dari ADO.Net.

Hal-hal tersebutlah yang menjadi dasar dan dorongan untuk menjadikan LINQ sebagai satu kesatuan cara pandang dari pengelolaan data… (ampun, bahasanya ribet)

 

Arsitektur LINQ

Berikut ini adalah diagram dari arsitektur LINQ :

 

Dari gambar di atas, dapat dilihat bahwa LINQ dapat mengakses data source dari berbagai sumber:

  1. LINQ to Objects, sumber data dari IENumerable dan IQueryable generic collection.
  2. LINQ to XML, sumber data dari IENumerable Xelement.
  3. LINQ to Dataset, sumber data dari IENumerable Datarow
  4. LINQ to SQL, sumber data dari IENumerable dan IQueryable dan setiap object yang kita tentukan sendiri sebagai represent data dari SQL tabel.

Mari kita bahas satu per satu…

LINQ to Objects

LINQ to Objects dapat mengakses sumber data IENumerable atau IEQueryable secara langsung tanpa membutuhkan LINQ Provider atau API, seperti pada LINQ to SQL atau LINQ to XML. IENumerable atau IEQueryable collection contohnya adalah array string (string()), array integer (integer()), bisa pula generic List.

Langsung aja masuk ke contoh, misalkan anda memiliki kumpulan data dalam sebuah array. Untuk mengakses data pada array, biasanya kita melakukan looping pada array tersebut dan melakukan iterasi pada setiap data yang sesuai dengan kriteria, misalnya nama sebuah makanan yang dimulai dengan huruf tertentu.

 

Di bawah ini adalah script vb.net untuk menampilkan data pada listbox dengan menggunakan pengulangan:

Dim makanan() As String = {"Pecel", "Gudeg", "Kerupuk", "Pizza", "Pisang Goreng", "Gadogado", "Sari roti", "Oreo", "Martabak"}
ListBox1.Items.Clear()
For Each strMakanan In makanan
    If strMakanan.StartsWith("P") Then
        ListBox1.Items.Add(strMakanan)
    End If
Next

Pada sepenggal script vb di atas, kebiasaan kita untuk mengakses data terhadap array dengan menggunakan looping. Kita juga melakukan iterasi dan melakukan pengkondisian terhadap nama makanan yang dimulai dari huruf "P" dengan menggunakan fungsi StartsWith.

Nah, dengan LINQ to Objects, kita modifikasi script di atas menjadi :

        Dim makanan() As String = {"Pecel", "Gudeg", "Kerupuk", "Pizza", "Pisang Goreng", "Gadogado", "Sari roti", "Oreo", "Martabak"}        
        ListBox1.Items.Clear()
        Dim linqMakanan As IEnumerable(Of String) = From namaMakanan In makanan Select namaMakanan _
                                                    Where namaMakanan.StartsWith("P")

        For Each strMakanan In linqMakanan
            ListBox1.Items.Add(strMakanan)
        Next

Sekarang mari kita bangingkan antara kedua script di atas. Script yang pertama menyelesaikan masalah dengan melakukan pengkondisian "If". Dan script yang kedua, menyelesaikan masalah dengan cara query (melakukan filtering "Where"). 

Selanjutnya pada bagian looping for each. Paradigma orang awam: "Sama aja tuh, di atas pake for each, yang bawah juga pake for each". Kalau saya bilang tidak sama, for each yang di atas melakukan iterasi terhadap semua elemen yang berada di dalam array makanan(). sementara for each yang di bawah, hanya melakukan iterasi pada data yang sudah terfilter. Sudah bisa dilihat kan bedanya? Dan tentunya sudah dapat dibayangkan, yang mana yang lebih cepat dalam hal mengakses dan mempresentasikan data.

Nah, sekarang kita melakukan pembahasan terhadap sintax LINQ. Mungkin para pembaca yang sudah mengerti dan paham luar dalam sintaks SQL, menyadari kalau penulisan sintax LINQ mirip-mirip dengan sintax SQL.  Perbedaan yang mendasar adalah operator sequens yang berbalik. Dimana SQL sintax memiliki faham SELECT – FROM – WHERE, sementara LINQ memiliki faham FROM – WHERE – SELECT (hmm, jadi kebayang format DM – MD di pelajaran bahasa). Kenapa pada LINQ sintax terbalik dengan SQL sintax? Jawabannya adalah agar supaya (kayak bahasa pak Jendral) intellisense dapat mengetahui sumber data mana yang akan kita gunakan. Sehingga intellisense dapat memberikan dan menyediakan saran/suggest untuk "where" clause dan "select" clause.

Pada sepenggal script LINQ di atas, yang dihasilkan adalah IENumerable String. Bisa saja kita melakukannya secara implisit seperti ini:

        Dim linqMakanan = From namaMakanan In makanan Select namaMakanan _
                          Where namaMakanan.StartsWith("P")

Pada script di atas, compiler akan secara otomatis menentukan tipe yang cocok, tidak masalah mau secara implisit atau sudah ditentukan.

LINQ akan lebih berguna lagi jika kita ingin memfilter data yang lebih kompleks. Pada contoh di atas, kita memfilter nama makanan yang huruf depannya adalah "P". Pada LINQ, kita bisa melakukan filtering yang lain, misalnya nama makanan yang huruf depan adalah "P" dan huruf akhir adalah "l".

        Dim linqMakanan = From namaMakanan In makanan Select namaMakanan _
                          Where namaMakanan.StartsWith("P") And namaMakanan.EndsWith("l")

dari sintax LINQ di atas akan menghasilkan "Pecel".

 

Query Syntax lawan Method Syntax

Syntax LINQ yang telah kita bahas di atas termasuk tipe Query Syntax. Query Syntax bersifat declarative manner.

        Dim angka() As Integer = {10, 12, 52, 32, 41, 75, 8, 88, 98, 72, 55, 21, 66, 33, 44, 41}
        Dim angkaGanjil As IEnumerable(Of Integer) = From bilGanjil In angka _
                                                     Select bilGanjil _
                                                     Where (bilGanjil Mod 2 = 1)

        For Each ganjil In angkaGanjil
            ListBox1.Items.Add(ganjil)
        Next

Sedangkan method syntax ditulis dengan menggunakan pemanggilan method (seperti where dan select):

        Dim angka() As Integer = {10, 12, 52, 32, 41, 75, 8, 88, 98, 72, 55, 21, 66, 33, 44, 41}
        Dim angkaGanjil As IEnumerable(Of Integer) = angka.Where(Function(n) n Mod 2 = 1)
        For Each ganjil In angkaGanjil
            ListBox1.Items.Add(ganjil)
        Next

Fungsi dari kedua script di atas sebenarnya sama, yaitu memfilter data dan mengembalikan angka ganjil dari kumpulan data. Pada script kedua, ada bagian seperti:angka.Where(Function(n) n Mod 2 = 1).

Function(n) ini disebut Lambda Expression. Lambda Expression adalah sebuah fungsi yang hanya menerima sebuah parameter input, terdiri dari 1 statement dan mengembalikan sebuah nilai (accpets single parameter input, contains single statement, returns a value)

Syntax tipe mana yang akan anda gunakan? Berdasarkan rumor yang beredar, di bawah ini adalah informasi perbandingan keduanya(berdasarkan buku C# 2008 Programmers Reference karangan Wei-Meng Lee):

1. Dari sisi performa, tidak ada perbedaan di antara kedua tipe syntax tersebut.

2. Query Syntax lebih mudah dibaca, jadi gunakanlah selagi memungkinkan.

3. Gunakanlah method syntax, jika tidak ada fungsi yang ekivalen di query syntax. Misalnya kita ingin menghitung berapa jumlah bilangan ganjil pada case di atas, kita menggunakan fungsi count.

Dim count As Integer = angka.Where(Function(n) n Mod 2 = 1).Count

 

Dimanakah anda sekarang?

Setelah membaca artikel saya yang ndak seberapa ini, seharusnya pembaca sudah mengerti mengenai:

– LINQ, singkatan dari apa, motivasi desain nya apa.

– Arsitektur LINQ yang meliputi LINQ to Objects, LINQ to XML, LINQ to Datasets dan LINQ to SQL

– Sintax LINQ dengan format FROM – WHERE – SELECT, yang berbanding terbalik dengan sintax SQL.

– Pemahaman dasar LINQ to Objects, pengaksesan data secara langsung terhadap IENumerable dan IQueryable.

– Bisa membedakan Query Syntax dan Method Syntax

– Sedikit mengetahui tentang Lambda

Selanjutnya kita akan membahas mengenai LINQ Extension Method dan LINQ to SQL. Tunggu tanggal mainnya.