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

Vedi anche