如何调试 CLR 数据库对象

适用范围:SQL Server

SQL Server 支持调试数据库中的 Transact-SQL 和公共语言运行库 (CLR) 对象。 在 SQL Server 中进行调试的主要特点一个是易于设置和使用,另一个特点是 SQL Server 调试程序与 Microsoft Visual Studio 调试程序集成。 此外,还可以跨语言进行调试。 用户可以在 Transact-SQL 中无缝地单步执行 CLR 对象,反之亦然。

SQL Server Management Studio 中的 Transact-SQL 调试器不能用于调试托管数据库对象,但可以使用 Visual Studio 中的调试器来调试对象。 Visual Studio 中的托管数据库对象调试支持所有常见的调试功能,例如,在服务器上执行的例程中的“单步执行”和“逐过程执行”语句。 调试器可以在调试过程中设置断点、检查调用堆栈、检查变量以及修改变量值。

调试权限和限制

调试是一项需要高特权的操作,因此只允许 sysadmin 固定服务器角色成员在 SQL Server 中进行调试。

调试时存在下列限制:

  • 调试 CLR 例程时仅限一次运行一个调试器实例。 此限制适用,因为当命中断点时,所有 CLR 代码执行都会冻结,并且执行不会继续,直到调试器从断点前进为止。 但可以在其他连接中继续调试 Transact-SQL。 尽管 Transact-SQL 调试不会冻结服务器上的其他执行,但会因持有锁而导致其他连接等待。

  • 无法调试现有连接,只有新连接,因为 SQL Server 需要有关客户端和调试器环境的信息,然后才能建立连接。

因此,我们建议在测试服务器上调试 Transact-SQL 和 CLR 代码,而不是在生产服务器上进行调试。

概述

在 SQL Server 中进行的调试遵循单连接模式。 调试器只能在附加到的客户端连接上检测和调试活动。 由于调试器的功能不受连接类型的限制,因此可以调试表格数据流(TDS)和 HTTP 连接。 但是,SQL Server 不允许调试现有连接。 调试支持在服务器上执行的例程中使用所有常见的调试功能。 调试程序与 SQL Server 之间的交互通过分布式组件对象模型 (COM) 进行。

有关调试托管存储过程、函数、触发器、用户定义类型和聚合的详细信息和场景,请参阅 Visual Studio 文档中的 SQL Server CLR 集成数据库调试

必须对 SQL Server 实例启用 TCP/IP 网络协议,才能使用 Visual Studio 进行远程开发、调试和开发。 有关在服务器上启用 TCP/IP 协议的详细信息,请参阅 配置客户端协议

调试步骤

按照以下步骤在 Microsoft Visual Studio 中调试 CLR 数据库对象:

  1. 打开 Microsoft Visual Studio,选择一个新的 SQL Server项目。 可以使用 Visual Studio 附带的 SQL LocalDB 实例。

  2. 创建新的 SQL CLR 类型 (C#):

    1. 在解决方案资源管理器中右键单击该项目,然后选择“添加”、“新建项...”
    2. 在“添加新项”窗口中,选择“SQL CLR C# 存储过程”、“SQL CLR C# 用户定义函数”、“SQL CLR C# 用户定义类型”、“SQL CLR C# 触发器”、“SQL CLR C# 聚合”或“类”
    3. 为新类型的源文件指定名称,然后选择“添加”
  3. 将此新类型的代码添加到文本编辑器中。 有关示例存储过程的示例代码,请参阅本文后面的“示例”部分。

  4. 添加测试该类型的脚本:

    1. 在解决方案资源管理器中,右键单击该项目节点,然后选择“添加”“脚本...”
    2. 在“添加新项”窗口中,选择“脚本(不在生成包中)”,并指定名称,例如 Test.sql。 选择“添加”按钮。
    3. 在解决方案资源管理器中,双击 节点以打开默认测试脚本源文件Test.sql
    4. 将测试脚本(将会调用要调试的代码)添加到文本编辑器中。 有关示例脚本,请参阅下一节的示例。
  5. 将一个或多个断点放在源代码中。 在要调试的函数或例程上右键单击文本编辑器中的代码行。 选择“断点”、“插入断点”。 即会添加断点,并以红色突出显示该行代码。

  6. 在“调试”菜单中,选择“开始调试”以编译、部署和测试项目。 这时会运行 Test.sql 中的测试脚本,并调用托管数据库对象。

  7. 如果在断点处出现黄色箭头(表示指令指针),代码执行将会暂停。 然后可以调试托管数据库对象:

    1. 使用“调试”菜单中的“单步切换”将指令指针前进到下一行代码
    2. 使用“局部变量”窗口观察指令指针当前突出显示的对象状态
    3. 将变量添加到“监视”窗口。 可以在调试会话中观察监视变量的状态,即使变量不在指令指针当前突出显示的代码行中也是如此。
    4. 从“调试”菜单中选择“继续”,以使指令指针前进到下一个断点或完成例程的执行(如果不再有其他断点)

示例代码

以下 C# 示例将 SQL Server 版本返回到调用方。

using System.Data.SqlClient;
using Microsoft.SqlServer.Server;

public class StoredProcedures
{
    [Microsoft.SqlServer.Server.SqlProcedure]
    public static void GetVersion()
    {
        using (var connection = new SqlConnection("context connection=true"))
        {
            connection.Open();
            var command = new SqlCommand("select @@version", connection);
            SqlContext.Pipe.ExecuteAndSend(command);
        }
    }
}

示例测试脚本

以下测试脚本演示了如何调用在上一示例中定义的 GetVersion 存储过程。

EXECUTE GetVersion;