Derlenmiş sorgular (LINQ to Entities)
Entity Framework'te yapısal olarak benzer sorguları birçok kez yürüten bir uygulamanız olduğunda, sorguyu bir kez derleyip farklı parametrelerle birkaç kez yürüterek performansı sık sık artırabilirsiniz. Örneğin, bir uygulamanın belirli bir şehirdeki tüm müşterileri alması gerekebilir; şehir, kullanıcı tarafından çalışma zamanında bir formda belirtilir. LINQ to Entities, bu amaçla derlenmiş sorguların kullanılmasını destekler.
.NET Framework 4.5'den başlayarak LINQ sorguları otomatik olarak önbelleğe alınır. Ancak, daha sonraki yürütmelerde bu maliyeti azaltmak için derlenmiş LINQ sorgularını kullanmaya devam edebilirsiniz ve derlenmiş sorgular otomatik olarak önbelleğe alınan LINQ sorgularından daha verimli olabilir. işleci bellek içi koleksiyonlara uygulayan Enumerable.Contains
LINQ to Entities sorguları otomatik olarak önbelleğe alınmaz. Ayrıca, derlenmiş LINQ sorgularında bellek içi koleksiyonları parametreleştirmeye izin verilmez.
sınıfı, CompiledQuery yeniden kullanmak üzere sorguların derlenmesini ve önbelleğe alınmasını sağlar. Kavramsal olarak, bu sınıf birkaç aşırı yükleme ile bir CompiledQuery's Compile
yöntemi içerir. Derlenen sorguyu Compile
temsil eden yeni bir temsilci oluşturmak için yöntemini çağırın. Compile
ve parametre değerleriyle sağlanan ObjectContext yöntemler, bazı sonuçlar (örneğin, bir örnek) üreten bir IQueryable<T> temsilci döndürür. Sorgu yalnızca ilk yürütme sırasında bir kez derlenmiş olur. Derleme sırasında sorgu için ayarlanan birleştirme seçenekleri daha sonra değiştirilemez. Sorgu derlendiğinde yalnızca ilkel türde parametreler sağlayabilirsiniz, ancak sorgunun oluşturulan SQL'i değiştirecek bölümlerini değiştiremezsiniz. Daha fazla bilgi için bkz . EF Birleştirme Seçenekleri ve Derlenmiş Sorgular.
'nin Compile
yönteminin CompiledQueryderlediği LINQ to Entities sorgu ifadesi gibi Func<T1,T2,T3,T4,TResult>genel Func
temsilcilerden biri tarafından temsil edilir. Sorgu ifadesi en fazla bir ObjectContext
parametreyi, dönüş parametresini ve 16 sorgu parametresini kapsülleyebilir. 16'dan fazla sorgu parametresi gerekiyorsa, özellikleri sorgu parametrelerini temsil eden bir yapı oluşturabilirsiniz. Ardından, özellikleri ayarladıktan sonra sorgu ifadesindeki yapıdaki özellikleri kullanabilirsiniz.
Örnek 1
Aşağıdaki örnek, giriş parametresini kabul eden bir Decimal sorguyu derleyip çağırır ve toplam ödemenin 200,00 TL'den büyük veya buna eşit olduğu bir sipariş dizisi döndürür:
static readonly Func<AdventureWorksEntities, Decimal, IQueryable<SalesOrderHeader>> s_compiledQuery2 =
CompiledQuery.Compile<AdventureWorksEntities, Decimal, IQueryable<SalesOrderHeader>>(
(ctx, total) => from order in ctx.SalesOrderHeaders
where order.TotalDue >= total
select order);
static void CompiledQuery2()
{
using (AdventureWorksEntities context = new AdventureWorksEntities())
{
Decimal totalDue = 200.00M;
IQueryable<SalesOrderHeader> orders = s_compiledQuery2.Invoke(context, totalDue);
foreach (SalesOrderHeader order in orders)
{
Console.WriteLine("ID: {0} Order date: {1} Total due: {2}",
order.SalesOrderID,
order.OrderDate,
order.TotalDue);
}
}
}
ReadOnly s_compQuery2 As Func(Of AdventureWorksEntities, Decimal, IQueryable(Of SalesOrderHeader)) = _
CompiledQuery.Compile(Of AdventureWorksEntities, Decimal, IQueryable(Of SalesOrderHeader))( _
Function(ctx As AdventureWorksEntities, total As Decimal) _
From order In ctx.SalesOrderHeaders _
Where (order.TotalDue >= total) _
Select order)
Sub CompiledQuery2()
Using context As New AdventureWorksEntities()
Dim totalDue As Decimal = 200.0
Dim orders As IQueryable(Of SalesOrderHeader) = s_compQuery2.Invoke(context, totalDue)
For Each order In orders
Console.WriteLine("ID: {0} Order date: {1} Total due: {2}", _
order.SalesOrderID, _
order.OrderDate, _
order.TotalDue)
Next
End Using
End Sub
Örnek 2
Aşağıdaki örnek, bir örneği döndüren ObjectQuery<T> bir sorguyu derleyip çağırır:
static readonly Func<AdventureWorksEntities, ObjectQuery<SalesOrderHeader>> s_compiledQuery1 =
CompiledQuery.Compile<AdventureWorksEntities, ObjectQuery<SalesOrderHeader>>(
ctx => ctx.SalesOrderHeaders);
static void CompiledQuery1_MQ()
{
using (AdventureWorksEntities context = new AdventureWorksEntities())
{
IQueryable<SalesOrderHeader> orders = s_compiledQuery1.Invoke(context);
foreach (SalesOrderHeader order in orders)
Console.WriteLine(order.SalesOrderID);
}
}
ReadOnly s_compQuery1 As Func(Of AdventureWorksEntities, ObjectQuery(Of SalesOrderHeader)) = _
CompiledQuery.Compile(Of AdventureWorksEntities, ObjectQuery(Of SalesOrderHeader))( _
Function(ctx) ctx.SalesOrderHeaders)
Sub CompiledQuery1_MQ()
Using context As New AdventureWorksEntities()
Dim orders As ObjectQuery(Of SalesOrderHeader) = s_compQuery1.Invoke(context)
For Each order In orders
Console.WriteLine(order.SalesOrderID)
Next
End Using
End Sub
Örnek 3
Aşağıdaki örnek, ürün listesi fiyatlarının ortalamasını değer olarak döndüren bir Decimal sorguyu derleyip çağırır:
static readonly Func<AdventureWorksEntities, Decimal> s_compiledQuery3MQ = CompiledQuery.Compile<AdventureWorksEntities, Decimal>(
ctx => ctx.Products.Average(product => product.ListPrice));
static void CompiledQuery3_MQ()
{
using (AdventureWorksEntities context = new AdventureWorksEntities())
{
Decimal averageProductPrice = s_compiledQuery3MQ.Invoke(context);
Console.WriteLine("The average of the product list prices is $: {0}", averageProductPrice);
}
}
Using context As New AdventureWorksEntities()
Dim compQuery = CompiledQuery.Compile(Of AdventureWorksEntities, Decimal)( _
Function(ctx) ctx.Products.Average(Function(Product) Product.ListPrice))
Dim averageProductPrice As Decimal = compQuery.Invoke(context)
Console.WriteLine("The average of the product list prices is $: {0}", averageProductPrice)
End Using
Örnek 4
Aşağıdaki örnek, giriş parametresini kabul eden bir String sorguyu derleyip çağırır ve ardından e-posta adresi belirtilen dizeyle başlayan bir Contact
sorgu döndürür:
static readonly Func<AdventureWorksEntities, string, Contact> s_compiledQuery4MQ =
CompiledQuery.Compile<AdventureWorksEntities, string, Contact>(
(ctx, name) => ctx.Contacts.First(contact => contact.EmailAddress.StartsWith(name)));
static void CompiledQuery4_MQ()
{
using (AdventureWorksEntities context = new AdventureWorksEntities())
{
string contactName = "caroline";
Contact foundContact = s_compiledQuery4MQ.Invoke(context, contactName);
Console.WriteLine("An email address starting with 'caroline': {0}",
foundContact.EmailAddress);
}
}
Using context As New AdventureWorksEntities()
Dim compQuery = CompiledQuery.Compile(Of AdventureWorksEntities, String, Contact)( _
Function(ctx, name) ctx.Contacts.First(Function(contact) contact.EmailAddress.StartsWith(name)))
Dim contactName As String = "caroline"
Dim foundContact As Contact = compQuery.Invoke(context, contactName)
Console.WriteLine("An email address starting with 'caroline': {0}", _
foundContact.EmailAddress)
End Using
Örnek 5
Aşağıdaki örnek, parametreleri kabul eden ve Decimal giriş parametrelerini kabul DateTime eden bir sorguyu derleyip çağırır ve sipariş tarihinin 8 Mart 2003'ten sonra olduğu ve toplam son tarihin 300,00 TL'den az olduğu bir sipariş dizisi döndürür:
static readonly Func<AdventureWorksEntities, DateTime, Decimal, IQueryable<SalesOrderHeader>> s_compiledQuery5 =
CompiledQuery.Compile<AdventureWorksEntities, DateTime, Decimal, IQueryable<SalesOrderHeader>>(
(ctx, orderDate, totalDue) => from product in ctx.SalesOrderHeaders
where product.OrderDate > orderDate
&& product.TotalDue < totalDue
orderby product.OrderDate
select product);
static void CompiledQuery5()
{
using (AdventureWorksEntities context = new AdventureWorksEntities())
{
DateTime date = new DateTime(2003, 3, 8);
Decimal amountDue = 300.00M;
IQueryable<SalesOrderHeader> orders = s_compiledQuery5.Invoke(context, date, amountDue);
foreach (SalesOrderHeader order in orders)
{
Console.WriteLine("ID: {0} Order date: {1} Total due: {2}", order.SalesOrderID, order.OrderDate, order.TotalDue);
}
}
}
ReadOnly s_compQuery5 = _
CompiledQuery.Compile(Of AdventureWorksEntities, DateTime, Decimal, IQueryable(Of SalesOrderHeader))( _
Function(ctx, orderDate, totalDue) From product In ctx.SalesOrderHeaders _
Where product.OrderDate > orderDate _
And product.TotalDue < totalDue _
Order By product.OrderDate _
Select product)
Sub CompiledQuery5()
Using context As New AdventureWorksEntities()
Dim orderedAfterDate As DateTime = New DateTime(2003, 3, 8)
Dim amountDue As Decimal = 300.0
Dim orders As IQueryable(Of SalesOrderHeader) = _
s_compQuery5.Invoke(context, orderedAfterDate, amountDue)
For Each order In orders
Console.WriteLine("ID: {0} Order date: {1} Total due: {2}", _
order.SalesOrderID, order.OrderDate, order.TotalDue)
Next
End Using
End Sub
Örnek 6
Aşağıdaki örnek, giriş parametresini kabul eden bir DateTime sorguyu derleyip çağırır ve sipariş tarihinin 8 Mart 2004'ten sonra olduğu bir sipariş dizisi döndürür. Bu sorgu, sipariş bilgilerini anonim türlerin dizisi olarak döndürür. Anonim türler derleyici tarafından çıkarılır, bu nedenle 's Compile
yönteminde CompiledQuerytür parametreleri belirtemezsiniz ve tür sorgunun kendisinde tanımlanır.
using (AdventureWorksEntities context = new AdventureWorksEntities())
{
var compiledQuery = CompiledQuery.Compile((AdventureWorksEntities ctx, DateTime orderDate) =>
from order in ctx.SalesOrderHeaders
where order.OrderDate > orderDate
select new {order.OrderDate, order.SalesOrderID, order.TotalDue});
DateTime date = new DateTime(2004, 3, 8);
var results = compiledQuery.Invoke(context, date);
foreach (var order in results)
{
Console.WriteLine("ID: {0} Order date: {1} Total due: {2}", order.SalesOrderID, order.OrderDate, order.TotalDue);
}
}
Using context As New AdventureWorksEntities()
Dim compQuery = CompiledQuery.Compile( _
Function(ctx As AdventureWorksEntities, orderDate As DateTime) _
From order In ctx.SalesOrderHeaders _
Where order.OrderDate > orderDate _
Select New With {order.OrderDate, order.SalesOrderID, order.TotalDue})
Dim orderedAfterDate As DateTime = New DateTime(2004, 3, 8)
Dim orders = compQuery.Invoke(context, orderedAfterDate)
For Each order In orders
Console.WriteLine("ID: {0} Order date: {1} Total due: {2}", _
order.SalesOrderID, order.OrderDate, order.TotalDue)
Next
End Using
Örnek 7
Aşağıdaki örnek, kullanıcı tanımlı yapı giriş parametresini kabul eden ve bir dizi sipariş döndüren bir sorguyu derleyip çağırır. Yapı başlangıç tarihi, bitiş tarihi ve toplam son tarih sorgu parametrelerini tanımlar ve sorgu, 3-8 Mart 2003 tarihleri arasında gönderilen siparişleri döndürür ve toplam vadesi 700,00 TL'den fazla olur.
static Func<AdventureWorksEntities, MyParams, IQueryable<SalesOrderHeader>> s_compiledQuery =
CompiledQuery.Compile<AdventureWorksEntities, MyParams, IQueryable<SalesOrderHeader>>(
(ctx, myparams) => from sale in ctx.SalesOrderHeaders
where sale.ShipDate > myparams.startDate && sale.ShipDate < myparams.endDate
&& sale.TotalDue > myparams.totalDue
select sale);
static void CompiledQuery7()
{
using (AdventureWorksEntities context = new AdventureWorksEntities())
{
MyParams myParams = new MyParams();
myParams.startDate = new DateTime(2003, 3, 3);
myParams.endDate = new DateTime(2003, 3, 8);
myParams.totalDue = 700.00M;
IQueryable<SalesOrderHeader> sales = s_compiledQuery.Invoke(context, myParams);
foreach (SalesOrderHeader sale in sales)
{
Console.WriteLine("ID: {0}", sale.SalesOrderID);
Console.WriteLine("Ship date: {0}", sale.ShipDate);
Console.WriteLine("Total due: {0}", sale.TotalDue);
}
}
}
ReadOnly s_compQuery = CompiledQuery.Compile(Of AdventureWorksEntities, MyParams, IQueryable(Of SalesOrderHeader))( _
Function(ctx, mySearchParams) _
From sale In ctx.SalesOrderHeaders _
Where sale.ShipDate > mySearchParams.startDate _
And sale.ShipDate < mySearchParams.endDate _
And sale.TotalDue > mySearchParams.totalDue _
Select sale)
Sub CompiledQuery7()
Using context As New AdventureWorksEntities()
Dim myParams As MyParams = New MyParams()
myParams.startDate = New DateTime(2003, 3, 3)
myParams.endDate = New DateTime(2003, 3, 8)
myParams.totalDue = 700.0
Dim sales = s_compQuery.Invoke(context, myParams)
For Each sale In sales
Console.WriteLine("ID: {0}", sale.SalesOrderID)
Console.WriteLine("Ship date: {0}", sale.ShipDate)
Console.WriteLine("Total due: {0}", sale.TotalDue)
Next
End Using
End Sub
Sorgu parametrelerini tanımlayan yapı:
struct MyParams
{
public DateTime startDate;
public DateTime endDate;
public decimal totalDue;
}
Public Structure MyParams
Public startDate As DateTime
Public endDate As DateTime
Public totalDue As Decimal
End Structure