Procedura: chiamare funzioni di database personalizzate

In questo argomento viene descritto come chiamare funzioni personalizzate definite nel database dall'interno di query LINQ to Entities.

Le funzioni di database che sono chiamate dalle query LINQ to Entities vengono eseguite nel database. L'esecuzione di funzioni nel database può migliorare le prestazioni dell'applicazione.

La procedura descritta di seguito fornisce una struttura di alto livello per la chiamata di una funzione di database personalizzata. Nell'esempio che segue vengono forniti dettagli aggiuntivi sui passaggi della procedura.

Per chiamare funzioni personalizzate definite nel database

  1. Creare una funzione personalizzata nel database.

    Per altre informazioni sulla creazione di funzioni personalizzate in SQL Server, vedere CREATE FUNCTION (Transact-SQL).

  2. Dichiarare una funzione nel linguaggio Store Schema Definition Language (SSDL) del file .edmx. Il nome della funzione deve essere identico a quello della funzione dichiarata nel database.

    Per altre informazioni, vedere Elemento Function (SSDL).

  3. Aggiungere un metodo corrispondente a una classe nel codice dell'applicazione e applicare un EdmFunctionAttribute al metodo. Si noti che i parametri NamespaceName e FunctionName dell'attributo sono rispettivamente il nome dello spazio dei nomi del modello concettuale e il nome della funzione nel modello concettuale. La risoluzione del nome della funzione per LINQ rileva la distinzione tra maiuscole e minuscole.

  4. Chiamare il metodo in una query LINQ to Entities.

Esempio 1

Nell'esempio seguente viene mostrato come chiamare una funzione di database personalizzata dall'interno una query LINQ to Entities. Nell'esempio viene usato il modello School. Per informazioni sul modello School, vedere Creazione del database di esempio dell'istituto di istruzione e Generazione del file con estensione edmx dell'istituto di istruzione.

Nel codice seguente viene aggiunta la funzione AvgStudentGrade al database di esempio School.

Nota

I passaggi per la chiamata di una funzione di database personalizzata sono gli stessi indipendentemente dal server database. Tuttavia, il codice seguente è specifico per la creazione di una funzione in un database SQL Server. Il codice per la creazione di una funzione personalizzata in altri server database potrebbe essere differente.

USE [School]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION [dbo].[AvgStudentGrade](@studentId INT)
RETURNS DECIMAL(3,2)
AS
    BEGIN
    DECLARE @avg DECIMAL(3,2);
    SELECT @avg = avg(Grade) FROM StudentGrade WHERE StudentID = @studentId;

    RETURN @avg;
END

Esempio 2

Dichiarare quindi una funzione nel linguaggio SSDL (Store Schema Definition Language) del file con estensione edmx . Il codice seguente dichiara la funzione AvgStudentGrade in SSDL:

<Function Name="AvgStudentGrade" ReturnType="decimal" Schema="dbo" >
  <Parameter Name="studentId" Mode="In" Type="int" />
</Function>

Esempio 3

Creare ora un metodo ed eseguire il mapping alla funzione dichiarata nel linguaggio SSDL. Il metodo nella classe seguente viene mappato alla funzione definita in SSDL (sopra) tramite un oggetto EdmFunctionAttribute. Quando il metodo viene chiamato, viene eseguita la funzione corrispondente nel database.

[EdmFunction("SchoolModel.Store", "AvgStudentGrade")]
public static decimal? AvgStudentGrade(int studentId)
{
    throw new NotSupportedException("Direct calls are not supported.");
}
<EdmFunction("SchoolModel.Store", "AvgStudentGrade")>
Public Function AvgStudentGrade(ByVal studentId As Integer) _
    As Nullable(Of Decimal)
    Throw New NotSupportedException("Direct calls are not supported.")
End Function

Esempio 4

Chiamare infine il metodo in una query LINQ to Entities. Nel codice seguente vengono visualizzati i cognomi di studenti e le medie dei voti alla console:

using (SchoolEntities context = new SchoolEntities())
{
    var students = from s in context.People
                   where s.EnrollmentDate != null
                   select new
                   {
                       name = s.LastName,
                       avgGrade = AvgStudentGrade(s.PersonID)
                   };

    foreach (var student in students)
    {
        Console.WriteLine("{0}: {1}", student.name, student.avgGrade);
    }
}
Using context As New SchoolEntities()
    Dim students = From s In context.People _
                   Where s.EnrollmentDate IsNot Nothing _
                   Select New With {.name = s.LastName, _
                                   .avgGrade = AvgStudentGrade(s.PersonID)}

    For Each student In students
        Console.WriteLine("{0}: {1}", _
                            student.name, _
                            student.avgGrade)
    Next
End Using

Vedi anche