Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Giriş Dili Tümleşik Sorgu (LINQ) belgelerindeki sorguların çoğu LINQ bildirim temelli sorgu söz dizimini kullanır. C# derleyicisi sorgu söz dizimini yöntem çağrılarına çevirir. Bu yöntem çağrıları standart sorgu işleçlerini uygular.
Where, Select, GroupBy, Join, Max ve Average gibi adları vardır. Sorgu söz dizimi yerine yöntem söz dizimini kullanarak bunları doğrudan çağırırsınız.
Sorgu söz dizimi ve yöntem söz dizimi aynı olsa da, sorgu söz dizimi genellikle daha basit ve daha kolay okunur. Bazı sorguları yöntem çağrıları olarak ifade etmeniz gerekir. Örneğin, belirtilen koşulla eşleşen öğe sayısını alan bir sorguyu ifade etmek için yöntem çağrısı kullanmanız gerekir. Ayrıca, kaynak dizisinde en yüksek değere sahip öğeyi alan bir sorgu için yöntem çağrısı kullanmanız gerekir. Ad alanında standart sorgu işleçleri için başvuru belgelerinde System.Linq genellikle yöntem söz dizimi kullanılır. Sorgularda ve sorgu ifadelerinde yöntem söz dizimlerini kullanmayı öğrenin.
Standart sorgu işleci uzantısı yöntemleri
Aşağıdaki örnekte basit bir sorgu ifadesi ve yöntem tabanlı sorgu olarak yazılmış olan eş zamanlı eşdeğer sorgu gösterilmektedir.
int[] numbers = [ 5, 10, 8, 3, 6, 12 ];
//Query syntax:
IEnumerable<int> numQuery1 =
from num in numbers
where num % 2 == 0
orderby num
select num;
//Method syntax:
IEnumerable<int> numQuery2 = numbers
.Where(num => num % 2 == 0)
.OrderBy(n => n);
foreach (int i in numQuery1)
{
Console.Write(i + " ");
}
Console.WriteLine(System.Environment.NewLine);
foreach (int i in numQuery2)
{
Console.Write(i + " ");
}
İki örnekten alınan çıkış aynıdır. Sorgu değişkeninin türü her iki biçimde de aynıdır: IEnumerable<T>.
İfadenin sağ tarafında yan tümcesinin where nesnesi üzerinde numbers bir örnek yöntemi olarak ifade edildiğine ve türüne IEnumerable<int>sahip olduğuna dikkat edin. Genel IEnumerable<T> arabirim hakkında bilgi sahibiyseniz, bir Where yöntemi olmadığını biliyorsunuz. Ancak, Visual Studio IDE'de IntelliSense tamamlama listesini çağırırsanız, yalnızca bir Where yöntemi değil, aynı zamanda , Select, SelectManyve Joingibi Orderbydiğer birçok yöntemi görürsünüz. Bu yöntemler standart sorgu işleçlerini uygular.
Daha fazla yöntem içeriyor gibi IEnumerable<T> görünse de, içermez. Standart sorgu işleçleri uzantı yöntemleri olarak uygulanır. Uzantı üyeleri var olan bir türü "genişletir"; türüne üyeymiş gibi çağrılabilirler. Standart sorgu işleçleri kapsamını genişletir IEnumerable<T>ve bu nedenle yazabilirsiniz numbers.Where(...). Uzantıları çağırmadan önce using yönergeleriyle kapsama getirirsiniz.
Uzantı üyeleri hakkında daha fazla bilgi için bkz. Uzantı üyeleri. Standart sorgu işleçleri hakkında daha fazla bilgi için bkz . Standart Sorgu İşleçlerine Genel Bakış (C#). Entity Framework ve LINQ to XML gibi bazı LINQ sağlayıcıları, dışındaki IEnumerable<T>diğer türler için kendi standart sorgu işleçlerini ve uzantı üyelerini uygular.
Lambda ifadeleri
Yukarıdaki örnekte, koşullu ifade (num işlecinin sol tarafındaki giriş değişkenidir ve bu değişken sorgu ifadesindekine num karşılık gelir. Derleyici, bunun genel num bir tür numbers olduğunu IEnumerable<T> bildiği için türünü çıkarsayabilir. Lambda gövdesi, sorgu söz dizimindeki veya başka bir C# ifadesi veya deyimindeki ifadeyle aynıdır. Yöntem çağrılarını ve diğer karmaşık mantığı içerebilir. Dönüş değeri ifade sonucudur. Yöntem söz diziminde yalnızca belirli sorguları ifade edebilirsiniz ve bu sorgulardan bazıları lambda ifadeleri gerektirir. Lambda ifadeleri, LINQ araç kutunuzda güçlü ve esnek bir araçtır.
Sorguların birlenebilirliği
Yukarıdaki kod örneğinde, Enumerable.OrderBy yöntemi Whereçağrısında nokta işleci kullanılarak çağrılır.
Where filtrelenmiş bir dizi oluşturur ve ardından Orderby tarafından Whereüretilen diziyi sıralar. Sorgular bir IEnumerabledöndüreceği için, yöntem çağrılarını birbirine zincirleyerek bunları yöntem söz diziminde oluşturursunuz. Sorgu söz dizimini kullanarak sorgu yazdığınızda derleyici bu bileşimi yapar. Sorgu değişkeni sorgunun sonuçlarını depolamadığından, sorguyu yürütürken bile istediğiniz zaman değiştirebilir veya yeni bir sorgunun temeli olarak kullanabilirsiniz.
Aşağıdaki örneklerde, daha önce listelenen her yaklaşımı kullanarak bazı temel LINQ sorguları gösterilmektedir.
Not
Bu sorgular bellek içi koleksiyonlarda çalışır; ancak söz dizimi LINQ to Entities ve LINQ to XML içinde kullanılan söz dizimi ile aynıdır.
Örnek - sorgu söz dizimi
Sorgu ifadeleri oluşturmak için sorgu söz dizimiylesorguların çoğunu yazın. Aşağıdaki örnekte üç sorgu ifadesi gösterilmektedir. İlk sorgu ifadesi, yan where tümcesi ile koşullar uygulayarak sonuçları filtrelemeyi veya kısıtlamayı gösterir. Kaynak dizideki değerleri 7'den büyük veya 3'ten küçük olan tüm öğeleri döndürür. İkinci ifade, döndürülen sonuçların nasıl sıralanması gerektiğini gösterir. Üçüncü ifadede sonuçların bir anahtara göre nasıl gruplandığı gösterilir. Bu sorgu, sözcüğün ilk harfine göre iki grup döndürür.
List<int> numbers = [ 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 ];
// The query variables can also be implicitly typed by using var
// Query #1.
IEnumerable<int> filteringQuery =
from num in numbers
where num is < 3 or > 7
select num;
// Query #2.
IEnumerable<int> orderingQuery =
from num in numbers
where num is < 3 or > 7
orderby num ascending
select num;
// Query #3.
string[] groupingQuery = ["carrots", "cabbage", "broccoli", "beans", "barley"];
IEnumerable<IGrouping<char, string>> queryFoodGroups =
from item in groupingQuery
group item by item[0];
Sorguların türü şeklindedir IEnumerable<T>. Bu sorguların tümü aşağıdaki örnekte gösterildiği gibi kullanılarak var yazılabilir:
var query = from num in numbers...
Önceki her örnekte sorgular, siz bir deyimdeki veya başka bir foreach deyimdeki sorgu değişkeni üzerinde yinelene kadar yürütülmeyecektir.
Örnek - yöntem söz dizimi
Bazı sorgu işlemlerini yöntem çağrısı olarak ifade etmeniz gerekir. Bu tür en yaygın yöntemler, , Sum, , MaxMinve gibi Averagetek sayısal değerler döndüren yöntemlerdir. Tek bir değer döndürdiklerinden ve daha fazla sorgu işlemi için kaynak işlevi göremeyeceklerinden, bu yöntemleri herhangi bir sorguda son olarak çağırın. Aşağıdaki örnekte sorgu ifadesindeki bir yöntem çağrısı gösterilmektedir:
List<int> numbers1 = [ 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 ];
List<int> numbers2 = [ 15, 14, 11, 13, 19, 18, 16, 17, 12, 10 ];
// Query #4.
double average = numbers1.Average();
// Query #5.
IEnumerable<int> concatenationQuery = numbers1.Concat(numbers2);
Yöntemin System.Action veya System.Func<TResult> parametreleri varsa, aşağıdaki örnekte gösterildiği gibi bu bağımsız değişkenleri lambda ifadesi biçiminde sağlayın:
// Query #6.
IEnumerable<int> largeNumbersQuery = numbers2.Where(c => c > 15);
Önceki sorgularda yalnızca Sorgu #4, genel IEnumerable<T> bir koleksiyon değil tek bir değer döndürdüğünden hemen yürütülür. Yönteminin kendisi değerini hesaplamak için veya benzer kod kullanır foreach .
Aşağıdaki örnekte gösterildiği gibi ile varörtük yazma kullanarak önceki sorguların her birini yazabilirsiniz:
// var is used for convenience in these queries
double average = numbers1.Average();
var concatenationQuery = numbers1.Concat(numbers2);
var largeNumbersQuery = numbers2.Where(c => c > 15);
Örnek: karma sorgu ve metot sözdizimi
Bu örnekte, sorgu yan tümcesinin sonuçlarında yöntem söz diziminin nasıl kullanılacağı gösterilmektedir. Sorgu ifadesini parantez içine alın ve nokta işlecini uygulayıp yöntemini çağırın. Aşağıdaki örnekte, #7 sorgusu değeri 3 ile 7 arasında olan sayıların sayısını döndürür.
// Query #7.
// Using a query expression with method syntax
var numCount1 = (
from num in numbers1
where num is > 3 and < 7
select num
).Count();
// Better: Create a new variable to store
// the method call result
IEnumerable<int> numbersQuery =
from num in numbers1
where num is > 3 and < 7
select num;
var numCount2 = numbersQuery.Count();
Sorgu #7 bir koleksiyon değil tek bir değer döndürdüğünden sorgu hemen yürütülür.
Örtük yazmayı var kullanarak önceki sorguyu aşağıdaki gibi yazabilirsiniz:
var numCount = (from num in numbers...
Bunu yöntem söz diziminde aşağıdaki gibi yazabilirsiniz:
var numCount = numbers.Count(n => n is > 3 and < 7);
Aşağıdaki gibi açık yazma kullanarak yazabilirsiniz:
int numCount = numbers.Count(n => n is > 3 and < 7);
Çalışma zamanında koşul filtrelerini dinamik olarak belirtme
Bazı durumlarda, çalışma zamanına kadar yan tümcedeki where kaynak öğelere uygulamanız gereken koşul sayısını bilmezsiniz. Birden çok koşul filtresini dinamik olarak belirtmenin Contains bir yolu, aşağıdaki örnekte gösterildiği gibi yöntemini kullanmaktır. Sorgu, sorgunun yürütüldüğü zaman değerine id göre farklı sonuçlar döndürür.
int[] ids = [ 111, 114, 112 ];
var queryNames = from student in students
where ids.Contains(student.ID)
select new
{
student.LastName,
student.ID
};
foreach (var name in queryNames)
{
Console.WriteLine($"{name.LastName}: {name.ID}");
}
/* Output:
Garcia: 114
O'Donnell: 112
Omelchenko: 111
*/
// Change the ids.
ids = [ 122, 117, 120, 115 ];
// The query will now return different results
foreach (var name in queryNames)
{
Console.WriteLine($"{name.LastName}: {name.ID}");
}
/* Output:
Adams: 120
Feng: 117
Garcia: 115
Tucker: 122
*/
Not
Bu örnekte aşağıdaki veri kaynağı ve 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)])
];
Önceden belirlenmiş alternatif sorgular arasından seçim yapmak için veya if... elsegibi switch denetim akışı deyimlerini kullanabilirsiniz. Aşağıdaki örnekte, studentQuery çalışma zamanı değeri where veya oddYearise true farklı false bir yan tümcesi kullanır.
void FilterByYearType(bool oddYear)
{
IEnumerable<Student> studentQuery = oddYear
? (from student in students
where student.Year is GradeLevel.FirstYear or GradeLevel.ThirdYear
select student)
: (from student in students
where student.Year is GradeLevel.SecondYear or GradeLevel.FourthYear
select student);
var descr = oddYear ? "odd" : "even";
Console.WriteLine($"The following students are at an {descr} year level:");
foreach (Student name in studentQuery)
{
Console.WriteLine($"{name.LastName}: {name.ID}");
}
}
FilterByYearType(true);
/* Output:
The following students are at an odd year level:
Fakhouri: 116
Feng: 117
Garcia: 115
Mortensen: 113
Tucker: 119
Tucker: 122
*/
FilterByYearType(false);
/* Output:
The following students are at an even year level:
Adams: 120
Garcia: 114
Garcia: 118
O'Donnell: 112
Omelchenko: 111
Zabokritski: 121
*/
Sorgu ifadelerinde boş değerler işleme
Bu örnek, kaynak koleksiyonlardaki olası null değerlerin nasıl işleneceğini gösterir. gibi bir IEnumerable<T> nesne koleksiyonu, değeri null olan öğeler içerebilir. Kaynak koleksiyon ise null veya değeri nullolan bir öğe içeriyorsa ve sorgunuz değerleri işlemezse null , sorguyu yürüttüğünüzde bir NullReferenceException oluşturulur.
Aşağıdaki örnekte bu türler ve statik veri dizileri kullanılır:
record Product(string Name, int CategoryID);
record Category(string Name, int ID);
static Category?[] categories =
[
new ("brass", 1),
null,
new ("winds", 2),
default,
new ("percussion", 3)
];
static Product?[] products =
[
new Product("Trumpet", 1),
new Product("Trombone", 1),
new Product("French Horn", 1),
null,
new Product("Clarinet", 2),
new Product("Flute", 2),
null,
new Product("Cymbal", 3),
new Product("Drum", 3)
];
Aşağıdaki örnekte gösterildiği gibi null başvuru özel durumunu önlemek için savunmayla kodlayabilirsiniz:
var query1 = from c in categories
where c != null
join p in products on c.ID equals p?.CategoryID
select new
{
Category = c.Name,
Name = p.Name
};
Önceki örnekte yan tümcesi, where kategoriler dizisindeki tüm null öğeleri filtreler. Bu teknik, join yan tümcesindeki null denetiminden bağımsızdır. Bu örnekte null olan koşullu ifade, için Products.CategoryIDkısaltma olan türünde int?olduğundan çalışırNullable<int>.
Birleştirme yan tümcesinde, karşılaştırma anahtarlarından yalnızca biri null değer türündeyse, diğerini sorgu ifadesinde null atanabilir bir değer türüne dönüştürebilirsiniz. Aşağıdaki örnekte, türündeki EmployeeIDdeğerleri içeren bir sütun olduğunu int? varsayalım:
var query =
from o in db.Orders
join e in db.Employees
on o.EmployeeID equals (int?)e.EmployeeID
select new { o.OrderID, e.FirstName };
Örneklerin equals her birinde sorgu anahtar sözcüğü kullanılır. ve için desenler içeren desen is null eşleştirmeyiis not null. Sorgu sağlayıcıları yeni C# söz dizimini doğru yorumlayamadığından bu desenler LINQ sorgularında önerilmez. Sorgu sağlayıcısı, C# sorgu ifadelerini Entity Framework Core gibi yerel bir veri biçimine çeviren bir kitaplıktır. Sorgu sağlayıcıları arabirimi uygulayan System.Linq.IQueryProvider veri kaynakları oluşturmak için arabirimi uygular System.Linq.IQueryable<T> .
Sorgu ifadelerinde özel durumları işleme
Sorgu ifadesi bağlamında herhangi bir yöntemi çağırabilirsiniz. Veri kaynağının içeriğini değiştirme veya özel durum oluşturma gibi yan etki oluşturabilen bir sorgu ifadesinde hiçbir yöntemi çağırmayın. Bu örnekte, özel durum işlemeyle ilgili genel .NET yönergelerini ihlal etmeden sorgu ifadesindeki yöntemleri çağırdığınızda özel durumların nasıl yükseltilmesinin önlenmesi gösterilmektedir. Bu yönergeler, belirli bir bağlamda neden atıldığını anladığınızda belirli bir istisnayı yakalamanın kabul edilebilir olduğunu belirtir. Daha fazla bilgi için bkz . Özel Durumlar için En İyi Yöntemler.
Son örnek, bir sorgunun yürütülmesi sırasında özel durum oluşturmanız gerektiğinde bu durumların nasıl işleneceğini gösterir.
Aşağıdaki örnekte, özel durum işleme kodunun sorgu ifadesinin dışına nasıl taşınacakları gösterilmektedir. Bu şekilde yeniden düzenleyebilirsiniz, ancak yöntem sorguda yerel olarak bulunan herhangi bir değişkene bağımlı olmadığında. Sorgu ifadesinin dışındaki özel durumlarla başa çıkmak daha kolaydır.
// A data source that is very likely to throw an exception!
IEnumerable<int> GetData() => throw new InvalidOperationException();
// DO THIS with a datasource that might
// throw an exception.
IEnumerable<int>? dataSource = null;
try
{
dataSource = GetData();
}
catch (InvalidOperationException)
{
Console.WriteLine("Invalid operation");
}
if (dataSource is not null)
{
// If we get here, it is safe to proceed.
var query = from i in dataSource
select i * i;
foreach (var i in query)
{
Console.WriteLine(i.ToString());
}
}
catch (InvalidOperationException) Yukarıdaki örnekteki blokta, özel durumu uygulamanız için uygun şekilde işleyin (veya işlemeyin).
Bazı durumlarda, sorgunun içinden oluşan bir özel duruma en iyi yanıt, sorgu yürütmeyi hemen durdurmak olabilir. Aşağıdaki örnek, sorgu gövdesinden oluşturulabilecek özel durumların nasıl işleneceğini gösterir. Bunun SomeMethodThatMightThrow , sorgu yürütmenin durdurulmasını gerektiren bir özel duruma neden olabileceğini varsayalım.
try Blok, sorgunun foreach kendisini değil döngünün içine alır.
foreach Döngü, sorgunun yürütüldiği noktadır. Sorgu yürütülürken çalışma zamanı özel durumları oluşturulur. Bu nedenle, bunları foreach döngüsünde işleyin.
// Not very useful as a general purpose method.
string SomeMethodThatMightThrow(string s) =>
s[4] == 'C' ?
throw new InvalidOperationException() :
$"""C:\newFolder\{s}""";
// Data source.
string[] files = ["fileA.txt", "fileB.txt", "fileC.txt"];
// Demonstration query that throws.
var exceptionDemoQuery = from file in files
let n = SomeMethodThatMightThrow(file)
select n;
try
{
foreach (var item in exceptionDemoQuery)
{
Console.WriteLine($"Processing {item}");
}
}
catch (InvalidOperationException e)
{
Console.WriteLine(e.Message);
}
/* Output:
Processing C:\newFolder\fileA.txt
Processing C:\newFolder\fileB.txt
Operation is not valid due to the current state of the object.
*/
Beklediğiniz istisnayı yakalayın ve gerekli temizlemeleri bir finally bloğunda yapın.