Bahasa
Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Setelah kueri LINQ dibuat oleh pengguna, kueri tersebut dikonversi ke pohon perintah. Pohon perintah adalah representasi kueri yang kompatibel dengan Kerangka Kerja Entitas. Pohon komando kemudian dijalankan terhadap sumber data. Pada waktu eksekusi kueri, semua ekspresi kueri (yaitu, semua komponen kueri) dievaluasi, termasuk ekspresi yang digunakan dalam materialisasi hasil.
Pada saat mana ekspresi kueri dijalankan dapat bervariasi. Kueri LINQ selalu dijalankan ketika variabel kueri diulang, bukan saat variabel kueri dibuat. Ini disebut eksekusi yang ditangguhkan. Anda juga dapat memaksa kueri untuk langsung dijalankan, yang berguna untuk pengelolaan cache hasil kueri. Ini dijelaskan nanti dalam topik ini.
Ketika kueri LINQ ke Entitas dijalankan, beberapa ekspresi dalam kueri mungkin dijalankan di server dan beberapa bagian mungkin dijalankan secara lokal pada klien. Evaluasi sisi klien dari ekspresi terjadi sebelum kueri dijalankan di server. Jika ekspresi dievaluasi pada klien, hasil evaluasi tersebut digantikan untuk ekspresi dalam kueri, dan kueri kemudian dijalankan di server. Karena kueri dijalankan pada sumber data, konfigurasi sumber data akan mengambil alih perilaku yang ditentukan dalam klien. Misalnya, penanganan nilai null dan presisi numerik bergantung pada pengaturan server. Setiap pengecualian yang dilemparkan selama eksekusi kueri di server diteruskan langsung ke klien.
Petunjuk / Saran
Untuk ringkasan operator kueri yang nyaman dalam format tabel, yang memungkinkan Anda mengidentifikasi perilaku eksekusi operator dengan cepat, lihat Klasifikasi Operator Kueri Standar dengan Cara Eksekusi (C#).
Eksekusi kueri yang ditangguhkan
Dalam kueri yang mengembalikan urutan nilai, variabel kueri itu sendiri tidak pernah menyimpan hasil kueri dan hanya menyimpan perintah kueri. Eksekusi kueri ditangguhkan hingga variabel kueri diulang dalam perulangan foreach atau For Each . Ini dikenal sebagai eksekusi yang ditangguhkan; artinya, eksekusi kueri terjadi beberapa saat setelah kueri dibuat. Ini berarti Anda bisa menjalankan kueri sesering yang Anda inginkan. Ini berguna ketika, misalnya, Anda memiliki database yang sedang diperbarui oleh aplikasi lain. Dalam aplikasi, Anda dapat membuat kueri untuk mengambil informasi terbaru dan berulang kali menjalankan kueri, mengembalikan informasi yang diperbarui setiap kali.
Eksekusi yang ditangguhkan memungkinkan beberapa kueri disatukan atau kueri diperluas. Saat kueri diperpanjang, kueri dimodifikasi untuk menyertakan operasi baru, dan pelaksanaan akhirnya akan menunjukkan perubahan tersebut. Dalam contoh berikut, kueri pertama mengembalikan semua produk. Kueri kedua memperluas yang pertama dengan menggunakan Where untuk mengembalikan semua produk berukuran "L":
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
Setelah kueri dijalankan, semua kueri berturut-turut akan menggunakan operator LINQ dalam memori. Iterasi atas variabel kueri dengan menggunakan foreach pernyataan atau For Each atau dengan memanggil salah satu operator konversi LINQ akan menyebabkan eksekusi segera. Operator konversi ini mencakup yang berikut ini: ToList, , ToArrayToLookup, dan ToDictionary.
Segera Eksekusi Kueri
Berbeda dengan eksekusi kueri yang ditangguhkan yang menghasilkan urutan nilai, kueri yang mengembalikan nilai singleton segera dijalankan. Beberapa contoh kueri singleton adalah Average, , Count, Firstdan Max. Ini langsung dijalankan karena kueri harus menghasilkan urutan untuk menghitung hasil singleton. Anda juga dapat memaksa eksekusi segera. Ini berguna saat Anda ingin menyimpan hasil kueri. Untuk memaksa eksekusi segera kueri yang tidak menghasilkan nilai singleton, Anda dapat memanggil metode ToList, metode ToDictionary, atau metode ToArray pada kueri atau variabel kueri. Contoh berikut menggunakan metode ToArray untuk langsung mengevaluasi sekuens ke dalam array.
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
Anda juga dapat memaksa jalannya eksekusi dengan meletakkan foreach atau For Each loop segera setelah ekspresi kueri, tetapi dengan memanggil ToList atau ToArray, Anda dapat menyimpan semua data dalam satu objek koleksi.
Eksekusi Toko
Secara umum, ekspresi dalam LINQ untuk Entitas dievaluasi di server, dan diharapkan perilaku ekspresi mengikuti semantik dari sumber data, bukan Common Language Runtime (CLR). Namun, ada pengecualian untuk ini, seperti ketika ekspresi dijalankan pada klien. Ini dapat menyebabkan hasil yang tidak terduga, misalnya ketika server dan klien berada di zona waktu yang berbeda.
Beberapa ekspresi dalam kueri mungkin dijalankan pada klien. Secara umum, sebagian besar eksekusi kueri diharapkan terjadi di server. Selain metode yang dijalankan terhadap elemen kueri yang dipetakan ke sumber data, sering ada ekspresi dalam kueri yang dapat dijalankan secara lokal. Eksekusi lokal ekspresi kueri menghasilkan nilai yang dapat digunakan dalam eksekusi kueri atau konstruksi hasil.
Operasi tertentu selalu dijalankan pada klien, seperti pengikatan nilai, sub ekspresi, sub kueri dari penutupan, dan materialisasi objek ke dalam hasil kueri. Efek bersih dari ini adalah bahwa elemen-elemen ini (misalnya, nilai parameter) tidak dapat diperbarui selama eksekusi. Tipe anonim dapat dibangun secara langsung pada sumber data, tetapi tidak boleh diasumsikan akan melakukannya. Pengelompokan sebaris juga dapat dibangun di sumber data, tetapi ini tidak boleh diasumsikan dalam setiap instans. Secara umum, yang terbaik adalah tidak membuat asumsi tentang apa yang dibangun di server.
Bagian ini menjelaskan skenario di mana kode dijalankan secara lokal pada klien. Untuk informasi selengkapnya tentang jenis ekspresi mana yang dijalankan secara lokal, lihat Ekspresi di LINQ ke Kueri Entitas.
Literal dan Parameter
Variabel lokal, seperti orderID variabel dalam contoh berikut, dievaluasi pada klien.
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
Parameter metode juga dievaluasi pada klien. Parameter orderID yang diteruskan ke MethodParameterExample metode , di bawah ini, adalah contoh.
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
Konversi Literal pada Platform Klien
Pengecoran dari null ke tipe CLR dilakukan di sisi klien.
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
Transmisi ke jenis, seperti nullable Decimal, dijalankan pada klien:
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
Konstruktor untuk Literal
Jenis CLR baru yang dapat dipetakan ke jenis model konseptual dijalankan pada klien:
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
Array baru juga dijalankan pada klien.
Simpan Pengecualian
Setiap kesalahan penyimpanan data yang ditemui selama eksekusi kueri diteruskan ke klien, dan tidak dipetakan ataupun ditangani.
Konfigurasi Toko
Saat kueri dieksekusi di toko, konfigurasi toko mengambil alih semua perilaku klien, dan semantik toko dinyatakan untuk semua operasi dan ekspresi. Hal ini dapat mengakibatkan perbedaan perilaku antara CLR dan eksekusi penyimpanan di area seperti perbandingan null, pengurutan GUID, presisi dan akurasi operasi yang melibatkan jenis data yang tidak tepat (seperti jenis titik mengambang atau DateTime), dan operasi string. Penting untuk mengingat hal ini saat memeriksa hasil kueri.
Misalnya, berikut ini adalah beberapa perbedaan perilaku antara CLR dan SQL Server:
SQL Server mengurutkan GUID secara berbeda dibandingkan CLR.
Mungkin juga ada perbedaan dalam presisi hasil saat berhadapan dengan jenis Desimal di SQL Server. Hal ini disebabkan oleh persyaratan presisi tetap dari jenis desimal SQL Server. Misalnya, rata-rata Decimal angka 0,0, 0,0, dan 1,0 adalah 0,3333333333333333333333333333 dalam memori pada klien, tetapi 0,333333 di dalam penyimpanan (berdasarkan presisi bawaan untuk jenis desimal SQL Server).
Beberapa operasi perbandingan string juga ditangani secara berbeda di SQL Server daripada di CLR. Perilaku perbandingan string tergantung pada pengaturan kolate di server.
Panggilan fungsi atau metode, ketika disertakan dalam kueri LINQ ke Entitas, dipetakan ke fungsi kanonis dalam Kerangka Kerja Entitas, yang kemudian diterjemahkan ke Transact-SQL dan dijalankan pada database SQL Server. Ada beberapa kasus ketika perilaku yang dipamerkan fungsi yang dipetakan ini mungkin berbeda dari implementasi di pustaka kelas dasar. Misalnya, memanggil Containsmetode , StartsWith, dan EndsWith dengan string kosong sebagai parameter akan kembali
trueketika dijalankan di CLR, tetapi akan kembalifalseketika dijalankan di SQL Server. Metode ini EndsWith juga dapat mengembalikan hasil yang berbeda karena SQL Server menganggap dua string sama jika hanya berbeda dalam spasi putih berikutnya, sedangkan CLR menganggapnya tidak sama. Ini diilustrasikan oleh contoh berikut:
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