Procedura: archiviare e riutilizzare query
Quando si usa un'applicazione che esegue molte volte query strutturalmente simili, è spesso possibile migliorare le prestazioni compilando la query una volta ed eseguendola più volte con parametri diversi. Un'applicazione potrebbe ad esempio essere usata per recuperare tutti i clienti di una determinata città, specificata in fase di esecuzione dall'utente in un modulo. In LINQ to SQL è supportato l'uso di query compilate per questo scopo.
Nota
Questo modello di utilizzo rappresenta il metodo più comune di uso delle query compilate. Sono tuttavia possibili altri approcci. Ad esempio, le query compilate possono essere archiviate come membri statici in una classe parziale che estende il codice generato dalla finestra di progettazione.
Esempio 1
In molti scenari è possibile riutilizzare le query oltre i limiti dei thread. In questi casi l'archiviazione delle query compilate in variabili statiche è particolarmente efficace. Nell'esempio di codice riportato di seguito si presuppone una classe Queries
progettata per archiviare le query compilate e una classe Northwind che rappresenta un oggetto DataContext fortemente tipizzato.
public static Func<Northwnd, string, IQueryable<Customer>>
CustomersByCity =
CompiledQuery.Compile((Northwnd db, string city) =>
from c in db.Customers where c.City == city select c);
public static Func<Northwnd, string, IQueryable<Customer>>
CustomersById = CompiledQuery.Compile((Northwnd db,
string id) => db.Customers.Where(c => c.CustomerID == id));
Class Queries
Public Shared CustomersByCity As _
Func(Of Northwnd, String, IQueryable(Of Customer)) = _
CompiledQuery.Compile(Function(db As Northwnd, _
city As String) _
From c In db.Customers Where c.City = city Select c)
Public Shared CustomersById As _
Func(Of Northwnd, String, IQueryable(Of Customer)) = _
CompiledQuery.Compile(Function(db As Northwnd, _
id As String) _
db.Customers.Where(Function(c) c.CustomerID = id))
End Class
// The following example invokes such a compiled query in the main
// program.
public IEnumerable<Customer> GetCustomersByCity(string city)
{
var myDb = GetNorthwind();
return Queries.CustomersByCity(myDb, city);
}
' The following example invokes such a compiled query in the main
' program
Public Function GetCustomersByCity(ByVal city As String) As _
IEnumerable(Of Customer)
Dim myDb = GetNorthwind()
Return Queries.CustomersByCity(myDb, city)
End Function
Esempio 2
Attualmente non è possibile archiviare in variabili statiche le query che restituiscono un tipo anonimo, perché il tipo non dispone di un nome da fornire come argomento generico. Nell'esempio riportato di seguito viene descritto come risolvere questo problema creando un tipo in grado di rappresentare il risultato, quindi utilizzandolo come argomento generico.
class SimpleCustomer
{
public string ContactName { get; set; }
}
class Queries2
{
public static Func<Northwnd, string, IEnumerable<SimpleCustomer>> CustomersByCity =
CompiledQuery.Compile<Northwnd, string, IEnumerable<SimpleCustomer>>(
(Northwnd db, string city) =>
from c in db.Customers
where c.City == city
select new SimpleCustomer { ContactName = c.ContactName });
}
Class SimpleCustomer
Private _ContactName As String
Public Property ContactName() As String
Get
Return _ContactName
End Get
Set(ByVal value As String)
_ContactName = value
End Set
End Property
End Class
Class Queries2
Public Shared CustomersByCity As Func(Of Northwnd, String, IEnumerable(Of SimpleCustomer)) = _
CompiledQuery.Compile(Of Northwnd, String, IEnumerable(Of SimpleCustomer))( _
Function(db As Northwnd, city As String) _
From c In db.Customers _
Where c.City = city _
Select New SimpleCustomer With {.ContactName = c.ContactName})
End Class