Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Quando si utilizza un'applicazione che esegue molte volte query strutturalmente simili in Entity Framework, è spesso possibile migliorare le prestazioni compilando la query una volta ed eseguendola più volte con parametri diversi. Un'applicazione potrebbe ad esempio essere utilizzata per recuperare tutti i clienti di una determinata città, specificata in fase di esecuzione dall'utente in un modulo. In LINQ to Entities è supportato l'utilizzo di query compilate per questo scopo.
La classe CompiledQuery consente di compilare e memorizzare nella cache le query da riutilizzare. A livello concettuale questa classe contiene un metodo Compile con diversi overload. Chiamare il metodo Compile per creare un nuovo delegato che rappresenti la query compilata. I metodi Compile forniti con un oggetto ObjectContext e altri valori per i parametri producono un risultato, ad esempio un'istanza di IQueryable. La query viene convertita e memorizzata nella cache quando il delegato viene richiamato per la prima volta.
L'espressione di query LINQ to Entities compilata dal metodo Compile è rappresentata da uno dei delegati Func generici, ad esempio Func. L'espressione di query può incapsulare al massimo un parametro ObjectContext, un parametro restituito e tre parametri di query. Se sono richiesti più di tre parametri di query, è possibile creare una struttura le cui proprietà rappresentino tali parametri. È possibile quindi utilizzare le proprietà sulla struttura nell'espressione di query dopo averle impostate.
Esempio
Nell'esempio seguente viene compilata e quindi richiamata una query che accetta un parametro di input Decimal e restituisce una sequenza di ordini in cui il totale dovuto è maggiore o uguale a 200,00 dollari:
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.SalesOrderHeader _
Where (order.TotalDue >= total) _
Select order)
Sub CompiledQuery2()
Using AWEntities As New AdventureWorksEntities()
Dim totalDue As Decimal = 200.0
Dim orders As IQueryable(Of SalesOrderHeader) = s_compQuery2.Invoke(AWEntities, 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
static readonly Func<AdventureWorksEntities, Decimal, IQueryable<SalesOrderHeader>> s_compiledQuery2 =
CompiledQuery.Compile<AdventureWorksEntities, Decimal, IQueryable<SalesOrderHeader>>(
(ctx, total) => from order in ctx.SalesOrderHeader
where order.TotalDue >= total
select order);
static void CompiledQuery2()
{
using (AdventureWorksEntities AWEntities = new AdventureWorksEntities())
{
Decimal totalDue = 200.00M;
IQueryable<SalesOrderHeader> orders = s_compiledQuery2.Invoke(AWEntities, totalDue);
foreach (SalesOrderHeader order in orders)
{
Console.WriteLine("ID: {0} Order date: {1} Total due: {2}",
order.SalesOrderID,
order.OrderDate,
order.TotalDue);
}
}
}
Esempio
Nell'esempio seguente viene compilata e quindi richiamata una query che restituisce un'istanza di ObjectQuery:
ReadOnly s_compQuery1 As Func(Of AdventureWorksEntities, ObjectQuery(Of SalesOrderHeader)) = _
CompiledQuery.Compile(Of AdventureWorksEntities, ObjectQuery(Of SalesOrderHeader))( _
Function(ctx) ctx.SalesOrderHeader)
Sub CompiledQuery1_MQ()
Using AWEntities As New AdventureWorksEntities()
Dim orders As ObjectQuery(Of SalesOrderHeader) = s_compQuery1.Invoke(AWEntities)
For Each order In orders
Console.WriteLine(order.SalesOrderID)
Next
End Using
End Sub
static readonly Func<AdventureWorksEntities, ObjectQuery<SalesOrderHeader>> s_compiledQuery1 =
CompiledQuery.Compile<AdventureWorksEntities, ObjectQuery<SalesOrderHeader>>(
ctx => ctx.SalesOrderHeader);
static void CompiledQuery1_MQ()
{
using (AdventureWorksEntities AWEntities = new AdventureWorksEntities())
{
IQueryable<SalesOrderHeader> orders = s_compiledQuery1.Invoke(AWEntities);
foreach (SalesOrderHeader order in orders)
Console.WriteLine(order.SalesOrderID);
}
}
Esempio
Nell'esempio seguente viene compilata e quindi richiamata una query che restituisce la media del prezzo di listino dei prodotti come valore Decimal:
Using AWEntities As New AdventureWorksEntities()
Dim compQuery = CompiledQuery.Compile(Of AdventureWorksEntities, Decimal)( _
Function(ctx) ctx.Product.Average(Function(Product) Product.ListPrice))
Dim averageProductPrice As Decimal = compQuery.Invoke(AWEntities)
Console.WriteLine("The average of the product list prices is $: {0}", averageProductPrice)
End Using
static readonly Func<AdventureWorksEntities, Decimal> s_compiledQuery3MQ = CompiledQuery.Compile<AdventureWorksEntities, Decimal>(
ctx => ctx.Product.Average(product => product.ListPrice));
static void CompiledQuery3_MQ()
{
using (AdventureWorksEntities AWEntities = new AdventureWorksEntities())
{
Decimal averageProductPrice = s_compiledQuery3MQ.Invoke(AWEntities);
Console.WriteLine("The average of the product list prices is $: {0}", averageProductPrice);
}
}
Esempio
Nell'esempio seguente viene compilata e quindi richiamata una query che accetta un parametro di input String e restituisce un oggetto Contact il cui indirizzo di posta elettronica inizia con la stringa specificata:
Using AWEntities As New AdventureWorksEntities()
Dim compQuery = CompiledQuery.Compile(Of AdventureWorksEntities, String, Contact)( _
Function(ctx, name) ctx.Contact.First(Function(contact) contact.EmailAddress.StartsWith(name)))
Dim contactName As String = "caroline"
Dim foundContact As Contact = compQuery.Invoke(AWEntities, contactName)
Console.WriteLine("An email address starting with 'caroline': {0}", _
foundContact.EmailAddress)
End Using
static readonly Func<AdventureWorksEntities, string, Contact> s_compiledQuery4MQ =
CompiledQuery.Compile<AdventureWorksEntities, string, Contact>(
(ctx, name) => ctx.Contact.First(contact => contact.EmailAddress.StartsWith(name)));
static void CompiledQuery4_MQ()
{
using (AdventureWorksEntities AWEntities = new AdventureWorksEntities())
{
string contactName = "caroline";
Contact foundContact = s_compiledQuery4MQ.Invoke(AWEntities, contactName);
Console.WriteLine("An email address starting with 'caroline': {0}",
foundContact.EmailAddress);
}
}
Esempio
Nell'esempio seguente viene compilata e quindi richiamata una query che accetta parametri di input DateTime e Decimal e restituisce una sequenza di ordini in cui la data di ordine è successiva all'8 marzo 2003 e il totale dovuto è inferiore a 300,00 dollari:
ReadOnly s_compQuery5 = _
CompiledQuery.Compile(Of AdventureWorksEntities, DateTime, Decimal, IQueryable(Of SalesOrderHeader))( _
Function(ctx, orderDate, totalDue) From product In ctx.SalesOrderHeader _
Where Product.OrderDate > orderDate _
And Product.TotalDue < totalDue _
Order By Product.OrderDate _
Select Product)
Sub CompiledQuery5()
Using AWEntities 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(AWEntities, 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
static readonly Func<AdventureWorksEntities, DateTime, Decimal, IQueryable<SalesOrderHeader>> s_compiledQuery5 =
CompiledQuery.Compile<AdventureWorksEntities, DateTime, Decimal, IQueryable<SalesOrderHeader>>(
(ctx, orderDate, totalDue) => from product in ctx.SalesOrderHeader
where product.OrderDate > orderDate
&& product.TotalDue < totalDue
orderby product.OrderDate
select product);
static void CompiledQuery5()
{
using (AdventureWorksEntities AWEntities = new AdventureWorksEntities())
{
DateTime date = new DateTime(2003, 3, 8);
Decimal amountDue = 300.00M;
IQueryable<SalesOrderHeader> orders = s_compiledQuery5.Invoke(AWEntities, date, amountDue);
foreach (SalesOrderHeader order in orders)
{
Console.WriteLine("ID: {0} Order date: {1} Total due: {2}", order.SalesOrderID, order.OrderDate, order.TotalDue);
}
}
}
Esempio
Nell'esempio seguente viene compilata e quindi richiamata una query che accetta un parametro di input DateTime e restituisce una sequenza di ordini in cui la data di ordine è successiva all'8 marzo 2004. Questa query restituisce le informazioni sull'ordine come sequenza di tipi anonimi. I tipi anonimi vengono dedotti dal compilatore, pertanto non è possibile specificare parametri di tipo nel metodo Compile e il tipo viene definito nella query stessa.
Using AWEntities As New AdventureWorksEntities()
Dim compQuery = CompiledQuery.Compile( _
Function(ctx As AdventureWorksEntities, orderDate As DateTime) _
From order In ctx.SalesOrderHeader _
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(AWEntities, 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
using (AdventureWorksEntities AWEntities = new AdventureWorksEntities())
{
var compiledQuery = CompiledQuery.Compile((AdventureWorksEntities ctx, DateTime orderDate) =>
from order in ctx.SalesOrderHeader
where order.OrderDate > orderDate
select new {order.OrderDate, order.SalesOrderID, order.TotalDue});
DateTime date = new DateTime(2004, 3, 8);
var results = compiledQuery.Invoke(AWEntities, date);
foreach (var order in results)
{
Console.WriteLine("ID: {0} Order date: {1} Total due: {2}", order.SalesOrderID, order.OrderDate, order.TotalDue);
}
}
Esempio
Nell'esempio seguente viene compilata e quindi richiamata una query che accetta un parametro di input di una struttura definita dall'utente e restituisce una sequenza di ordini La struttura definisce i parametri di query della data di inizio, della data di fine e del totale dovuto e la query restituisce gli ordini inviati tra il 3 e l'8 marzo 2003 con un totale dovuto maggiore di 700.00 dollari.
ReadOnly s_compQuery = CompiledQuery.Compile(Of AdventureWorksEntities, MyParams, IQueryable(Of SalesOrderHeader))( _
Function(ctx, mySearchParams) _
From sale In ctx.SalesOrderHeader _
Where sale.ShipDate > mySearchParams.startDate _
And sale.ShipDate < mySearchParams.endDate _
And sale.TotalDue > mySearchParams.totalDue _
Select sale)
Sub CompiledQuery7()
Using AWEntities 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(AWEntities, 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
static Func<AdventureWorksEntities, MyParams, IQueryable<SalesOrderHeader>> s_compiledQuery =
CompiledQuery.Compile<AdventureWorksEntities, MyParams, IQueryable<SalesOrderHeader>>(
(ctx, myparams) => from sale in ctx.SalesOrderHeader
where sale.ShipDate > myparams.startDate && sale.ShipDate < myparams.endDate
&& sale.TotalDue > myparams.totalDue
select sale);
static void CompiledQuery7()
{
using (AdventureWorksEntities AWEntities = 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(AWEntities, 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);
}
}
}
La struttura che definisce i parametri di query:
Public Structure MyParams
Public startDate As DateTime
Public endDate As DateTime
Public totalDue As Decimal
End Structure
struct MyParams
{
public DateTime startDate;
public DateTime endDate;
public decimal totalDue;
}