Практическое руководство. Вызов настраиваемых функций базы данных
В данном разделе описаны процедуры вызова пользовательских функций, определенных в базе данных, из запросов LINQ to Entities.
Функции базы данных, вызываемые в запросах LINQ to Entities, выполняются в базе данных. При выполнении функций в базе данных может увеличиться производительность приложений.
Процедура, приведенная ниже, обеспечивает высокоуровневую структуру вызова пользовательской функции базы данных. В следующем примере подробно описаны шаги данной процедуры.
Вызов пользовательских функций, определенных в базе данных.
Создайте пользовательскую функцию в базе данных.
Дополнительные сведения о создании пользовательских функций в SQL Server см. в статье CREATE FUNCTION (Transact-SQL).
Объявите функцию на языке SSDL в EDMX-файле. Имя функции должно совпадать с именем функции, объявленной в базе данных.
Дополнительные сведения см. в разделе "Элемент функции ( SSDL)".
Добавьте соответствующий метод к классу в коде приложения и примените EdmFunctionAttribute к этому методу. Обратите внимание, что параметры атрибута NamespaceName и FunctionName представляют собой имя пространства имен концептуальной модели и имя функции концептуальной модели соответственно. При разрешении имени функции для LINQ учитывается регистр.
Вызовите метод в запросе LINQ to Entities.
Пример 1
В следующем примере показываются процедуры вызова пользовательской функции базы данных из запроса LINQ to Entities. В этом примере используется модель School. Сведения о модели school см. в разделе "Создание учебной образца базы данных " и создание файла edmx для школы.
Следующий код добавляет функцию AvgStudentGrade
в образец базы данных.
Примечание.
Шаги вызова пользовательской функции базы данных одинаковы, независимо от сервера базы данных. Однако следующий код предназначен специально для создания функции в базе данных SQL Server. Код для создания пользовательской функции на других серверах баз данных может отличаться.
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
Пример 2
Затем объявите функцию в языке определения схемы хранилища (SSDL) файла edmx . Следующий код объявляет функцию AvgStudentGrade
в SSDL:
<Function Name="AvgStudentGrade" ReturnType="decimal" Schema="dbo" >
<Parameter Name="studentId" Mode="In" Type="int" />
</Function>
Пример 3
Теперь создайте метод и сопоставите его с функцией, объявленной в SSDL. Метод в следующем классе сопоставляется с функцией, определенной на языке SSDL (выше) с помощью EdmFunctionAttribute. При вызове этого метода в базе данных выполняется соответствующая функция.
[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
Пример 4
Наконец, вызовите метод в запросе LINQ to Entities. Следующий код отображает в консоли фамилии студентов и средние баллы:
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