如何:调用自定义数据库函数

本主题介绍如何从 LINQ to Entities 查询中调用在数据库中定义的自定义函数。

从 LINQ to Entities 查询中调用的数据库函数在数据库中执行。 在数据库中执行函数可以改进应用程序性能。

下面的过程高度概括了有关调用自定义数据库函数的信息。 后面的示例提供了有关该过程中各个步骤的更多详细信息。

调用在数据库中定义的自定义函数

  1. 在数据库中创建自定义函数。

    有关在 SQL Server 中创建自定义函数的更多信息,请参阅 CREATE FUNCTION (Transact-SQL)

  2. 在您的 .edmx 文件的存储架构定义语言 (SSDL) 中声明一个函数。 该函数的名称必须与在数据库中声明的函数的名称相同。

    有关详细信息,请参阅函数元素 (SSDL)

  3. 将相应的方法添加到应用程序代码中的类,并将 EdmFunctionAttribute 应用于该方法。注意,该特性的 NamespaceNameFunctionName 参数分别是概念模型的命名空间名称和概念模型中的函数名称。 LINQ 的函数名称解析区分大小写。

  4. 在 LINQ to Entities 查询中调用此方法。

示例 1

下面的示例演示如何从 LINQ to Entities 查询中调用自定义数据库函数。 本示例使用 School 模型。 有关 School 模型的信息,请参阅创建 School 示例数据库生成 School .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

接下来,在 .edmx 文件的存储架构定义语言 (SSDL) 中声明一个函数。 下面的代码在 SSDL 中声明 AvgStudentGrade 函数:

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

示例 3

现在创建一个方法,并将其映射到在 SSDL 中声明的函数。 通过使用 EdmFunctionAttribute 将以下类中的方法映射到在 SSDL 中定义的函数(上述)。 调用此方法时,将执行数据库中相应的函数。

[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

请参阅