Поделиться через


Практическое руководство. Вызов пользовательских функций базы данных

В этом разделе описывается, как вызывать пользовательские функции, определенные в базе данных из запросов LINQ to Entity.

Функции базы данных, вызываемые из запросов LINQ to Entity, выполняются в базе данных. Выполнение функций в базе данных может повысить производительность приложения.

Приведенная ниже процедура содержит высокоуровневую структуру для вызова пользовательской функции базы данных. Приведенный ниже пример содержит дополнительные сведения о шагах, описанных в процедуре.

Вызов пользовательских функций, определенных в базе данных

  1. Создайте пользовательскую функцию в базе данных.

    Дополнительные сведения о создании пользовательских функций в SQL Server см. в разделе CREATE FUNCTION (Transact-SQL).

  2. Объявите функцию в языке определения схемы хранилища (SSDL) файла edmx. Имя функции должно совпадать с именем функции, объявленной в базе данных.

    Дополнительные сведения см. в элементе функции (SSDL).

  3. Добавьте соответствующий метод в класс в коде приложения и примените EdmFunctionAttribute к методу Обратите внимание, что параметры NamespaceName и FunctionName атрибута — это имя пространства имен концептуальной модели и имя функции в концептуальной модели соответственно. Разрешение имен функции для LINQ чувствительно к регистру.

  4. Вызовите метод в запросе LINQ to Entities.

Пример 1

В следующем примере показано, как вызвать пользовательскую функцию базы данных из запроса LINQ to Entities. В примере используется модель Школа. Дополнительные сведения о модели школы см. в разделах Создание учебной базы данных и Генерация файла .edmx для школы.

Следующий код добавляет функцию AvgStudentGrade в пример базы данных School.

Примечание.

Действия по вызову пользовательской функции базы данных одинаковы независимо от сервера базы данных. Однако приведенный ниже код предназначен для создания функции в базе данных 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($"{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

См. также