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 bir yönerge 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 veya IEnumerable<T>IQueryable<T> koleksiyonu olarak görür. Örneğin, LINQ to XML'de kaynak veriler olarak IEnumerable
<XElement>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 daha sonra aşağıdaki örnekte gösterildiği gibi döndürülen sırayı çeşitli şekillerde sıralayabilir veya gruplandırabilir (varsayın
scores
: ):int[]
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 örnekte bir ile olan
int
yansıtma gösterilmektedirstring
. Yeni türünehighScoresQuery
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 tamsayı dizisinden 80'den
scores
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, yöntemine çağrılmadan önce sorgu ifadesinin çevresinde parantezlerin kullanıldığına Enumerable.Count 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, tarafından döndürülen highScoresQuery
öğe sayısını belirlemek için Count
Count
sonuçlar üzerinde yineleme yapması gerektiğinden, sorgusu çağrısında yürütülür.
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. Sırayla her yan tümce bir veya daha fazla C# ifadesi içerir ve bu ifadeler kendileri bir sorgu ifadesi olabilir veya sorgu ifadesi içerebilir.
Sorgu ifadesinin from yan tümcesiyle başlaması ve select veya group yan tümcesiyle bitmesi gerekir. birinci from
yan tümcesi ile son select
veya group
yan tümcesi arasında şu isteğe bağlı yan tümcelerden birini veya daha fazlasını içerebilir: where, orderby, join, let ve hatta başka bir from yan tümcesi. Aynı sorgu ifadesindeki daha fazla sorgu yan tümcesi için kaynak olarak hizmet vermek üzere bir join
veya group
yan tümcesinin sonucunu etkinleştirmek için into anahtar sözcüğünü de kullanabilirsiniz.
Sorgu değişkeni
LINQ'de sorgu değişkeni, sorgunun sonuçları yerine sorguyu depolayan herhangi bir değişkendir. Daha açık belirtmek gerekirse, sorgu değişkeni her zaman bir deyimde yinelendiğinde veya yöntemine IEnumerator.MoveNext() doğrudan çağrı yapıldığında bir dizi öğe üreten numaralandırılabilir bir foreach
türdür.
Not
Bu makaledeki örneklerde aşağıdaki veri kaynağı ve örnek veriler kullanılmaktadı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
bazen yalnızca sorgu olarak adlandırılan bir sorgu değişkenidir. Sorgu değişkeni, döngüde oluşturulan gerçek sonuç verilerini depolamaz foreach
. Deyimi yürütürken foreach
sorgu sonuçları sorgu değişkeni scoreQuery
aracılığıyla döndürülmüyor. Bunun yerine, yineleme değişkeni testScore
aracılığıyla döndürülürler. Değişken scoreQuery
ikinci foreach
bir döngüde yinelenebilir. Ne değiştirildiği ne de veri kaynağı değiştirildiği sürece 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 hem de queryMajorCities
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 > 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);
Ö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 yazıları
Bu belgeler genellikle sorgu değişkeni ile select yan tümcesi arası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>
öğedir.
Sorgu ifadesi başlatma
Sorgu ifadesi bir from
yan tümceyle 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. Aralık değişkeni, veri kaynağındaki öğelerin türüne göre kesin olarak yazılır. Aşağıdaki örnekte, countries
bir nesne dizisi Country
olduğundan, aralık değişkeni olarak da yazılır Country
. 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 > 500000 //sq km
select country;
Aralık değişkeni, sorgudan noktalı virgülle veya continuation yan tümcesiyle çıkılana kadar kapsam içindedir.
Sorgu ifadesi birden çok from
yan tümce içerebilir. Kaynak dizideki her öğe bir koleksiyon olduğunda veya bir koleksiyon içerdiğinde daha fazla from
yan tümce kullanın. Örneğin, her biri Country
adlı Cities
bir nesne koleksiyonu içeren bir nesne koleksiyonunuz City
olduğunu varsayalım. Her Country
içindeki nesneleri sorgulamak City
için burada gösterildiği gibi iki from
yan tümce 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 from yan tümcesine bakın.
Sorgu ifadesini sonlandırma
Sorgu ifadesinin bir group
yan tümcesi veya select
yan tümcesi ile bitmesi gerekir.
group tümcesi
group
Belirttiğiniz bir anahtara göre düzenlenmiş bir grup dizisi oluşturmak için yan tümcesini kullanın. Anahtar herhangi bir veri türü olabilir. Örneğin, aşağıdaki sorgu bir veya daha fazla Country
nesne içeren ve anahtarı ülke adlarının ilk harfi olan bir tür olan bir char
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 . group yan tümcesi.
select tümcesi
select
Tüm diğer dizi türlerini üretmek için yan tümcesini kullanın. Basit select
bir yan tümcesi, veri kaynağında bulunan nesnelerle aynı türde nesneler dizisi oluşturur. Bu örnekte, veri kaynağı nesneleri içerir Country
. orderby
yan tümcesi yalnızca öğeleri yeni bir düzende sıralar ve select
yan tümcesi yeniden sıralanmış Country
nesnelerin bir dizisini oluşturur.
IEnumerable<Country> sortedQuery =
from country in countries
orderby country.Area
select country;
yan tümcesi select
, kaynak verileri yeni tür dizilerine dönüştürmek için kullanılabilir. Bu dönüştürmeye projeksiyon da adı verilmiştir. Aşağıdaki örnekte yan tümcesi, özgün öğedeki select
alanların yalnızca bir alt kümesini içeren bir dizi anonim türü projelendirmektedir. 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, var
sorgu anonim bir tür ürettiğinden gereklidir.
Bir select
yan tümcenin 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 devam eder
Bir sorguyu into
depolayan geçici bir select
tanımlayıcı oluşturmak için bir veya group
yan tümcesinde anahtar sözcüğünü kullanabilirsiniz. Gruplandırma veya seçme işleminden into
sonra sorguda ek sorgu işlemleri gerçekleştirmeniz gerektiğinde yan tümcesini kullanın. Aşağıdaki örnekte, countries
10 milyonluk aralıklarda popülasyona göre gruplandırılır. Bu gruplar oluşturulduktan sonra, daha fazla yan tümce bazı grupları filtreleyerek grupları artan düzende sıralar. Bu ek işlemleri gerçekleştirmek için tarafından countryGroup
temsil edilen devamlılık gereklidir.
// 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);
}
}
Daha fazla bilgi için bkz . içine.
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 tümcesi
Yan tümcesini where
kullanarak kaynak verilerdeki öğeleri bir veya daha fazla koşul ifadesine göre filtreleyin. where
Aşağıdaki örnekteki yan tümcesinde iki koşul içeren bir koşul vardır.
IEnumerable<City> queryCityPop =
from city in cities
where city.Population is < 200000 and > 100000
select city;
Daha fazla bilgi için where yan tümcesine bakın.
orderby tümcesi
orderby
Sonuçları artan veya azalan düzende sıralamak için yan tümcesini kullanın. İkincil sıralama düzenlerini de belirtebilirsiniz. Aşağıdaki örnek, özelliğini kullanarak Area
nesneler üzerinde country
birincil sıralama gerçekleştirir. Ardından özelliğini kullanarak Population
ikincil bir sıralama gerçekleştirir.
IEnumerable<Country> querySortedCountries =
from country in countries
orderby country.Area, country.Population descending
select country;
Anahtar ascending
sözcük isteğe bağlıdır; herhangi bir düzen belirtilmezse varsayılan sıralama düzenidir. Daha fazla bilgi için bkz . orderby yan tümcesi.
join tümcesi
Bir veri kaynağındaki join
öğeleri, her öğedeki belirtilen anahtarlar arasındaki eşitlik karşılaştırmasına göre başka bir veri kaynağındaki öğelerle ilişkilendirmek ve/veya birleştirmek için yan tümcesini kullanın. 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, özelliği dize dizisindeki categories
kategorilerden biriyle eşleşen nesneleri Category
ilişkilendirirprod
. içindeki herhangi bir dizeyle categories
eşleşmeyen Category
ürünler filtrelenir. deyimi, select
özellikleri hem hem de cat
prod
'den alınan yeni bir tür oluşturur.
var categoryQuery =
from cat in categories
join prod in products on cat equals prod.Category
select new
{
Category = cat,
Name = prod.Name
};
Ayrıca, içinde anahtar sözcüğünü kullanarak işlemin sonuçlarını join
geçici bir değişkende depolayarak bir grup birleştirme gerçekleştirebilirsiniz. Daha fazla bilgi için bkz . join yan tümcesi.
let tümcesi
let
Yöntem çağrısı gibi bir ifadenin sonucunu yeni bir aralık değişkeninde depolamak için yan tümcesini kullanın. Aşağıdaki örnekte, aralık değişkeni firstName
tarafından Split
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 yan tümcesi.
Sorgu ifadesindeki alt sorgular
Sorgu yan tümcesi, bazen alt sorgu olarak adlandırılan bir sorgu ifadesi içerebilir. Her alt sorgu, ilk from
yan tümcede 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.