Aracılığıyla paylaş


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 bir int[]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’dan string’e yapılan projeksiyonu gösterir. yeni highScoresQuerytü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ü CounthighScoresQuerytarafı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 ile başlamalı ve seçim veya grup yan tümcesiyle bitmelidir. İlk yan tümcesi ile son veya yan tümcesi arasında, şu isteğe bağlı yan tümcelerden birini veya daha fazlasını içerebilir: burada, orderby, birleştirme, ve hatta yan tümcelerinden başka bir izin verir. aynı sorgu ifadesindeki daha fazla sorgu yan tümcesi için kaynak görevi görecek 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 scoreQuerybir 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ı scoreQuerysorgu değişkeni aracılığıyla döndürülmüyor. Bunun yerine, testScoreyineleme 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 Countryolarak 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 Countryadlı bir City nesnesi koleksiyonu içeren bir Cities nesnesi koleksiyonunuz olduğunu varsayalım. Her CityCountry 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 'a bakın.

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, Splittarafı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.

Ayrıca bkz.