Sorgu ifadesi temelleri
Bu makalede C# dilindeki sorgu ifadeleriyle ilgili temel kavramlar tanıtılmıştır.
Sorgu nedir ve ne yapar?
sorgu, belirli bir veri kaynağından (veya kaynaklarından) alınacak verileri ve döndürülen verilerin hangi şekil ve kuruluşa sahip olması gerektiğini açıklayan yönergeler kümesidir. Sorgu, ürettiği sonuçlardan farklıdır.
Genellikle, kaynak veriler mantıksal olarak aynı türde bir öğe dizisi olarak düzenlenir. Örneğin, BIR SQL veritabanı tablosu bir satır dizisi içerir. XML dosyasında XML öğelerinin bir "sırası" vardır (XML öğeleri ağaç yapısında hiyerarşik olarak düzenlenmiş olsa da). Bellek içi koleksiyon bir dizi nesne içerir.
Uygulamanın bakış açısından özgün kaynak verilerin belirli türü ve yapısı önemli değildir. Uygulama her zaman kaynak verileri bir IEnumerable<T> veya IQueryable<T> koleksiyonu olarak görür. Örneğin, LINQ to XML'de kaynak veriler IEnumerable
<XElement>olarak görünür hale getirilir.
Bu kaynak dizisini göz önünde bulundurarak bir sorgu şu üç işlemden birini yapabilir:
Öğeleri tek tek değiştirmeden yeni bir dizi oluşturmak için öğelerin bir alt kümesini alın. Sorgu, aşağıdaki örnekte gösterildiği gibi döndürülen sırayı çeşitli şekillerde sıralayabilir veya gruplandırabilir (
scores
birint[]
olduğunu varsayın):IEnumerable<int> highScoresQuery = from score in scores where score > 80 orderby score descending select score;
Önceki örnekte olduğu gibi bir öğe dizisi alın, ancak bunları yeni bir nesne türüne dönüştürün. Örneğin, bir sorgu bir veri kaynağındaki belirli müşteri kayıtlarından yalnızca aile adlarını alabilir. Ya da kaydın tamamını alıp son sonuç dizisini oluşturmadan önce başka bir bellek içi nesne türü ve hatta XML verileri oluşturmak için kullanabilir. Aşağıdaki örnek, bir
int
’danstring
’e yapılan projeksiyonu gösterir. yenihighScoresQuery
türüne dikkat edin.IEnumerable<string> highScoresQuery2 = from score in scores where score > 80 orderby score descending select $"The score is {score}";
Kaynak veriler hakkında aşağıdakiler gibi tekil bir değer alın:
Belirli bir koşulla eşleşen öğelerin sayısı.
En büyük veya en az değere sahip öğe.
Bir koşulla eşleşen ilk öğe veya belirtilen öğe kümesindeki belirli değerlerin toplamı. Örneğin, aşağıdaki sorgu
scores
tamsayı dizisinden 80'den büyük puan sayısını döndürür:var highScoreCount = ( from score in scores where score > 80 select score ).Count();
Önceki örnekte, Enumerable.Count yöntemine çağrıdan önce sorgu ifadesinin çevresinde parantezlerin kullanıldığına dikkat edin. Somut sonucu depolamak için yeni bir değişken de kullanabilirsiniz.
IEnumerable<int> highScoresQuery3 = from score in scores where score > 80 select score; var scoreCount = highScoresQuery3.Count();
Önceki örnekte sorgu Count
çağrısında yürütülür çünkü Count
highScoresQuery
tarafından döndürülen öğe sayısını belirlemek için sonuçlar üzerinde yinelemesi gerekir.
Sorgu ifadesi nedir?
sorgu ifadesi, sorgu söz diziminde ifade edilen bir sorgudur. Sorgu ifadesi birinci sınıf bir dil yapısıdır. Diğer ifadeler gibi ve C# ifadesinin geçerli olduğu herhangi bir bağlamda kullanılabilir. Sorgu ifadesi, SQL veya XQuery'ye benzer bildirim temelli bir söz diziminde yazılmış bir yan tümce kümesinden oluşur. Her bir ifade sırasıyla bir veya daha fazla C# ifadesi içerir ve bu ifadeler, kendi başlarına bir sorgu ifadesi olabilir veya sorgu ifadeleri içerebilir.
Sorgu ifadesi yan tümcesinden join
veya group
yan tümcesinin sonucunu etkinleştirmek için into
anahtar sözcüğünü de kullanabilirsiniz.
Sorgu değişkeni
LINQ'te sorgu değişkeni, sorgunun sonuçları yerine sorgu depolayan herhangi bir değişkendir. Daha açık belirtmek gerekirse, sorgu değişkeni her zaman bir foreach
deyiminde yinelendiğinde veya IEnumerator.MoveNext() yöntemine doğrudan çağrı yapıldığında bir dizi öğe üreten numaralandırılabilir bir türdür.
Not
Bu makaledeki örneklerde aşağıdaki veri kaynağı ve örnek veriler kullanılır.
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)])
];
Aşağıdaki kod örneğinde bir veri kaynağı, bir filtreleme yan tümcesi, bir sıralama yan tümcesi ve kaynak öğelerin dönüşümü olmayan basit bir sorgu ifadesi gösterilmektedir.
select
yan tümcesi sorguyu sonlandırır.
// 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
Önceki örnekte scoreQuery
bir sorgu değişkenidir ve bazen yalnızca sorguolarak adlandırılır. Sorgu değişkeni, foreach
döngüsünde üretilen gerçek sonuç verilerini depolamaz.
foreach
deyimi yürütüldüğünde, sorgu sonuçları scoreQuery
sorgu değişkeni aracılığıyla döndürülmüyor. Bunun yerine, testScore
yineleme değişkeni aracılığıyla döndürülürler.
scoreQuery
değişkeni ikinci bir foreach
döngüsünde yinelenebilir. Kendisinin ya da veri kaynağının değiştirildiği haller haricinde aynı sonuçları üretir.
Sorgu değişkeni, sorgu söz dizimi veya yöntem söz dizimi ile ifade edilen bir sorguyu ya da ikisinin birleşimini depolayabilir. Aşağıdaki örneklerde hem queryMajorCities
hem de queryMajorCities2
sorgu değişkenleridir:
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 > 30_000_000
select city;
// Execute the query to produce the results
foreach (City city in queryMajorCities)
{
Console.WriteLine(city);
}
// Output:
// City { Name = Tokyo, Population = 37833000 }
// City { Name = Delhi, Population = 30290000 }
// Method-based syntax
IEnumerable<City> queryMajorCities2 = cities.Where(c => c.Population > 30_000_000);
// Execute the query to produce the results
foreach (City city in queryMajorCities2)
{
Console.WriteLine(city);
}
// Output:
// City { Name = Tokyo, Population = 37833000 }
// City { Name = Delhi, Population = 30290000 }
Öte yandan aşağıdaki iki örnek, her biri bir sorguyla başlatılmış olsa bile sorgu değişkeni olmayan değişkenleri gösterir. Sonuçları depoladıkları için sorgu değişkenleri değildir:
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();
Sorgu değişkenlerinin açık ve örtük tür belirlemesi
Bu belge genellikle sorgu değişkeni ile select yan tümcesiarasındaki tür ilişkisini göstermek için sorgu değişkeninin açık türünü sağlar. Ancak, derleyiciye derleme zamanında bir sorgu değişkeninin (veya başka bir yerel değişkenin) türünü çıkarmasını bildirmek için var anahtar sözcüğünü de kullanabilirsiniz. Örneğin, bu makalede daha önce gösterilen sorgu örneği örtük yazma kullanılarak da ifade edilebilir:
var queryCities =
from city in cities
where city.Population > 100000
select city;
Yukarıdaki örnekte, var kullanımı isteğe bağlıdır.
queryCities
, örtük veya açıkça yazılan bir IEnumerable<City>
.
Sorgu ifadesi başlatma
Sorgu ifadesi bir from
yan tümcesiyle başlamalıdır. Bir veri kaynağını bir aralık değişkeniyle birlikte belirtir. Aralık değişkeni, kaynak dizide geçiş yapılırken kaynak dizideki ardışık her öğeyi temsil eder. Dizi değişkeni, veri kaynağındaki öğelerin türüne göre sıkı şekilde yazılır. Aşağıdaki örnekte, countries
bir Country
nesnesi dizisi olduğundan, aralık değişkeni de Country
olarak yazılır. Aralık değişkeni kesin olarak yazıldığı için, türün kullanılabilir üyelerine erişmek için nokta işlecini kullanabilirsiniz.
IEnumerable<Country> countryAreaQuery =
from country in countries
where country.Area > 20 //sq km
select country;
Aralık değişkeni, sorgudan noktalı virgülle veya devamlılık yan tümcesiyle çıkılana kadar kapsam içindedir.
Sorgu ifadesi birden çok from
yan tümcesi içerebilir. Kaynak dizideki her öğe bir koleksiyon olduğunda veya bir koleksiyon içerdiğinde daha fazla from
yan tümcesi kullanın. Örneğin, her biri Country
adlı bir City
nesnesi koleksiyonu içeren bir Cities
nesnesi koleksiyonunuz olduğunu varsayalım. Her City
Country
nesnelerini sorgulamak için, burada gösterildiği gibi iki from
yan tümcesi kullanın:
IEnumerable<City> cityQuery =
from country in countries
from city in country.Cities
where city.Population > 10000
select city;
Daha fazla bilgi için,maddesinden
Sorgu ifadesini sonlandırma
Sorgu ifadesi bir group
yan tümcesiyle veya select
yan tümcesiyle bitmelidir.
Grup cümlesi
group
yan tümcesini kullanarak belirttiğiniz bir anahtara göre düzenlenmiş bir grup dizisi oluşturun. Anahtar herhangi bir veri türü olabilir. Örneğin, aşağıdaki sorgu bir veya daha fazla Country
nesnesi içeren ve anahtarı ülkelerin adlarının ilk harfi olan bir char
türü olan bir grup dizisi oluşturur.
var queryCountryGroups =
from country in countries
group country by country.Name[0];
Gruplandırma hakkında daha fazla bilgi için bkz. grup yan tümcesi.
select ifadesi
Diğer tüm dizi türlerini üretmek için select
yan tümcesini kullanın. Basit bir select
yan tümcesi yalnızca veri kaynağında yer alan nesnelerle aynı türde nesneler dizisi oluşturur. Bu örnekte, veri kaynağı Country
nesneleri içerir.
orderby
yan tümcesi yalnızca öğeleri yeni bir düzende sıralar ve select
yan tümcesi yeniden sıralanmış Country
nesnelerinin bir dizisini oluşturur.
IEnumerable<Country> sortedQuery =
from country in countries
orderby country.Area
select country;
select
yan tümcesi, kaynak verileri yeni tür dizilerine dönüştürmek için kullanılabilir. Bu dönüşüm, projeksiyonu olarak da adlandırılır. Aşağıdaki örnekte, projeler select
yan tümcesi, özgün öğedeki alanların yalnızca bir alt kümesini içeren bir dizi anonim tür. Yeni nesneler bir nesne başlatıcı kullanılarak başlatılır.
var queryNameAndPop =
from country in countries
select new
{
Name = country.Name,
Pop = country.Population
};
Bu nedenle bu örnekte sorgu anonim bir tür ürettiğinden var
gereklidir.
Bir select
yan tümcesinin kaynak verileri dönüştürmek için kullanılabilmesinin tüm yolları hakkında daha fazla bilgi için bkz. select yan tümcesi.
ile devamları
sorguyu depolayan geçici bir tanımlayıcı oluşturmak için into
veya select
yan tümcesinde group
anahtar sözcüğünü kullanabilirsiniz. Gruplandırma veya seçme işleminden sonra sorguda ek sorgu işlemleri gerçekleştirmeniz gerektiğinde into
yan tümcesini kullanın. Aşağıdaki örnekte, countries
10 milyon aralığındaki popülasyona göre gruplandırılır. Bu gruplar oluşturulduktan sonra, daha fazla yan tümce bazı grupları filtreler ve ardından grupları artan düzende sıralar. Bu ek işlemleri gerçekleştirmek için countryGroup
tarafından temsil edilen devamlılık gereklidir.
// percentileQuery is an IEnumerable<IGrouping<int, Country>>
var percentileQuery =
from country in countries
let percentile = (int)country.Population / 1_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);
}
}
Daha fazla bilgi için bkz. into
.
Filtreleme, sıralama ve birleştirme
Başlangıç from
yan tümcesi ile bitiş select
veya group
yan tümcesi arasında, diğer tümceler (where
, join
, orderby
, from
, let
) isteğe bağlıdır. İsteğe bağlı yan tümcelerden herhangi biri sorgu gövdesinde sıfır veya birden çok kez kullanılabilir.
where koşulu
Kaynak verilerdeki öğeleri bir veya daha fazla koşul ifadesine göre filtrelemek için where
yan tümcesini kullanın. Aşağıdaki örnekteki where
yan tümcesinde iki koşul içeren bir koşul vardır.
IEnumerable<City> queryCityPop =
from city in cities
where city.Population is < 15_000_000 and > 10_000_000
select city;
Daha fazla bilgi için. madde koşullarına bkz:
orderby koşulu
Sonuçları artan veya azalan düzende sıralamak için orderby
yan tümcesini kullanın. İkincil sıralama düzenlerini de belirtebilirsiniz. Aşağıdaki örnek, country
özelliğini kullanarak Area
nesneleri üzerinde birincil sıralama gerçekleştirir. Ardından Population
özelliğini kullanarak ikincil bir sıralama gerçekleştirir.
IEnumerable<Country> querySortedCountries =
from country in countries
orderby country.Area, country.Population descending
select country;
ascending
anahtar sözcüğü isteğe bağlıdır; hiçbir düzen belirtilmezse, varsayılan sıralama düzenidir. Daha fazla bilgi için bkz. "orderby" yan tümcesi.
Birleştirme yan tümcesi
join
yan tümcesini kullanarak bir veri kaynağındaki öğeleri, her öğedeki belirtilen anahtarlar arasındaki eşitlik karşılaştırmasına göre başka bir veri kaynağındaki öğelerle ilişkilendirin ve/veya birleştirin. LINQ'te birleştirme işlemleri, öğeleri farklı türlerde olan nesne dizilerinde gerçekleştirilir. İki diziyi birleştirdikten sonra, çıkış dizisinde depolanacak öğeyi belirtmek için bir select
veya group
deyimi kullanmanız gerekir. Ayrıca, her ilişkili öğe kümesindeki özellikleri çıkış dizisi için yeni bir türde birleştirmek için anonim bir tür de kullanabilirsiniz. Aşağıdaki örnek, prod
özelliği Category
dize dizisindeki kategorilerden biriyle eşleşen categories
nesneleri ilişkilendirir.
Category
categories
ile eşleşmeyen ürünler filtrelenir. select
ifadesi, özellikleri hem cat
'ten hem de prod
'ten alınan yeni bir tür yansıtır.
var categoryQuery =
from cat in categories
join prod in products on cat equals prod.Category
select new
{
Category = cat,
Name = prod.Name
};
join
işleminin sonuçlarını into
anahtar sözcüğünü kullanarak geçici bir değişkende depolayarak da grup birleştirme gerçekleştirebilirsiniz. Daha fazla bilgi için bkz. join yan tümcesi.
let yan tümcesi
yöntem çağrısı gibi bir ifadenin sonucunu yeni bir aralık değişkeninde depolamak için let
yan tümcesini kullanın. Aşağıdaki örnekte, firstName
aralık değişkeni, Split
tarafından döndürülen dize dizisinin ilk öğesini depolar.
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
Daha fazla bilgi için bkz. let ifadesi.
Sorgu ifadesindeki alt sorgular
Sorgu yan tümcesi, bazen alt sorgusuolarak adlandırılan bir sorgu ifadesi içerebilir. Her alt sorgu, ilk from
yan tümcesiyle aynı veri kaynağına işaret etmeyen kendi from
yan tümcesiyle başlar. Örneğin, aşağıdaki sorgu bir gruplandırma işleminin sonuçlarını almak için select deyiminde kullanılan bir sorgu ifadesini gösterir.
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()
};
Daha fazla bilgi için bkz. gruplandırma işleminde alt sorgu gerçekleştirme.