Dasar-dasar ekspresi kueri
Artikel ini memperkenalkan konsep dasar yang terkait dengan ekspresi kueri di C#.
Apa itu kueri dan apa fungsinya?
Kueri adalah sekumpulan instruksi yang menjelaskan data apa yang akan diambil dari sumber data (atau sumber) tertentu dan bentuk serta organisasi apa yang harus dimiliki data yang dikembalikan. Kueri berbeda dari hasil yang dihasilkannya.
Umumnya, data sumber diatur secara logis sebagai urutan elemen dari jenis yang sama. Misalnya, tabel database SQL berisi urutan baris. Dalam file XML, ada "urutan" elemen XML (meskipun elemen XML diatur secara hierarkis dalam struktur pohon). Koleksi dalam memori berisi urutan objek.
Dari sudut pandang aplikasi, jenis dan struktur tertentu dari data sumber asli tidak penting. Aplikasi selalu melihat data sumber sebagai kumpulan IEnumerable<T> atau IQueryable<T>. Misalnya, di LINQ ke XML, data sumber dibuat terlihat sebagai IEnumerable
<XElement>.
Mengingat urutan sumber ini, kueri mungkin melakukan salah satu dari tiga hal:
Mengambil subset elemen untuk menghasilkan urutan baru tanpa mengubah elemen individual. Kueri kemudian dapat mengurutkan atau mengelompokkan urutan yang dikembalikan dengan berbagai cara, seperti yang ditunjukkan dalam contoh berikut (asumsikan
scores
adalahint[]
):IEnumerable<int> highScoresQuery = from score in scores where score > 80 orderby score descending select score;
Mengambil urutan elemen seperti pada contoh sebelumnya tetapi mengubahnya menjadi jenis objek baru. Misalnya, kueri mungkin hanya mengambil nama keluarga dari rekaman pelanggan tertentu di sumber data. Atau mungkin mengambil rekaman lengkap lalu menggunakannya untuk membangun jenis objek dalam memori lain atau bahkan data XML sebelum menghasilkan urutan hasil akhir. Contoh berikut menunjukkan proyeksi dari
int
kestring
. Perhatikan jenis baruhighScoresQuery
.IEnumerable<string> highScoresQuery2 = from score in scores where score > 80 orderby score descending select $"The score is {score}";
Mengambil nilai singleton tentang data sumber, seperti:
Jumlah elemen yang cocok dengan kondisi tertentu.
Elemen yang memiliki nilai terbesar atau paling sedikit.
Elemen pertama yang cocok dengan kondisi, atau jumlah nilai tertentu dalam sekumpulan elemen tertentu. Misalnya, kueri berikut mengembalikan jumlah skor yang lebih besar dari 80 dari array bilangan bulat
scores
:var highScoreCount = ( from score in scores where score > 80 select score ).Count();
Dalam contoh sebelumnya, perhatikan penggunaan tanda kurung di sekitar ekspresi kueri sebelum panggilan ke metode Enumerable.Count. Anda juga dapat menggunakan variabel baru untuk menyimpan hasil konkret.
IEnumerable<int> highScoresQuery3 = from score in scores where score > 80 select score; var scoreCount = highScoresQuery3.Count();
Dalam contoh sebelumnya, kueri dijalankan dalam panggilan ke Count
, karena Count
harus mengulangi hasil untuk menentukan jumlah elemen yang dikembalikan oleh highScoresQuery
.
Apa itu ekspresi kueri?
Ekspresi kueri adalah kueri yang dinyatakan dalam sintaks kueri. Ekspresi kueri adalah konstruksi bahasa kelas satu. Ini sama seperti ekspresi lain dan dapat digunakan dalam konteks apa pun di mana ekspresi C# valid. Ekspresi kueri terdiri dari sekumpulan klausul yang ditulis dalam sintaks deklaratif yang mirip dengan SQL atau XQuery. Setiap klausa pada gilirannya berisi satu atau beberapa ekspresi C#, dan ekspresi ini mungkin berupa ekspresi kueri atau berisi ekspresi kueri.
Ekspresi kueri harus diawali dengan klausul from dan harus diakhiri dengan klausul select atau group. Antara klausa pertama from
dan klausul atau group
terakhirselect
, klausul tersebut dapat berisi satu atau beberapa klausa opsional ini: di mana, orderby, gabungkan, biarkan dan bahkan yang lain dari klausa. Anda juga dapat menggunakan ke dalam kata kunci untuk mengaktifkan hasil join
klausa atau group
untuk berfungsi sebagai sumber untuk klausa kueri lainnya dalam ekspresi kueri yang sama.
Variabel kueri
Di LINQ, variabel kueri adalah variabel mana pun yang menyimpan kueri sebagai ganti kueri hasil. Lebih khusus lagi, variabel kueri selalu merupakan jenis enumerable yang menghasilkan urutan elemen ketika diulang dalam foreach
pernyataan atau panggilan langsung ke metodenya IEnumerator.MoveNext() .
Catatan
Contoh dalam artikel ini menggunakan sumber data dan data sampel berikut.
record City(string Name, long Population);
record Country(string Name, double Area, long Population, List<City> Cities);
record Product(string Name, string Category);
static readonly City[] cities = [
new City("Tokyo", 37_833_000),
new City("Delhi", 30_290_000),
new City("Shanghai", 27_110_000),
new City("São Paulo", 22_043_000),
new City("Mumbai", 20_412_000),
new City("Beijing", 20_384_000),
new City("Cairo", 18_772_000),
new City("Dhaka", 17_598_000),
new City("Osaka", 19_281_000),
new City("New York-Newark", 18_604_000),
new City("Karachi", 16_094_000),
new City("Chongqing", 15_872_000),
new City("Istanbul", 15_029_000),
new City("Buenos Aires", 15_024_000),
new City("Kolkata", 14_850_000),
new City("Lagos", 14_368_000),
new City("Kinshasa", 14_342_000),
new City("Manila", 13_923_000),
new City("Rio de Janeiro", 13_374_000),
new City("Tianjin", 13_215_000)
];
static readonly Country[] countries = [
new Country ("Vatican City", 0.44, 526, [new City("Vatican City", 826)]),
new Country ("Monaco", 2.02, 38_000, [new City("Monte Carlo", 38_000)]),
new Country ("Nauru", 21, 10_900, [new City("Yaren", 1_100)]),
new Country ("Tuvalu", 26, 11_600, [new City("Funafuti", 6_200)]),
new Country ("San Marino", 61, 33_900, [new City("San Marino", 4_500)]),
new Country ("Liechtenstein", 160, 38_000, [new City("Vaduz", 5_200)]),
new Country ("Marshall Islands", 181, 58_000, [new City("Majuro", 28_000)]),
new Country ("Saint Kitts & Nevis", 261, 53_000, [new City("Basseterre", 13_000)])
];
Contoh kode berikut menunjukkan ekspresi kueri sederhana dengan satu sumber data, satu klausul pemfilteran, satu klausul pengurutan, dan tidak ada transformasi elemen sumber. Klausul select
mengakhiri kueri.
// Data source.
int[] scores = [90, 71, 82, 93, 75, 82];
// Query Expression.
IEnumerable<int> scoreQuery = //query variable
from score in scores //required
where score > 80 // optional
orderby score descending // optional
select score; //must end with select or group
// Execute the query to produce the results
foreach (var testScore in scoreQuery)
{
Console.WriteLine(testScore);
}
// Output: 93 90 82 82
Dalam contoh sebelumnya, scoreQuery
adalah variabel kueri, yang terkadang disebut sebagai kueri saja. Variabel kueri tidak menyimpan data hasil aktual, yang diproduksi dalam perulangan foreach
. Dan ketika foreach
pernyataan dijalankan, hasil kueri tidak dikembalikan melalui variabel scoreQuery
kueri . Sebaliknya, mereka dikembalikan melalui variabel testScore
iterasi . Variabel scoreQuery
dapat diulang dalam perulangan foreach
kedua. Ini menghasilkan hasil yang sama selama sumber data maupun sumber data tidak dimodifikasi.
Variabel kueri mungkin menyimpan kueri yang dinyatakan dalam sintaks kueri atau sintaks metode, atau kombinasi keduanya. Dalam contoh berikut, queryMajorCities
dan queryMajorCities2
merupakan variabel kueri:
City[] cities = [
new City("Tokyo", 37_833_000),
new City("Delhi", 30_290_000),
new City("Shanghai", 27_110_000),
new City("São Paulo", 22_043_000)
];
//Query syntax
IEnumerable<City> queryMajorCities =
from city in cities
where city.Population > 100000
select city;
// Execute the query to produce the results
foreach (City city in queryMajorCities)
{
Console.WriteLine(city);
}
// Output:
// City { Population = 120000 }
// City { Population = 112000 }
// City { Population = 150340 }
// Method-based syntax
IEnumerable<City> queryMajorCities2 = cities.Where(c => c.Population > 100000);
Di sisi lain, dua contoh berikut menunjukkan variabel yang tidak mengkueri variabel meskipun masing-masing diinisialisasi dengan kueri. Mereka bukan variabel kueri karena menyimpan hasil:
var highestScore = (
from score in scores
select score
).Max();
// or split the expression
IEnumerable<int> scoreQuery =
from score in scores
select score;
var highScore = scoreQuery.Max();
// the following returns the same result
highScore = scores.Max();
var largeCitiesList = (
from country in countries
from city in country.Cities
where city.Population > 10000
select city
).ToList();
// or split the expression
IEnumerable<City> largeCitiesQuery =
from country in countries
from city in country.Cities
where city.Population > 10000
select city;
var largeCitiesList2 = largeCitiesQuery.ToList();
Jenis eksplisit dan implisit variabel kueri
Dokumentasi ini biasanya menyediakan jenis eksplisit variabel kueri untuk memperlihatkan hubungan jenis antara variabel kueri dan klausul select. Namun, Anda juga dapat menggunakan kata kunci var untuk menginstruksikan pengompilasi untuk menyimpulkan jenis variabel kueri (atau variabel lokal lainnya) pada waktu kompilasi. Misalnya, contoh kueri yang diperlihatkan sebelumnya dalam artikel ini juga dapat dinyatakan dengan menggunakan pengetikan implisit:
var queryCities =
from city in cities
where city.Population > 100000
select city;
Dalam contoh sebelumnya, penggunaan var bersifat opsional. queryCities
IEnumerable<City>
adalah apakah secara implisit atau eksplisit ditik.
Memulai ekspresi kueri
Ekspresi kueri harus diawali dengan klausul from
. Ini menentukan sumber data bersama dengan variabel rentang. Variabel rentang mewakili setiap elemen berturut-turut dalam urutan sumber karena urutan sumber sedang dilintasi. Variabel rentang sangat berjenis berdasarkan jenis elemen dalam sumber data. Dalam contoh berikut, karena countries
merupakan array objek Country
, variabel rentang juga memiliki jenis sebagai Country
. Karena variabel rentang memiliki jenis yang kuat, Anda dapat menggunakan operator titik untuk mengakses anggota jenis yang tersedia.
IEnumerable<Country> countryAreaQuery =
from country in countries
where country.Area > 500000 //sq km
select country;
Variabel rentang berada dalam cakupan hingga kueri keluar baik dengan titik koma atau dengan klausul continuation.
Ekspresi kueri mungkin berisi beberapa from
klausa. Gunakan lebih from
banyak klausa ketika setiap elemen dalam urutan sumber adalah koleksi itu sendiri atau berisi koleksi. Misalnya, asumsikan bahwa Anda memiliki kumpulan objek Country
, yang masing-masing berisi kumpulan objek City
bernama Cities
. Untuk mengkueri objek City
di masing-masing Country
, gunakan dua klausul from
seperti yang ditunjukkan di sini:
IEnumerable<City> cityQuery =
from country in countries
from city in country.Cities
where city.Population > 10000
select city;
(Untuk informasi selengkapnya, lihat klausul from.
Mengakhiri ekspresi kueri
Ekspresi kueri harus diakhiri dengan klausul group
atau klausul select
.
klausaul group
Gunakan klausul group
untuk menghasilkan urutan grup yang diatur oleh kunci yang Anda tentukan. Kunci boleh berupa jenis data apa pun. Misalnya, kueri berikut membuat urutan grup yang berisi satu atau beberapa objek Country
dan yang kuncinya adalah jenis char
dengan nilai yang menjadi huruf pertama nama negara.
var queryCountryGroups =
from country in countries
group country by country.Name[0];
Untuk informasi selengkapnya tentang pengelompokan, lihat klausul group.
pilih klausa
Gunakan klausul select
untuk menghasilkan semua jenis urutan lainnya. Klausul select
sederhana hanya menghasilkan urutan dari jenis objek yang sama dengan objek yang terkandung dalam sumber data. Dalam contoh ini, sumber data berisi objek Country
. Klausul orderby
hanya mengurutkan elemen ke dalam urutan baru dan klausul select
menghasilkan urutan objek Country
yang diurutkan ulang.
IEnumerable<Country> sortedQuery =
from country in countries
orderby country.Area
select country;
Klausul select
dapat digunakan untuk mengubah data sumber menjadi urutan jenis baru. Transformasi ini juga bernama proyeksi. Dalam contoh berikut, select
klausul memproyeksikan urutan jenis anonim yang hanya berisi subset bidang dalam elemen asli. Objek baru diinisialisasi dengan menggunakan penginisialisasi objek.
var queryNameAndPop =
from country in countries
select new
{
Name = country.Name,
Pop = country.Population
};
Jadi dalam contoh ini, var
diperlukan karena kueri menghasilkan jenis anonim.
Untuk informasi selengkapnya tentang semua cara klausul select
dapat digunakan untuk mengubah data sumber, lihat klausul select.
Kelanjutan dengan into
Anda bisa menggunakan kata kunci into
dalam klausul select
atau group
untuk membuat pengidentifikasi sementara yang menyimpan kueri. into
Gunakan klausa saat Anda harus melakukan operasi kueri tambahan pada kueri setelah pengelompokan atau memilih operasi. Dalam contoh berikut, countries
dikelompokkan sesuai dengan populasi dalam kisaran 10 juta. Setelah grup ini dibuat, lebih banyak klausa memfilter beberapa grup, lalu untuk mengurutkan grup dalam urutan naik. Untuk melakukan operasi tambahan tersebut, kelanjutan yang diwakili oleh countryGroup
diperlukan.
// percentileQuery is an IEnumerable<IGrouping<int, Country>>
var percentileQuery =
from country in countries
let percentile = (int)country.Population / 10_000_000
group country by percentile into countryGroup
where countryGroup.Key >= 20
orderby countryGroup.Key
select countryGroup;
// grouping is an IGrouping<int, Country>
foreach (var grouping in percentileQuery)
{
Console.WriteLine(grouping.Key);
foreach (var country in grouping)
{
Console.WriteLine(country.Name + ":" + country.Population);
}
}
Untuk informasi lebih lanjut, lihat ke .
Memfilter, mengurutkan, dan bergabung
Antara klausul from
awal, dan klausul select
atau group
akhir, semua klausul lainnya (where
, join
, orderby
, from
, let
) bersifat opsional. Salah satu klausa opsional mungkin digunakan nol kali atau beberapa kali dalam isi kueri.
klausul where
Gunakan klausul where
untuk memfilter elemen dari data sumber berdasarkan satu atau beberapa ekspresi predikat. Klausul where
dalam contoh berikut memiliki satu predikat dengan dua kondisi.
IEnumerable<City> queryCityPop =
from city in cities
where city.Population is < 200000 and > 100000
select city;
Untuk informasi selengkapnya, lihat klausul where.
klausul orderby
Gunakan klausul orderby
untuk mengurutkan hasil dalam urutan naik atau turun. Anda juga dapat menentukan urutan pengurutan sekunder. Contoh berikut melakukan pengurutan utama pada objek country
menggunakan properti Area
. Kemudian ini melakukan pengurutan sekunder dengan menggunakan properti Population
.
IEnumerable<Country> querySortedCountries =
from country in countries
orderby country.Area, country.Population descending
select country;
Kata ascending
kunci bersifat opsional; ini adalah urutan pengurutan default jika tidak ada urutan yang ditentukan. Untuk informasi selengkapnya, lihat klausul orderby.
klausul Join
Gunakan klausul join
untuk mengaitkan dan/atau menggabungkan elemen dari satu sumber data dengan elemen dari sumber data lain berdasarkan perbandingan kesetaraan antara kunci yang ditentukan di setiap elemen. Di LINQ, operasi gabungan dilakukan pada urutan objek yang elemennya berbeda jenis. Setelah menggabungkan dua urutan, Anda harus menggunakan select
pernyataan atau group
untuk menentukan elemen mana yang akan disimpan dalam urutan output. Anda juga dapat menggunakan jenis anonim untuk menggabungkan properti dari setiap set elemen terkait ke dalam jenis baru untuk urutan output. Contoh berikut mengaitkan objek prod
yang properti Category
miliknya cocok dengan salah satu kategori dalam array string categories
. Produk yang Category
tidak cocok dengan string apa pun difilter categories
. Pernyataan ini select
memproyeksikan jenis baru yang propertinya diambil dari dan cat
prod
.
var categoryQuery =
from cat in categories
join prod in products on cat equals prod.Category
select new
{
Category = cat,
Name = prod.Name
};
Anda juga dapat melakukan gabungan grup dengan menyimpan hasil operasi join
ke dalam variabel sementara menggunakan kata kunci into. Untuk informasi selengkapnya, lihat klausul join.
klausul let
Gunakan klausul let
untuk menyimpan hasil ekspresi, seperti panggilan metode, dalam variabel rentang baru. Dalam contoh berikut, variabel firstName
rentang menyimpan elemen pertama dari array string yang dikembalikan oleh Split
.
string[] names = ["Svetlana Omelchenko", "Claire O'Donnell", "Sven Mortensen", "Cesar Garcia"];
IEnumerable<string> queryFirstNames =
from name in names
let firstName = name.Split(' ')[0]
select firstName;
foreach (var s in queryFirstNames)
{
Console.Write(s + " ");
}
//Output: Svetlana Claire Sven Cesar
Untuk informasi selengkapnya, lihat klausul let.
Subkueri dalam ekspresi kueri
Klausa kueri mungkin berisi ekspresi kueri, yang terkadang disebut sebagai subkueri. Setiap subkueri dimulai dengan klausanya sendiri from
yang tidak selalu menunjuk ke sumber data yang sama dalam klausa pertama from
. Misalnya, kueri berikut menunjukkan ekspresi kueri yang digunakan dalam pernyataan pilih untuk mengambil hasil operasi pengelompokan.
var queryGroupMax =
from student in students
group student by student.Year into studentGroup
select new
{
Level = studentGroup.Key,
HighestScore = (
from student2 in studentGroup
select student2.ExamScores.Average()
).Max()
};
Untuk informasi selengkapnya, lihat Melakukan subkueri pada operasi pengelompokan.
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