数据库

位置:IT落伍者 >> 数据库 >> 浏览文章

使用 SQL Server 2005中的 CLR 集成(1)


发布日期:2019年10月25日
 
使用 SQL Server 2005中的 CLR 集成(1)

简介

Microsoft 通过宿主 Microsoft NET Framework 公共语言运行库 (CLR)SQL Server 显着地增强了数据库编程模型的功能它支持用任何 CLR 语言(特别是 Microsoft Visual C# NETMicrosoft Visual Basic NET 和 Microsoft Visual C++)编写过程触发器和函数同时它还提供了扩展数据库系统中的类型系统和聚合函数的功能方法是允许应用程序创建它们自己的数据类型和聚合函数

本白皮书从数据库应用程序开发人员的角度描述了如何最有效地利用这项技术它还将 CLR 与 SQL Server 中支持的现有编程语言(即 TransacTSQL (TSQL) 和扩展存储过程 (XP))进行了比较本白皮书不打算提供这些功能的基本参考资料SQL Server Beta Books Online 对其进行了详细介绍

本白皮书的目标读者包括数据库应用程序开发人员架构师和数据库管理员本白皮书假设读者熟悉基于 NET Framework 的编程和数据库编程

CLR 集成概述

下面简要概述了 CLR 集成执行的 SQL Server 功能以及 Visual Studio 最终发布版本如何支持这些功能

注册和执行数据库中的托管代码包括以下步骤

开发人员将托管程序编写为一组类定义将 SQL Server 内旨在用作存储过程函数或触发器(下面统称为例程)的代码编写为类的 static(或 Microsoft Visual Basic NET 中的 shared)方法将旨在用作用户定义的类型和聚合的代码编写为一个整类开发人员编译该程序并创建一个程序集

然后将此程序集上载到 SQL Server 数据库在其中使用 CREATE ASSEMBLY 数据定义语言 (DDL) 将它存储到系统目录

接着创建 TransacTSQL 对象例如例程(函数过程和触发器)类型和聚合并将其绑定到已经上载的程序集中的入口点(对例程来说是方法对类型和聚合来说是类)使用 CREATE PROCEDURE/FUNCTION/ TRIGGER/TYPE/AGGREGATE 语句来完成这一步

在创建了这些例程之后应用程序就可以像使用 TSQL 例程一样使用它们例如可以从 TSQL 查询中调用 CLR 函数从客户端应用程序或从 TSQL 批处理中调用 CLR 过程就好像它们是 TSQL 过程一样

Visual Studio Beta 支持在 SQL Server 中开发部署和调试托管代码有一种新的项目类型(称为 SQL Server 项目)它允许开发人员在 SQL Server 中开发部署和调试例程(函数过程和触发器)类型和聚合

构建和部署

SQL Server 项目提供了代码模板这使得开发人员能够轻松地开始为基于 CLR 的数据库例程类型和聚合编写代码该项目还允许添加对数据库中其他的程序集的引用在构建项目时可以将其编译成一个程序集部署此程序集可以将程序集的二进制文件上载到与该项目相关联的 SQL Server 数据库中部署操作还自动创建在数据库的程序集中定义的例程类型和聚合方法是使用在代码中定义的自定义属性(SqlProcedureSqlFunction 和 SqlTrigger 等等)它还上载与该程序集相关联的源代码和 pdb 文件(调试符号)

调试

对于任何平台来说调试都是开发人员体验的基本部分SQL Server 和 Visual Studio 为数据库编程人员提供了这些功能调试 SQL Server 对象的关键部分在于其易于安装和使用调试到运行 SQL Server 的计算机的连接在很大程度上同调试传统操作系统中运行的进程的方式一样调试器的功能不会受到客户端到服务器的连接类型的影响这样就可以调试表格数据流 (TDS) 和 HTTP 连接而且还可以跨语言进行无缝调试因此如果有一个调用 CLR 存储过程的 TSQL 存储过程调试会允许您从 TSQL 过程进入到 CLR 过程

CLR 与 TransacTSQL

现在我们进入本文的关键部分对 CLR 集成和 SQL Server 中支持的现有编程语言进行比较

TransacTSQL (TSQL) 是 SQL Server 支持的本机编程语言和大多数 SQL Server 版本一样它包含数据处理功能和数据定义功能数据处理功能一般可以分为两类查询语言(由 SELECT/INSERT/UPDATE/ DELETE 语句组成)和过程语言(WHILE赋值触发器光标等)一般来说SQL Server 中的 CLR 支持为过程语言提供了 TSQL 的替代方法

即使在 SQL Server 中引入 CLR 支持以前数据库应用程序应该尽可能多地使用查询语言这始终被认为是很重要的数据库应用程序应该利用面向集的查询处理器并且只在查询语言无法表示逻辑时才转向过程编程对于 SQL Server 中的 CLR 支持这仍然是正确的不应该使用 CLR 来编写可以用简单的 SELECT 语句表示的过程代码在 SQL Server 中增加了许多重要的功能来提高TSQL 查询语言的表达能力

递归查询遍历表中的递归层次的能力

分析函数RANK 和 ROW_NUMBER 允许排列结果集中的行

新的关联操作APPLYPIVOT 和 UNPIVOT

试图使用 CLR 功能的开发人员应该确保他们充分地利用查询语言包括 SQL Server 中的扩展在内对于在查询语言中无法以声明方式表示的逻辑他们应该考虑将 CLR 作为有效的替代办法

现在让我们看一些方案其中基于 CLR 的编程能够补充 TSQL 查询语言的表达能力通常需要在查询(可称为函数)内嵌入过程逻辑这允许许多方案例如

根据数据库表中存储的值对每行进行复杂的计算(必须用过程逻辑来表示)这可以包括将这些计算的结果发送给客户端或者使用计算来过滤发送给客户端的行集如以下示例中所示

SELECT <complexcalculation>(<columnname>)

FROM <table>

WHERE <complexcalculation>(<columnname>) =

使用过程逻辑来评估表格结果然后在 SELECT 或 DML语句的 FROM 子句中进行查询

SQL Server 引入了支持这些方案的 TSQL 函数(标量和表值)有了 SQL Server 就可以用 CLR 语言更容易地编写这样的函数并且会极大地提高它们的性能之所以编写这些函数非常容易是因为事实上编写 CLR 代码的开发人员可以利用 NET Framework API中存在的大量有用函数和类这个类/函数库比 TransacTSQL 中支持的内置函数要丰富得多此外CLR 编程语言提供了 TSQL 中所没有的丰富构造(例如数组和列表等)与 TSQL(它是一种解释语言)相比CLR 编程语言之所以具有更好的性能是因为托管代码是已编译的对于涉及算术计算字符串处理条件逻辑等的操作托管代码的性能可能要优于 TSQL 一个数量级

注对于函数几乎没有必要从函数中访问数据库外部查询已经从数据库中检索到数据值并且将其作为参数传递给函数这是 CLR 的优势在计算性任务上比 TSQL 更胜一筹

从 CLR 中访问数据

现在让我们从编程模型和性能这两个方面看看如何用 CLR 来编写访问数据库的业务逻辑

编程模型

使用 TSQL只是在过程代码内部嵌入查询语言语句 (SELECT/INSERT/UPDATE/ DELETE)通过托管代码可以使用 SQL Server 托管提供程序来实现 Microsoft ADONET 数据访问 API(也称为 inproc ADONET)使用这种方法可以将查询语言语句(SELECT 和 DML 语句)作为动态字符串嵌入并且将其作为参数传递给 ADONET API与 TSQL 的静态方法相比过程代码内嵌入的 SQL 语句的基于动态 API 的特性是它们在编程模型上的主要区别不利的是inproc ADONET 模型会产生比 TSQL 更冗长的代码此外因为 SQL 语句是动态字符串所以在执行之前不在语法或语义上进行编译和验证有利的是带有 ADONET 的数据库编程模型与客户端或中间层中使用的模型相似因而更容易在各层之间移动代码和利用现有的技术

此外在基于 TSQL 和基于 CLR 的编程模型中使用的都是同一 SQL 查询语言不同之处在于过程部分注意到这一点是非常重要的

性能

正如已经提到的在谈及过程代码计算等方面时与 TSQL 相比托管代码在性能方面具有决定性的优势然而对于数据访问方面TSQL 在性能方面通常会更好因此通用规则是用 CLR 编写计算和逻辑密集的代码要比数据访问密集的代码好不过这值得更详细地考虑

让我们看看数据访问编程中的一些典型的基元和模式以及在这些情况下如何使用 ADONET 进行 TSQL 和托管编程

将结果发送到客户端

这包括将一组行发送到客户端而没有在服务器中消费它们(即没有在例程内导航行)使用 TSQL只需在 TSQL proc 中嵌入一个 SELECT 语句就可以将 SELECT 产生的行发送到客户端通过托管代码可以使用 SqlPipe 对象将结果发送到客户端TSQL 和 inproc ADONET 平台在这种情况下的作用是一样的

提交 SQL 语句

这包括来自过程代码的 SQL 语句的执行往返在这种情况下TSQL 具有很大的优势(比 inproc ADONET 快两倍多)

此处需要重点注意的是之所以在 CLR 中出现性能降低是因为增加了额外的代码层包括将来自托管代码的 TSQL 语句提交给原生 SQL 代码在将该语句提交给查询处理器之后基于语句源(TSQL 或 inproc ADONET)的性能方面就没有什么不同了

注典型的数据访问密集的存储过程可能涉及提交一系列的 SQL 语句如果 SQL 语句简单并且不需要花费大量的时间执行则来自托管代码的调用开销可能占用大部分

上一篇:用SQL测试具有百万条记录的数据库

下一篇:浅析Sybase SQL Server内存分配