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.
Bir kullanıcı tarafından LINQ sorgusu oluşturulduktan sonra komut ağacına dönüştürülür. Komut ağacı, Entity Framework ile uyumlu bir sorgunun gösterimidir. Ardından komut ağacı veri kaynağına karşı yürütülür. Sorgu yürütme zamanında, sonuç gerçekleştirmede kullanılan ifadeler de dahil olmak üzere tüm sorgu ifadeleri (sorgunun tüm bileşenleri) değerlendirilir.
Sorgu ifadelerinin hangi noktada yürütülebileceği farklılık gösterebilir. SORGU değişkeni oluşturulduğunda değil, sorgu değişkeni yinelendiğinde LINQ sorguları her zaman yürütülür. Buna ertelenmiş yürütme denir. Sorgu sonuçlarını önbelleğe almak için yararlı olan sorguyu hemen yürütülmeye de zorlayabilirsiniz. Bu konu başlığında daha sonra açıklanmıştır.
LinQ to Entities sorgusu yürütürken, sorgudaki bazı ifadeler sunucuda yürütülebilir ve bazı bölümler istemcide yerel olarak yürütülebilir. Bir ifadenin istemci tarafı değerlendirmesi, sorgu sunucuda yürütülmeden önce gerçekleşir. İstemcide bir ifade değerlendirilirse, bu değerlendirmenin sonucu sorgudaki ifadeyle değiştirilir ve sorgu sunucuda yürütülür. Sorgular veri kaynağında yürütülürken, veri kaynağı yapılandırması istemcide belirtilen davranışı geçersiz kılar. Örneğin, null değer işleme ve sayısal duyarlık sunucu ayarlarına bağlıdır. Sunucuda sorgu yürütme sırasında oluşturulan tüm özel durumlar doğrudan istemciye iletilir.
Tavsiye
Bir işlecin yürütme davranışını hızla tanımlamanızı sağlayan tablo biçimindeki sorgu işleçlerinin kolay bir özeti için bkz. Standart Sorgu İşleçlerinin Yürütme Biçimine Göre Sınıflandırması (C#).
Sorgu yürütmesinin ertelenmesi
Bir dizi değer döndüren bir sorguda, sorgu değişkeninin kendisi hiçbir zaman sorgu sonuçlarını tutmaz ve yalnızca sorgu komutlarını depolar. Sorgunun yürütülmesi, sorgu değişkeni bir foreach veya For Each döngüsünde yinelene kadar ertelenmiş olur. Bu, ertelenmiş yürütme olarak bilinir; başka bir ifadeyle, sorgunun yürütülmesi, sorgu oluşturmadan bir süre sonra gerçekleşir. Bu, bir sorguyu istediğiniz sıklıkta yürütebileceğiniz anlamına gelir. Bu, örneğin diğer uygulamalar tarafından güncelleştirilen bir veritabanınız olduğunda kullanışlıdır. Uygulamanızda, en son bilgileri almak için bir sorgu oluşturabilir ve her seferinde güncelleştirilmiş bilgileri döndürerek sorguyu tekrar tekrar yürütebilirsiniz.
Ertelenmiş yürütme, birden çok sorguyu birleştirmeye veya bir sorguyu uzatmaya olanak tanır. Bir sorgu genişletildiğinde, yeni işlemleri içerecek şekilde değiştirilir ve nihai yürütme değişiklikleri yansıtır. Aşağıdaki örnekte, ilk sorgu tüm ürünleri döndürür. İkinci sorgu, "L" boyutundaki tüm ürünleri döndürmek için kullanarak Where ilk sorguyu genişletir:
using (AdventureWorksEntities context = new AdventureWorksEntities())
{
IQueryable<Product> productsQuery =
from p in context.Products
select p;
IQueryable<Product> largeProducts = productsQuery.Where(p => p.Size == "L");
Console.WriteLine("Products of size 'L':");
foreach (var product in largeProducts)
{
Console.WriteLine(product.Name);
}
}
Using context As New AdventureWorksEntities()
Dim productsQuery = _
From p In context.Products _
Select p
Dim largeProducts = _
productsQuery.Where(Function(p) p.Size = "L")
Console.WriteLine("Products of size 'L':")
For Each product In largeProducts
Console.WriteLine(product.Name)
Next
End Using
Bir sorgu yürütüldükten sonra, ardışık tüm sorgular bellek içi LINQ işleçlerini kullanır.
foreach veya For Each deyimini kullanarak ya da LINQ dönüştürme işleçlerinden birini çağırarak sorgu değişkeni üzerinde yinelemek anında yürütmeye neden olur. Bu dönüştürme işleçleri şunlardır: ToList, ToArray, ToLookupve ToDictionary.
Anında Sorgu Yürütme
Bir dizi değer üreten sorguların ertelenmiş yürütülmesinin aksine, tek değer döndüren sorgular hemen yürütülür. Tekil sorgulara örnek olarak Average, Count, First ve Max verilebilir. Sorgunun tekil sonucu hesaplamak için bir dizi oluşturması gerektiğinden, bunlar hemen yürütülür. Ayrıca anında yürütülmesini zorlayabilirsiniz. Bu, bir sorgunun sonuçlarını önbelleğe almak istediğinizde kullanışlıdır. Tek değer üretmeyen bir sorgunun hemen yürütülmesini zorlamak için, bir sorguda veya sorgu değişkeninde ToList yöntemini, ToDictionary yöntemini veya ToArray yöntemini çağırabilirsiniz. Aşağıdaki örnek, bir diziyi hemen bir diziye dönüştürmek için ToArray yöntemini kullanır.
using (AdventureWorksEntities context = new AdventureWorksEntities())
{
ObjectSet<Product> products = context.Products;
Product[] prodArray = (
from product in products
orderby product.ListPrice descending
select product).ToArray();
Console.WriteLine("Every price from highest to lowest:");
foreach (Product product in prodArray)
{
Console.WriteLine(product.ListPrice);
}
}
Using context As New AdventureWorksEntities
Dim products As ObjectSet(Of Product) = context.Products
Dim prodArray As Product() = ( _
From product In products _
Order By product.ListPrice Descending _
Select product).ToArray()
Console.WriteLine("The list price from highest to lowest:")
For Each prod As Product In prodArray
Console.WriteLine(prod.ListPrice)
Next
End Using
Sorgu ifadesinden hemen sonra foreach veya For Each döngüsünü koyarak yürütmeyi zorlayabilirsiniz; ancak, ToList veya ToArray ile tüm verileri tek bir koleksiyon nesnesinde önbelleğe alırsınız.
Mağaza Uygulaması
Genel olarak, LINQ to Entities ifadeleri sunucuda değerlendirilir ve ifadenin davranışının ortak dil çalışma zamanı (CLR) semantiğini değil, veri kaynağının davranışlarını izlemesi beklenmemelidir. Bunun istisnaları vardır, ancak bunlar ifadenin istemcide yürütülmesi gibi durumlar içindir. Bu, örneğin sunucu ve istemci farklı saat dilimlerinde olduğunda beklenmeyen sonuçlara neden olabilir.
Sorgudaki bazı ifadeler istemcide yürütülebilir. Genel olarak, sorgu yürütmenin çoğunun sunucuda gerçekleşmesi beklenir. Veri kaynağına eşlenen sorgu öğelerine karşı yürütülen yöntemlerin yanı sıra, sorguda genellikle yerel olarak yürütülebilen ifadeler vardır. Sorgu ifadesinin yerel olarak yürütülmesi, sorgu yürütme veya sonuç oluşturmada kullanılabilecek bir değer verir.
Değerlerin bağlanması, alt ifadeler, kapanışlardan gelen alt sorgular ve nesnelerin sorgu sonuçları olarak somutlaştırılması gibi bazı işlemler her zaman istemcide yürütülür. Bunun net etkisi, bu öğelerin (örneğin parametre değerleri) yürütme sırasında güncelleştirilememesidir. Anonim türler veri kaynağında doğrudan oluşturulabilir, ancak bunun böyle olduğu varsayılmamalıdır. Satır içi gruplandırmalar veri kaynağında da oluşturulabilir, ancak bu her örnekte varsayılmamalıdır. Genel olarak, sunucuda nelerin oluşturulduğunda herhangi bir varsayımda bulunmamak en iyisidir.
Bu bölümde, kodun istemcide yerel olarak yürütüldiği senaryolar açıklanmaktadır. Hangi ifade türlerinin yerel olarak yürütüldiği hakkında daha fazla bilgi için bkz. LINQ to Entities Queries içindeki ifadeler.
Değişmez Değerler ve Parametreler
Aşağıdaki örnekteki orderID değişken gibi yerel değişkenler istemcide değerlendirilir.
int orderID = 51987;
IQueryable<SalesOrderHeader> salesInfo =
from s in context.SalesOrderHeaders
where s.SalesOrderID == orderID
select s;
Dim orderID As Integer = 51987
Dim salesInfo = _
From s In context.SalesOrderHeaders _
Where s.SalesOrderID = orderID _
Select s
Yöntem parametreleri de istemcide değerlendirilir. Aşağıdaki orderID yöntemine geçirilen MethodParameterExample parametresi bir örnektir.
public static void MethodParameterExample(int orderID)
{
using (AdventureWorksEntities context = new AdventureWorksEntities())
{
IQueryable<SalesOrderHeader> salesInfo =
from s in context.SalesOrderHeaders
where s.SalesOrderID == orderID
select s;
foreach (SalesOrderHeader sale in salesInfo)
{
Console.WriteLine("OrderID: {0}, Total due: {1}", sale.SalesOrderID, sale.TotalDue);
}
}
}
Function MethodParameterExample(ByVal orderID As Integer)
Using context As New AdventureWorksEntities()
Dim salesInfo = _
From s In context.SalesOrderHeaders _
Where s.SalesOrderID = orderID _
Select s
Console.WriteLine("Sales order info:")
For Each sale As SalesOrderHeader In salesInfo
Console.WriteLine("OrderID: {0}, Total due: {1}", sale.SalesOrderID, sale.TotalDue)
Next
End Using
End Function
İstemcide Sabit Değerleri Tür Dönüştürme
null'den bir CLR türüne atama, istemcide yürütülür.
IQueryable<Contact> query =
from c in context.Contacts
where c.EmailAddress == (string)null
select c;
Dim query = _
From c In context.Contacts _
Where c.EmailAddress = CType(Nothing, String) _
Select c
Null atanabilir Decimalgibi bir türe dönüştürme, istemcide yürütülür:
var weight = (decimal?)23.77;
IQueryable<Product> query =
from product in context.Products
where product.Weight == weight
select product;
Dim weight = CType(23.77, Decimal?)
Dim query = _
From product In context.Products _
Where product.Weight = weight _
Select product
Sabitler için Oluşturucular
Kavramsal model türlerine eşlenebilen yeni CLR türleri istemcide yürütülür:
var weight = new decimal(23.77);
IQueryable<Product> query =
from product in context.Products
where product.Weight == weight
select product;
Dim weight = New Decimal(23.77)
Dim query = _
From product In context.Products _
Where product.Weight = weight _
Select product
Yeni diziler ayrıca istemcide çalıştırılır.
İstisnaları Saklama
Sorgu yürütme sırasında karşılaşılan tüm depo hataları istemciye geçirilir ve eşlenmez veya işlenmez.
Depolama Yapılandırması
Sorgu depoda yürütüldüğünde, depo yapılandırması tüm istemci davranışlarını geçersiz kılar ve tüm işlemler ve ifadeler için depo semantik kuralları uygulanır. Bu, CLR ile depolama yürütmesi arasında null karşılaştırmalar, GUID sıralaması, hassas olmayan veri türleri (kayan nokta türleri veya DateTimegibi) ve dize işlemleri içeren işlemlerin duyarlığı ve doğruluğu gibi alanlarda davranışta farka neden olabilir. Sorgu sonuçlarını incelerken bunu göz önünde bulundurmak önemlidir.
Örneğin, CLR ile SQL Server arasındaki davranış farklılıkları şunlardır:
SQL Server GUID'leri CLR'den farklı bir şekilde sipariş eder.
SQL Server'da Decimal türüyle ilgilenirken sonuç duyarlılığında farklılıklar da olabilir. Bunun nedeni SQL Server ondalık türünün sabit duyarlık gereksinimleridir. Örneğin, istemcideki bellekte 0,0, 0,0 ve 1,0 değerlerinin ortalaması 0,3333333333333333333333333333 Decimal iken, depoda 0,333333'tür (SQL Server'ın ondalık türü için varsayılan duyarlığı temel alır).
Bazı dize karşılaştırma işlemleri de SQL Server'da CLR'ye göre farklı işlenir. Dize karşılaştırma davranışı, sunucudaki harmanlama ayarlarına bağlıdır.
LINQ to Entities sorgusuna dahil edilen işlev veya yöntem çağrıları, Entity Framework'teki kurallı işlevlerle eşlenir ve daha sonra Transact-SQL çevrilir ve SQL Server veritabanında yürütülür. Bu eşlenen işlevlerin sergilendiği davranışın temel sınıf kitaplıklarındaki uygulamadan farklı olabileceği durumlar vardır. Örneğin, parametre olarak boş bir dizeyle Contains, StartsWith ve EndsWith yöntemlerini çağırmak, CLR'de yürütüldüğünde
true, ancak SQL Server'da yürütüldüğündefalsedöndürecektir. EndsWith SQL Server iki dizeyi yalnızca sondaki boşlukta farklıysa eşit olarak kabul ettiğinden, CLR bunların eşit olmadığını düşündüğü için yöntemi farklı sonuçlar da döndürebilir. Bu, aşağıdaki örnekte gösterilmiştir:
using (AdventureWorksEntities context = new AdventureWorksEntities())
{
IQueryable<string> query = from p in context.Products
where p.Name == "Reflector"
select p.Name;
IEnumerable<bool> q = query.Select(c => c.EndsWith("Reflector "));
Console.WriteLine("LINQ to Entities returns: " + q.First());
Console.WriteLine("CLR returns: " + "Reflector".EndsWith("Reflector "));
}
Using context As New AdventureWorksEntities()
Dim query = _
From p In context.Products _
Where p.Name = "Reflector" _
Select p.Name
Dim q = _
query.Select(Function(c) c.EndsWith("Reflector "))
Console.WriteLine("LINQ to Entities returns: " & q.First())
Console.WriteLine("CLR returns: " & "Reflector".EndsWith("Reflector "))
End Using