Pengantar Kueri LINQ di C#
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 Dari Operasi Kueri
Semua operasi kueri LINQ terdiri dari tiga tindakan berbeda:
- Dapatkan sumber data.
- Buat kueri.
- Mengeksekusi kueri.
Contoh berikut menunjukkan bagaimana tiga bagian operasi kueri dinyatakan dalam kode sumber. Contoh ini 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 menunjukkan 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 generik IEnumerable<T> . Fakta ini berarti dapat dikueri dengan LINQ. Kueri dijalankan dalam pernyataan foreach
, dan foreach
memerlukan IEnumerable atau IEnumerable<T>. Jenis yang mendukung IEnumerable<T> atau antarmuka turunan seperti IQueryable<T> generik disebut 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 generik IEnumerable<T> , atau antarmuka yang mewarisinya, biasanya IQueryable<T>.
Catatan
Jenis seperti ArrayList yang mendukung antarmuka non-generik IEnumerable juga dapat digunakan sebagai sumber data LINQ. Untuk informasi selengkapnya, lihat Cara kueri ArrayList dengan LINQ.
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 bilangan 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, where
klausul menerapkan filter, dan select
klausa 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#).
Catatan
Kueri juga dapat diekspresikan dengan menggunakan sintaks metode. Untuk informasi selengkapnya, lihat Sintaksis 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 segera mengembalikan hasil skalar. Contoh kueri tersebut adalah Count
, Max
, Average
, dan First
. Metode ini dijalankan tanpa pernyataan eksplisit foreach
karena kueri itu sendiri harus digunakan foreach
untuk mengembalikan hasil. Kueri ini mengembalikan satu nilai, bukan IEnumerable
koleksi. Anda dapat memaksa kueri apa pun untuk segera dijalankan menggunakan Enumerable.ToList metode 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 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 dalam satu objek koleksi.
Ditangguhkan
Eksekusi yang ditangguhkan berarti bahwa operasi tidak dilakukan pada titik dalam kode tempat kueri dideklarasikan. Operasi hanya dilakukan saat 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 adalah 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
ini juga di mana 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 Anda dapat menjalankannya pada interval untuk mengambil hasil yang diperbarui.
Operator kueri yang menggunakan eksekusi yang ditangguhkan juga dapat diklasifikasikan sebagai streaming atau nonstreaming.
Streaming
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 menangguhkan 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.
Non-aliran
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.
Catatan
Jika operator ditandai dalam dua kolom, dua urutan input terlibat dalam operasi, dan setiap urutan dievaluasi secara berbeda. Dalam kasus ini, selalu merupakan urutan pertama dalam daftar parameter yang dievaluasi dengan cara streaming yang ditangguhkan.
LINQ ke objek
"LINQ ke Objek" mengacu pada penggunaan kueri LINQ dengan salah satu IEnumerable atau IEnumerable<T> koleksi secara langsung. Anda dapat menggunakan LINQ untuk mengkueri koleksi yang dapat dijumlahkan, seperti List<T>, , Arrayatau Dictionary<TKey,TValue>. Koleksi dapat ditentukan pengguna atau jenis yang dikembalikan oleh .NET API. 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 tradisional foreach
:
- Mereka lebih ringkas dan mudah dibaca, terutama saat memfilter beberapa kondisi.
- Mereka menyediakan kemampuan pemfilteran, pengurutan, dan pengelompokan yang kuat dengan minimum kode aplikasi.
- Mereka dapat diport 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 di dalam memori
Kueri pada dasarnya adalah sekumpulan instruksi tentang cara mengambil dan menata data. Kueri dijalankan sesekali, karena setiap item berikutnya dalam hasil diminta. Saat Anda menggunakan foreach
untuk mengiterasi hasilnya, item dikembalikan sebagai diakses. 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]);
Lihat juga
Saran dan Komentar
https://aka.ms/ContentUserFeedback.
Segera hadir: Sepanjang tahun 2024 kami akan menghentikan penggunaan GitHub Issues sebagai mekanisme umpan balik untuk konten dan menggantinya dengan sistem umpan balik baru. Untuk mengetahui informasi selengkapnya, lihat:Kirim dan lihat umpan balik untuk