Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
kueri adalah ekspresi yang mengambil data dari sumber data. Sumber data yang berbeda memiliki bahasa kueri asli yang berbeda, misalnya SQL untuk database relasional dan XQuery untuk XML. Pengembang harus mempelajari bahasa kueri baru untuk setiap jenis sumber data atau format data yang harus mereka dukung. LINQ menyederhanakan situasi ini dengan menawarkan model bahasa C# yang konsisten untuk jenis sumber dan format data. Dalam kueri LINQ, Anda selalu bekerja dengan objek C#. Anda menggunakan pola pengkodian dasar yang sama untuk mengkueri dan mengubah data dalam dokumen XML, database SQL, koleksi .NET, dan format lainnya saat penyedia LINQ tersedia.
Tiga Bagian Operasi Kueri
Semua operasi kueri LINQ terdiri dari tiga tindakan yang berbeda:
- Dapatkan sumber data.
- Buat kueri.
- Mengeksekusi kueri.
Contoh berikut menunjukkan bagaimana tiga bagian operasi kueri dinyatakan dalam kode sumber. Contoh menggunakan array bilangan bulat sebagai sumber data untuk kenyamanan; namun, konsep yang sama juga berlaku untuk sumber data lain. Contoh ini disebut di seluruh sisa artikel ini.
// The Three Parts of a LINQ Query:
// 1. Data source.
int[] numbers = [ 0, 1, 2, 3, 4, 5, 6 ];
// 2. Query creation.
// numQuery is an IEnumerable<int>
var numQuery = from num in numbers
where (num % 2) == 0
select num;
// 3. Query execution.
foreach (int num in numQuery)
{
Console.Write("{0,1} ", num);
}
Ilustrasi berikut ini memperlihatkan operasi kueri lengkap. Di LINQ, eksekusi kueri berbeda dari kueri itu sendiri. Dengan kata lain, Anda tidak mengambil data apa pun dengan membuat variabel kueri.
Sumber Data
Sumber data dalam contoh sebelumnya adalah array, yang mendukung antarmuka IEnumerable<T> generik. Fakta ini berarti dapat dikueri dengan LINQ. Kueri dijalankan dalam pernyataan foreach
, dan foreach
memerlukan IEnumerable atau IEnumerable<T>. Jenis yang mengakomodasi IEnumerable<T> atau antarmuka turunan seperti generik IQueryable<T> dikenal sebagai jenis yang dapat dikueri.
Jenis yang dapat dikueri tidak memerlukan modifikasi atau perlakuan khusus untuk berfungsi sebagai sumber data LINQ. Jika data sumber belum dalam memori sebagai jenis yang dapat dikueri, penyedia LINQ harus mewakilinya. Misalnya, LINQ ke XML memuat dokumen XML ke dalam jenis XElement yang dapat dikueri:
// Create a data source from an XML document.
// using System.Xml.Linq;
XElement contacts = XElement.Load(@"c:\myContactList.xml");
Dengan EntityFramework, Anda membuat pemetaan hubungan objek antara kelas C# dan skema database Anda. Anda menulis kueri anda terhadap objek, dan pada run-time EntityFramework menangani komunikasi dengan database. Dalam contoh berikut, Customers
mewakili tabel tertentu dalam database, dan jenis hasil kueri, IQueryable<T>, berasal dari IEnumerable<T>.
Northwnd db = new Northwnd(@"c:\northwnd.mdf");
// Query for customers in London.
IQueryable<Customer> custQuery =
from cust in db.Customers
where cust.City == "London"
select cust;
Untuk informasi selengkapnya tentang cara membuat jenis sumber data tertentu, lihat dokumentasi untuk berbagai penyedia LINQ. Namun, aturan dasarnya sederhana: sumber data LINQ adalah objek apa pun yang mendukung antarmuka IEnumerable<T> generik, atau antarmuka yang mewarisinya, biasanya IQueryable<T>.
Nota
Jenis seperti ArrayList yang mendukung antarmuka IEnumerable non-generik juga dapat digunakan sebagai sumber data LINQ. Untuk informasi selengkapnya, lihat Cara mengkueri ArrayList dengan LINQ (C#).
Kueri
Kueri menentukan informasi apa yang akan diambil dari sumber data atau sumber. Secara opsional, kueri juga menentukan bagaimana informasi tersebut harus diurutkan, dikelompokkan, dan dibentuk sebelum dikembalikan. Kueri disimpan dalam variabel kueri dan diinisialisasi dengan ekspresi kueri. Anda menggunakan sintaks kueri C# untuk menulis kueri.
Kueri dalam contoh sebelumnya mengembalikan semua angka genap dari array bilangan bulat. Ekspresi kueri berisi tiga klausa: from
, where
, dan select
. (Jika Anda terbiasa dengan SQL, Anda melihat bahwa urutan klausul dibalik dari urutan dalam SQL.) Klausa from
menentukan sumber data, klausa where
menerapkan filter, dan klausa select
menentukan jenis elemen yang dikembalikan. Semua klausa kueri dibahas secara rinci di bagian ini. Untuk saat ini, poin pentingnya adalah bahwa dalam LINQ, variabel kueri itu sendiri tidak mengambil tindakan dan tidak mengembalikan data. Ini hanya menyimpan informasi yang diperlukan untuk menghasilkan hasil ketika kueri dijalankan di beberapa titik kemudian. Untuk informasi selengkapnya tentang bagaimana kueri dibuat, lihat Gambaran Umum Operator Kueri Standar (C#) .
Nota
Kueri juga dapat diekspresikan dengan menggunakan sintaks metode. Untuk informasi selengkapnya, lihat sintaks kueri dan Sintaks Metode di LINQ.
Klasifikasi operator kueri standar dengan cara eksekusi
Implementasi LINQ ke Objek dari metode operator kueri standar dijalankan dengan salah satu dari dua cara utama: segera atau ditangguhkan. Operator kueri yang menggunakan eksekusi yang ditangguhkan juga dapat dibagi menjadi dua kategori: streaming dan nonstreaming .
Segera
Eksekusi langsung berarti bahwa sumber data dibaca dan operasi dilakukan sekali. Semua operator kueri standar yang mengembalikan hasil skalar akan dieksekusi secara langsung. Contoh kueri tersebut adalah Count
, Max
, Average
, dan First
. Metode ini dijalankan tanpa pernyataan foreach
eksplisit karena kueri itu sendiri harus menggunakan foreach
untuk mengembalikan hasil. Kueri ini mengembalikan satu nilai saja, bukan koleksi IEnumerable
. Anda dapat memaksa kueri apa pun untuk segera dijalankan menggunakan metode Enumerable.ToList atau Enumerable.ToArray. Eksekusi langsung menyediakan penggunaan kembali hasil kueri, bukan deklarasi kueri. Hasilnya diambil sekali, lalu disimpan untuk digunakan di masa mendatang. Kueri berikut mengembalikan hitungan angka genap dalam array sumber:
var evenNumQuery = from num in numbers
where (num % 2) == 0
select num;
int evenNumCount = evenNumQuery.Count();
Untuk memaksa eksekusi langsung kueri apa pun dan menyimpan cache hasilnya, Anda dapat memanggil metode ToList atau ToArray.
List<int> numQuery2 = (from num in numbers
where (num % 2) == 0
select num).ToList();
// or like this:
// numQuery3 is still an int[]
var numQuery3 = (from num in numbers
where (num % 2) == 0
select num).ToArray();
Anda juga dapat memaksa eksekusi dengan menempatkan perulangan foreach
segera setelah ekspresi kueri. Namun, dengan memanggil ToList
atau ToArray
Anda juga menyimpan semua data dalam satu objek koleksi.
Ditangguhkan
Eksekusi yang ditangguhkan berarti bahwa operasi tidak dilakukan pada titik dalam kode tempat kueri dideklarasikan. Operasi dilakukan hanya ketika variabel kueri dijumlahkan, misalnya dengan menggunakan pernyataan foreach
. Hasil menjalankan kueri bergantung pada konten sumber data saat kueri dijalankan daripada saat kueri ditentukan. Jika variabel kueri dijumlahkan beberapa kali, hasilnya mungkin berbeda setiap saat. Hampir semua operator kueri standar yang jenis pengembaliannya IEnumerable<T> atau IOrderedEnumerable<TElement> dijalankan dengan cara yang ditangguhkan. Eksekusi yang ditangguhkan menyediakan fasilitas penggunaan kembali kueri karena kueri mengambil data yang diperbarui dari sumber data setiap kali hasil kueri diulang. Kode berikut menunjukkan contoh eksekusi yang ditangguhkan:
foreach (int num in numQuery)
{
Console.Write("{0,1} ", num);
}
Pernyataan foreach
juga merupakan tempat hasil kueri diambil. Misalnya, dalam kueri sebelumnya, variabel iterasi num
menyimpan setiap nilai (satu per satu) dalam urutan yang dikembalikan.
Karena variabel kueri itu sendiri tidak pernah menyimpan hasil kueri, Anda dapat menjalankannya berulang kali untuk mengambil data yang diperbarui. Misalnya, aplikasi terpisah mungkin terus memperbarui database. Dalam aplikasi, Anda dapat membuat satu kueri yang mengambil data terbaru, dan menjalankannya secara berkala untuk mengambil hasil yang diperbarui.
Operator kueri yang menggunakan eksekusi yang ditangguhkan juga dapat diklasifikasikan sebagai streaming atau nonstreaming.
Penayangan langsung
Operator streaming tidak perlu membaca semua data sumber sebelum menghasilkan elemen. Pada saat eksekusi, operator streaming melakukan operasinya pada setiap elemen sumber saat dibaca dan menghasilkan elemen jika sesuai. Operator streaming terus membaca elemen sumber hingga elemen hasil dapat diproduksi. Ini berarti bahwa lebih dari satu elemen sumber mungkin dibaca untuk menghasilkan satu elemen hasil.
Bukan Streaming
Operator nonstreaming harus membaca semua data sumber sebelum dapat menghasilkan elemen hasil. Operasi seperti pengurutan atau pengelompokan termasuk dalam kategori ini. Pada saat eksekusi, operator kueri non-aliran membaca semua data sumber, memasukkannya ke dalam struktur data, melakukan operasi, dan menghasilkan elemen yang dihasilkan.
Tabel klasifikasi
Tabel berikut mengklasifikasikan setiap metode operator kueri standar sesuai dengan metode eksekusinya.
Nota
Jika operator ditandai dalam dua kolom, dua urutan input terlibat dalam operasi, dan setiap urutan dievaluasi secara berbeda. Dalam kasus ini, selalu urutan pertama dalam daftar parameter yang dievaluasi secara bertahap dan ditunda.
LINQ to Objects
"LINQ untuk Objek" mengacu pada penggunaan kueri LINQ dengan koleksi IEnumerable atau IEnumerable<T> secara langsung. Anda dapat menggunakan LINQ untuk mengkueri koleksi yang dapat dijumlahkan, seperti List<T>, Array, atau Dictionary<TKey,TValue>. Koleksi dapat ditentukan pengguna atau jenis yang dihasilkan oleh API .NET. Dalam pendekatan LINQ, Anda menulis kode deklaratif yang menjelaskan apa yang ingin Anda ambil. LINQ ke Objek memberikan pengantar yang bagus untuk pemrograman dengan LINQ.
Kueri LINQ menawarkan tiga keuntungan utama daripada perulangan foreach
tradisional:
- Mereka lebih ringkas dan mudah dibaca, terutama saat memfilter beberapa kondisi.
- Mereka menyediakan kemampuan pemfilteran, pemesanan, dan pengelompokan yang kuat dengan minimal kode aplikasi.
- Mereka dapat di-port ke sumber data lain dengan sedikit atau tanpa modifikasi.
Semakin kompleks operasi yang ingin Anda lakukan pada data, semakin banyak manfaat yang Anda wujudkan menggunakan LINQ alih-alih teknik iterasi tradisional.
Menyimpan hasil kueri dalam memori
Kueri pada dasarnya adalah serangkaian instruksi tentang cara mengambil dan menata data. Kueri dijalankan dengan malas, karena setiap item berikutnya dalam hasil diminta. Saat Anda menggunakan foreach
untuk mengiterasi hasilnya, item dikembalikan sesuai urutan akses. Untuk mengevaluasi kueri dan menyimpan hasilnya tanpa menjalankan perulangan foreach
, cukup panggil salah satu metode berikut pada variabel kueri:
Anda harus menetapkan objek koleksi yang dikembalikan ke variabel baru saat menyimpan hasil kueri, seperti yang diperlihatkan dalam contoh berikut:
List<int> numbers = [ 1, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20 ];
IEnumerable<int> queryFactorsOfFour = from num in numbers
where num % 4 == 0
select num;
// Store the results in a new variable
// without executing a foreach loop.
var factorsofFourList = queryFactorsOfFour.ToList();
// Read and write from the newly created list to demonstrate that it holds data.
Console.WriteLine(factorsofFourList[2]);
factorsofFourList[2] = 0;
Console.WriteLine(factorsofFourList[2]);