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ınscores: ):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österilmektedir string. Yeni türüne highScoresQuerydikkat 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 CountCount 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 scoreQueryaracılığıyla döndürülmüyor. Bunun yerine, yineleme değişkeni testScorearacı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 queryMajorCitiesqueryMajorCities2 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ı Citiesbir nesne koleksiyonu içeren bir nesne koleksiyonunuz City olduğunu varsayalım. Her Countryiç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 catprod'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 Splitdö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.

Ayrıca bkz.