SQL Server数据库引擎.NET CLR环境数据库管理员向导
 

这本白皮书也为数据库引擎 .NET Framework 编程 API提供了配置向导。它也为编码,更改和释放管理过程提供建议,并且这些建议应该适合每个数据库管理员的具体情况以确保一个专业和安全的配置。

目录

关于此白皮书

为工作寻找正确的工具
 
在数据库引擎中.NET Framework编程的初步介绍 
高性能执行 
设计,默认及部署方面的安全 
步骤1: 打开Surface Area Configuration 工具 
步骤2: 激活数据库引擎.NET Framework 设计 API 
用Transact-SQL激活API
 
为工作选择正确的工具
 
程序范例
 
目录对象 
程序集 
存储过程 
触发器 
用户定义函数 
标量函数 
表值函数 
用户定义聚合 
用户定义类型
 
安全维护
 
源代码管理
 
Release 管理 

性能检测
 
调试代码
 
排错 

Beyond SQL Server 2005 

概要 

SQL Server 2005的额外资料
在Microsoft.com, MSDN和 TechNet上的免费资料 

其他资源 

关于此白皮书

在此白皮书中描述的这些特性及计划是SQL Server下一版本的发展方向。它们不是这一产品的说明书而且也建议在使用中有所变更。在此不作出任何保证,暗示或其它,这些新特性将会包含在最后产品发行书中。

对于某些新特性,此文档以读者熟悉SQL Server 2000的性能和服务为前提。若您拥有SQL Server性能和服务的背景, 读者可以参见正式产品的网站:http://www.microsoft.com/sql/ 或者在Microsoft 网站上获取SQL Server资源工具包。

此白皮书会提供相关信息使得数据库管理员能够成功的,没有风险的,没有压力的在数据库引擎中确保Microsoft .NET Framework编程的使用。因此,此白皮书的读者应该是数据库管理员。 作为一个使用SQL Server 2005数据库引擎且具有远见的开发者,您可以登录MSDN 中题目为 Using CLR Integration in SQL Server 2005的白皮书以学习更多知识。

为工作寻找正确的工具

Microsoft® SQL Server™ 2005 提供一套完整的程序接口,使得开发者可以比以前更加轻松,更易操作的,更具可靠性的构建完善的数据库应用程序。随着大篇幅的程序选项而来的是为每个任务提供整套适当工具的考量的需求。虽然很多任务可以用很多方法完成,但每种方式都有其优势和弊端。因此,为工作找寻最好的工具的标准在于应用程序在商业使用中的加载和使用的程度。数据库管理员可能会有意下一些问题:

◆系统是否应该用XML处理数据或者删除和存储是否应该相关联?
◆这些过程和这些过程复杂的操作步骤是否应该被同步或异步处理?
◆这些商业逻辑,计算或额外的安全选则是否应该在客户应用程序,中间层或后台数据库中被处理?
◆数据分析是否应该在关联数据库中或者通过商业整合引擎来处理?
◆数据转变是否在智能服务ETL 引擎里发生或者是在SQL处理数据库里来转变?
◆传统运行在中间层服务器中的复杂商业逻辑是否仍然在中间层或是移动至SQL Server平台?
◆怎样混合的客户及服务器在infrastructure 中运行。是否需要Windows客户端,Unix 客户段的支持,还是两个均需要?
 
在大多数数据库开发项目中,与数据库相互影响的技术选择和组件结构化设计的角色落到了数据库管理员(DBA)的身上。这个管理者就是管理和恢复商业数据拥有最终职责的那个人。大多数数据库管理员们对新技术采取保守态度。这是一个本能,因为同新功能提供的好处随之而来的是,新技术可能包括危及稳定性和完整性的新风险。经验丰富的数据库管理员 经常通过全面的测试和对新技术的理解来为管理风险/利益作出保证。而且更多的是,他们常常花时间来确定哪里加入更值得,或者更重要的是,哪里不能被使用。因此在本能的保守主义作用下,数据库管理员可能会问:“当我明白了这些特性我怎么将它们关掉?”好消息是早前发布的SQL Server ,这回发布的版本在默认情况下新特性是关掉的。

与那些将新特性永久关闭的人不同的是,一个谨慎的数据库管理员 将会注意学习足够的技术来决定它可以在哪里被适当的使用以及哪里可以使它发挥最大作用。完全不需要理解开发者可能会使用到的每一个语言里的每一行代码,但是你确实需要足够的信心来提供非常多的操作支持,维护和排错。 在这些新特性的围绕下,适当使用它们的关键在于理解力,分析能力以及强的控制力。

#p#

在数据库引擎中.NET Framework编程的初步介绍

当SQL Server数据库表和视图不许编写代码时,SQL Server 2000数据库程序员拥有如下选择:

◆在数据库中使用Transact-SQL 编写代码。代码可以被写为存储过程,用户定义功能,也可以将触发器看作调用数据变化的已存储的过程。
◆使用Microsoft® Visual C++® 来编写代码,可以在数据库中运行。被写为一个扩展存储过程的代码在用户表面上看来是一个存储过程,且以同样方法运行。Parameters can be passed to参数可以被传递给扩展存储过程,而且他们可以参与事务的处理以及返回结果和状态。
◆使用sp_OA* (Object Access) 使用COM对象加载和影响系统存储过程。
◆使用其它语言和中间设备,例如ADO 和ADO.NET, 用他们来编写在数据库外执行代码,然后在查询语句中查询或者调用存储过程和功能来访问数据。passes in queries or invokes stored procedures and functions to access data.

当解决方案要求用外部库提供数据在具有功能性的前提下是完整的时,每个选项都有不同作用。例如,有些选项是选择由.NET Framework提供,或者有些是选择将复杂数学运算应用在数据上,再或者是更多复杂性的需求,例如一个客户数据集或一个真实的使用者定义数据类型。

这四个选项每一个都有限制:

◆Transact-SQL对于操作的基本设置是最好的,例如在表之间作比较,但是由于口语的限制,它为繁重任务量的可估测性的传送带来了障碍。另一个限制是不同于现代编程语言,Transact-SQL 不能够支持私有/共有数据封装,因此对他来在模块间清除接口说是比较困难的。 最后, SQL Server 2005在Transact-SQL中引进了改良的错误处理机制。然而,它仍然易受那些由丢失对象或错误语法所引起的不可引导的错误所影响,但这些错误在.NET Framework语言中是很容易解决的。
◆扩展存储过程是很自然地被编写在不可管理的代码中且在SQL Server进程中执行。高级别的编程能力是在不关注内存漏洞的情况下创建SQL Server进程完整的代码。扩展存储过程不可以提供在进程中状态时不支持状态中对Microsoft .NET Framework 库的访问。 想得到更多信息,请登陆题目是Using extended stored procedures or SP_OA stored procedures to load the CLR in SQL Server的基础知识文章。在这里并不提供。
◆sp_OA* 系统存储过程空间在COM上是有限制性的。它要求它的接口是在兼容的方法上执行,在单独调用的COM对象上有更加严格的数据限制。它们鼓励使用不相称组件,而且它们没有被设计为可以使用高吞吐量,或者不支持在单一进程中使用多重调用。在最坏的情况下,组件可以试着显示一个错误消息界面或者在SQL Server上显示其它对话框。
◆外部代码可以导致操作问题,因为数据必须留给SQL Server 进程空间而且需流动至应用程序呼叫。这个数据组可能占用大量数据集。
◆目前的选项没有可以用来创建first-class,客户聚合功能 functions or custom data types where first-class means running within the database as if it were a SQL Server primitive function or data type.首要级别的函数或者用户数据类型意味着在数据库上像原始的函数和数据类型一样的运行。

由于以上的局限,SQL Server 2005整合了.NET Framework 通用语言运行时(为管理代码提供执行环境)因此,数据库开发者能够可以将以管理好的应用程序代码安放在SQL Server中,这样做是安全,保险,可升级和多特色的。代码可以按以下方式写:

◆用户定义功能(标量 或者表值)
◆存储过程
◆触发器
◆用户定义聚合
◆用户定义类型

对于对象的用户定义功能的映射, 存储过程,以及触发器都在管理代码里编写,这样做是非常直观的。CLR程序像应用Transact-SQL一样的被访问和执行的。然而, 用户定义聚合和类型是非直观的, 数据库程序员可以用新的方法选择扩展选项:

◆用户定义聚合允许程序员建立习惯性聚合函数(用GROUP BY子句来关联). 这可以在数据库引擎中进行复杂统计和数据分析。
◆用户定义类型为程序员提供用习惯性行为定义新类型的权限。综合.NET Framework 的能力和第三方库,这个新型能将会允许强大的类型对象被创建而不是形成关联陈述。

高性能执行

SQL Server 2005向 数据库服务器进程中的已管理的代码传递高性能访问,与其它数据库技术不同的是,它提供.NET Framework 综合度,SQL Server 2005管理数据库引擎进程空间中的运行时环境(CLR)。使得SQL Server 查询执行环境具有更高的性能。而整合功能被设计出来是为了在数据库查询和编程时避免内存和CPU冲突。另外, the SQL Server和.NET Framework 软件工程师们致力于使CLRSQL Server 进程中更安全和更好用。

◆CLR 向SQL Server提出内存请求,而不是直接从Windows中申请。
◆CPU加强器CLR内存 通过SQL Server回收资源。
◆一个在进程中的version of the被管理的SQL Server 客户通过SQL 要求直接进入SQL Server 查询进程器, 因此应避免昂贵的网络交互作用。
◆CLR 应用程序域被SQL Server创建及管理。

被设计出来的所有的工程是为了确保失控的CLR程序不可以危及SQL Server的可靠性。

设计,默认及部署方面的安全

Microsoft 致力于为其客户提供安全的产品。例如,SQL Server 2000 SP3中提出的信任计算。这种设计将作为微软产品更进一步增前“off by default”默认安全的理念将进一步影响SQL Server。

注意  数据库引擎.NET Framework 编程 API 是默认关闭的, 且数据库管理员 必须进行一些操作来激活这一功能。

SQL Server 2005 引入了Surface Area Configuration 工具,它被激活后能够由数据库管理员 来控制。这一改变可以确保那些潜在的人们不习惯使用的功能不被激活且被遗留为不被保护状态。

步骤1: 打开Surface Area Configuration 工具

 

图 1

The 此工具的快捷方式被安装在SQL Server 2005程序组的配置工具sub-group 中的Start/All 程序菜单。

选择SQL Server Surface Area 配置选项然后选择 Surface Area Configuration for Features选项。

这样将会打开一个对话框在它下面激活一个SQL 服务器实例选项,然后是均锁定的选项

#p#

步骤2: 激活数据库引擎.NET Framework 设计 API

选择Surface Area Configuration for Features opens the dialog below. 将出现两个视图:通过SQL Server默认(通过实例)激活选项,第二个是通过组件激活选项例如数据库引擎和报表服务。

在激活这些功能前,增加SQL 服务器的 的外表区域,推荐数据库管理员确保他们的系统遵从以下几点:

◆最新的服务包和关键的热修补包 (可由 Microsoft Update获得)
◆配置遵从他们的推荐以使系统更安全 (这些也可以由其他的针对服务器和基础架构的第三方工具来配置)

 

图 2

数据库引擎 .NET Framework 设计API是数据库引擎特性趋势,且把它以CLR 整合到用户界面中。

用户界面为浏览和设置SQL Server 2005实例层权限提供了一个简单的方法。SQL Server 2005实例层特性也可以被以下命令控制:

◆Transact-SQL sp_con图 命令
◆使用服务器管理对象(SMO)服务器对象配置类管理代码

用Transact-SQL激活API

-- Enable & Check the Database Engine .NET Framework 编程 api
sp_configure N'clr enabled', 1
go
reconfigure
go
SELECT sc.*
FROM sys.configurations AS sc
WHERE sc.[name] = N'clr enabled'

为工作选择正确的工具

工具和API的选择取决于其他因素例如你内部员工的技术水平,depend on many other factors such as the skills of your internal staff, the recommendations of the 第三方软件厂商为你公司运行系统的推荐,系统的需求等等。

 

图 3

以上插图显示出了每一个数据库管理员都将面对的进退两难的选择。 有些选择是很简单的但是有些选择是非常复杂的,特别是当有很多方法都可以实现这些功能时,而且在技术选项之间也没有绝对的说明。

在这些情况下,原型就显得愈加重要。一个快捷的执行方法使用两种或两种以上的选项,这样可以使选择更加清楚。

根据以前的经验, 经验丰富的数据库管理员是保守的。同样的, 新技术不可能很轻松的就实行起来;他们必须首先被理解然后在他们完整引进至生产环境前需要进行严格的测试。另外,冒着动摇数据库的危险而导致用户对数据库管理的系统完整性不信任,可能会威胁到数据库管理员工作的安全。一个长远的假设是开发者会更加期望捕获风险和采用新工具来提高他们的生产力,以及扩大他们的知识面宽度,以帮助他们可以为用户提供的更多的解决方法。数据库引擎.NET Framework 编程模型具有强大功能是毫无疑问的,很多数开发者将会感激这项在数据库中以第一类编程语言写代码的新功能。

因此,在保持系统的稳定性和获得更大的生产力着两者之间就出现了矛盾。那么如何处理这个矛盾哪?

答案就是找到平衡,理解时机,然后更加着重于理性的定义选择,基于严格的标准做技术选择。这个章节给出了一些指导方针,送而找到一个折中的平衡点。

#p#

第一组观点就是在可能出现错误的地方使用新功能提供指导:

◆深度相关的数据访问
不要将简单的查询执行移出Transact-SQL。Transact-SQL 基本设置访问将会比在.NET Framework中移进移出数据更快速,特别是基本设置查询被类指针所代替。排错包含了此种潜在信息可能的花费。应该注意那些相反的请求,那些被查询所替代的复杂的计算,在这种情况下,将逻辑移动到.NET Framework程序里,在那里计算将被完全编译,逻辑可以明显改善。

那些简单的计算和基本的关系型数据访问在Transact-SQL和.NET Framework执行环境之间转换所需的花费是很明显的。在这样的情况下,Transact-SQL很可能将会胜过CLR。

◆长时间与转,外部呼叫
While it is tempting to use the new functionalityt档使用新功能的同时可以更进一步的与现有的商业系统结合是很具诱惑力的,花费时间来确保最终用户在呼叫外部API和外部系统时的花费不会得到消极的影响是非常重要的。这些影响可能在用户定义功能里特别的明显,他们可能会导致对表的每一行查询。在应用于一个10,000-row表时,外部呼叫可能在在线系统中从每秒一行的状态突然变成不可用的。

◆不必要使用用户定义类型
当对象数据可能被简单的映射成一个一队夺得关联数据类型,你可以中止或继续相关。用户定义类型有以下几种:

◆8-K大小约束。他们必须适合单一SQL Server数据页。
◆如果进行更新时,在UDT中的所有数据是可读和可重写的。
,当连接大队列对象时,应该担心同样的大小约束会被应用于用户定义聚合。

◆用户定义聚合以及在线支持
用户定义聚合不可以与SQL Server 索引师徒俩和使用,因为为在线报表操作来自动整合数据是不可能的。 如果状态数据是可接受的,然后,由定期的缓存聚合所产生的结果是一个分离的可创建和可维护的表,它可以被一个索引视图替代。

◆与早期SQL Server版本兼容
如果你的应用程序必须支持早期的SQL Server版本,你不可以使用此功能。

◆适当的使用技术
数据库引擎 .NET Framework 编程 API 为数据库程序员引入了很多新可能性。然而, 你可能会避免草率的使用这个新功能除非你可以清楚地了解它使用的基本原理。

这些观点可能看起来像是为不发展技术提供了一个很有利的实例。然而, 这有很多强有力的例证可以证明很多值得思考的优点。他们包括以下这些:

◆.NET Framework和the Visual Studio编程环境的杠杆作用
这是获得大多数利润的关键所在,它们以开发者的生产力和新兴事物形式被获取。

在SQL Server 2005和 Microsoft® Visual Studio®2005这代中, 整合开发环境和.NET Frameworks是他们第二代的第三版, 它允许了一个重要的开发者回馈。也就是说使用者接口能够快速应用开发,而且类库提供了一整套大量的对象和方法使得开发者可以不用花费力气来编写大量的普通任务。

.NET Framework (C#, Managed C++, and Visual Basic.NET)的第一类编程语言提供给程序员更多的对错误处理的控制也为访问堆栈和其他调试信息提供了更好的诊断。

在不需要提升权限的情况下程序员有权使用大多数本地功能,也就说例如大量的XML, 数组,常规表达式,数据功能操作等等都是可被访问的且不会威胁数据的安全。

另外, 因为这些代码是编译然完成的,他们已经被转换成机器语言,所以在执行业务逻辑的时候会比Transact-SQL更快。

举例可能会在以下几种情况下出现:

在表格样式里连接远程网站服务来访问数据 (在数据层里为web服务整合更加清晰的权限)

◆基于数据库中的改变,调用第三方厂商控制,来添加一个ERP系统。
◆为了你的商业用途调用代码库中提供的数据类型和函数。例如你的研究,商业,销售的需求。
◆替代扩展存储过程 (XPs)
在数据库引擎 .NET Framework 设计 API到来之前, 提供外部世界使用权的唯一方法是通过扩展存储过程和sp_OA* 存储过程。 然而, 早期文件证明,即使由经验丰富的开发者使用,这种方法具有仍对数据库稳定性极具威胁性。

推荐那些拥有提供外部商业逻辑的扩展存储过程系统或者那些通过sp_OA*存储过程使用对象模型操作的数据库管理员考虑赶快采用这种新技术,因为 SQL CLR 更加安全。

使用SQL CLR有以下优势:

◆不会因为用户代码的错误导致SQL Server服务发生故障的情况。
◆没有发生管理用户代码内存漏洞导致SQL Server减速或暂停的可能性。
◆通过SQL Server’s内存管理器控制系统资源更具操作性和可测量性。
◆不会出现安全故障,因为它完全整合了SQL Server和 .NET Framework 环境的安全。

这个优势可能不会在不安全情况下的程序集注册中应用, 因为他们可以调用不可控的代码或者线程库(例如对话产生代码,线程创建代码或者干涉进程关联处理的代码。)或者因为他们使用COM自动操作。此外,通过引起违法访问或者内存漏洞,他们可能仍然对SQL Server 实例有影响。

大多数扩展存储过程可以被替代,特别是考虑到 C++ 是一个可利用的代码编写工具。

数据更新确认
为多用户共同改变数据强制指定一个商业规则是许多系统一直面临的一个问题。新的API允许这些逻辑在数据库队列中移动触发器来确保所有更新是一致的。

一个例子可能会要求以特别的顺序引入数据,而其中的一些系统和技术是通常是不能直接被Transact-SQL触发器访问的。触发器可以检测出一个新的用户是不是第一次进入,是不是一个来自远程的可信任的IBM大型机系统。他可以为所有的商业用户提供风险管理。

#p#

减少网络通信量
一些运算法则要求所有或者大比率的数据产生结果。然而,在服务期间移动大量数据是非常消耗CPU资源的。因此,好的算法可以降低数据对CPU的消耗和对网络的消耗。也可以使应用程序有更好的性能。

例如这可能影响以下的内容:
 
◆统计计算需要所有数据以产生输出结果。
◆在SQL的数据集要连接到一些非关系型数据库时,连接服务不可用及SQL上的数据比远程服务器上的数据更大时。

写入常规目的函数

一个整合意图功能具有记下几个特征:

◆数据以论据行为传递。
◆针对内部函数存在很少或者没有额外的数据访问。
◆复杂的计算通过是一个循环中的数据的类指针代码被应用的,它是每次处理一行。

在CLR执行环境下编译开销与环境之间转换所花费的消耗相比更具有优势,在性能测试中,SQL团队测试出大约每个调用三个整形操作的降低。

实例中包括了模拟每日的事务处理量,以及一些不长用的数据模拟。

标量工具, 用户定义类型
虽然大多数数据可以被映射为关系模型,这里仍然有很多例子表现出用户自定义数据类型需要值得考虑的地方:
◆此类型约束的外部行为是为了使它被SQL Server所接受。一个实例就可以是一个表现了UTC 功能的日期类型。
◆此类型使用了封装来保护它的内容及数据经常被一起读和更新的位置。一个实例也可以是一个的空间的数据类型或者一个复合数字的执行。

使用自定义和用户定义聚合的功能
许多的行业数据在本地聚合操作中是基于all/subsets分组定制输入的,例如SUM, AVG, 和MIN, 以及其它公司。实例可能进行一个傅立叶变换或者进行一个精确的预先计算的处理。用户自定义聚合允许通过多线程的散开/散入(关联执行) 操作,因而,通过多重处理器应该很好的被分离。

高性能表值,用户定义函数
在保存实例化之前从流动表值,用户定义函数中通过支持局部结果的时候,许多运算法则不要求从外部数据源而来的涵盖所有条目的完整列表。一些例子包括了 “获得最新的股票价格”, “获得最新的事件日志”, 和 “获得队列中第一个项目”。用户定义函数支持流动的数据。数据是被查询到的而不是在某一时间点获得的,因此应该避免读取大量结果并且插入到内存中。

它的实际能力超过Transact-SQL表值,用户定义函数, 而Transact-SQL在它被调用时必须展示实例化所有数据。在这种情况下, 普通的部分请求查询它绝对胜过传统的用户定义函数。

我们应该从一个开发和系统管理服务共同体的角度来理解这个罗列出好坏用途的列表

程序范例

开发者用Visual Studio编写代码。 这是用数据库引擎 .NET Framework 设计API来编写程序最适合的工具。使用其它工具来开发程序是有可能的,例如Express toolset甚至Windows 记事本,但是他们缺乏数据库引擎的神奇功能, 整合了MSDN和Visual Source Safe, 以及其它团队发展工具。另外,Visual Studio提供了一个具有多样性的配置,测试,贺调试工具,通过它经验丰富的开发者可以开发高终端程序。

 

图 4

举一个简单的例子: 在开发者完成他们的解决方案之后,他们使用.NET Framework编译器来编译程序集(一个后缀为.dll 的文件存储在目标文件服务器上)然后不是手动就是自动的再数据库中配置二进制程序集。

在程序集assembly被加载进数据库后,它就与原始的文件(以.dll为后缀的文件)独立开来。 这意味着不用担心外部对象依赖关系就可以对数据库进行备份,移动甚至存储操作。因为他们全部预先加载进数据库中。

注意原始源代码必须仍然维护操作,而且所有改变都应该被记录下来。

以下的建议是为了使开发者得到最大生产力:

◆开发者应该拥有一整套的专业工具
◆Visual Studio 2005 组系统和 MSDN
◆临时数据库引擎的SQL Server 2005 Express 。.NET Framework API users和一些测试和开发的限制窗体
◆为正规的数据库 .NET Framework API 用户提供的SQL Server 2005 开发者版本
◆为组访问源代码和释放管理提供的Visual 源安全或者一个同等的源控制管理系统
◆开发者需要访问类产品数据。
◆一个拥有合理的相关表大小继承和模糊的灵敏型客户数据的scaled-down版本的数据库产品, 应该允许被访问使它能够被测试和更正原形。一个很重要的解释是其它的工具,例如SQL Server 2005整合服务,可以被用来为你的产品数据库创建一个丰富的开发者版本,你的产品数据库可以包含隐式信任卡,名称,地址,及社交安全数字。
◆访问测试web服务来测试和其他系统的整合。

针对每个开发者的数据库.NET Framework基础结构有一些限制。它包含了当使用Visual Studio调试器来跟踪代码时的执行过程是CLR引擎的单一的线程,除了最后的报表,调试决不可能取代生产系统。

经验丰富的程序员推荐使用SQL Server 2005开发者版本,因为它为程序员们提供了Management Studio,它的资源控制API是绝对完整的。这个版本也包含了SQL Server Profiler,这样做是为了适应了SQL Server的需要。这个版本里还包含了在脚本和自动控制方面大量的工具, 由于数据库管理员和开发者的角色有重叠, 这样做就可以使开发者在创建和调试数据库对象例如SQLCMD时更加多产。想知道更多关于工具的信息,请登陆白皮书结束部分所列出的资源及网站链接。

#p#

目录对象

一个好的数据库管理员的主要任务就是跟踪服务器上的对象,例如那些表在哪些数据库中,哪些存储过程和函数是被要求的,哪些脚本每日,每周,每月一定要运行等等。为了帮助针对所有这些对象的跟踪,我们有很多的工具,他们有来自Microsoft的也有其他的软件生产厂商的,这其中就包括针对数据模型的Microsoft® Visio®和针对数据库的Microsoft SQL Server Management Studio 等等。

面对外部世界SQL Server 2005的整合功能引入了很多新的对象来对相关系统目录的早期版本进行补充和扩展。这部分文字介绍了如何利用改变的编录去获得这些新数据库对象的正确列表,以及数据库中每个新数据库对象类型附加的新的源数据。

程序集

-- SYS.ASSEMBLIES
-- Name, Assembly ID, security and “is_visible” flag
SELECT * FROM sys.assemblies

-- SYS.ASSEMBLY_FILES
-- Assembly ID, name of each file & assembly contents
SELECT * FROM sys.assembly_files

-- SYS.ASSEMBLY_MODULES
-- Sql ObjectID, Assembly ID, name & assembly method
SELECT * FROM sys.assembly_modules

-- SYS.ASSEMBLY_REFERENCES
-- Links between assemblies on Assembly ID
SELECT * FROM sys.assembly_references

-- SYS.MODULE_ASSEMBLY_USAGES
-- Partial duplicate of SYS.ASSEMBLY_MODULES
-- Links SQL Object ID to an Assembly ID
SELECT * FROM sys.module_assembly_usages

这些视图被定义为系统目录视图为这些新的程序集的容器提供信息。这些程序集(或者.dll文件)是数据库中.NET Framework 程序编辑和注册的结果。

sys.assemblies 的“is visible”标记可以在使用公共方法注册时隐藏程序集。它可以隐藏例如利用网络服务访问数据时.XmlSerializers产生的帮助程序集。

在sys.assembly_modules视图中,一个空程序集方法显示了一个被用于用户定义聚合的程序集。需要注意的是有两个系统存储过程对这些表提供访问。如下图。

EXEC sys.sp_assemblies_rowset N'<AssemblyName>'
EXEC sys.sp_assembly_dependencies_rowset <AssemblyID>

存储过程

-- Read CLR Stored Procedure Metadata
SELECT schema_name(sp.schema_id) + '.' + sp.[name] AS [Name]
 , sp.create_date
 , sp.modify_date
 , sa.permission_set_desc AS [Access]
 , sp.is_auto_executed
FROM sys.procedures AS sp
 INNER JOIN sys.module_assembly_usages AS sau
  ON sp.object_id = sau.object_id
 INNER JOIN sys.assemblies AS sa
  ON sau.assembly_id = sa.assembly_id
WHERE sp.type_desc = N'CLR_STORED_PROCEDURE'

触发器

-- CLR Trigger Metadata
-- Note that Trigger parent object is always in the same schema
SELECT schema_name(so.schema_id) + '.' + tr.[name] AS [Name]
 , schema_name(so.schema_id) + '.' + object_name(tr.parent_id) AS    [Parent]
 , te.type_desc AS [Fired On]
 , te.is_first
 , te.is_last
 , tr.create_date
 , tr.modify_date
 , sa.permission_set_desc AS [Access]
 , tr.is_disabled
 , tr.is_not_for_replication
 , tr.is_instead_of_trigger
FROM sys.triggers AS tr
 INNER JOIN sys.objects AS so
  ON tr.[object_id] = so.[object_id]
 INNER JOIN sys.trigger_events AS te
  ON tr.[object_id] = te.[object_id]
 INNER JOIN sys.module_assembly_usages AS mau
  ON tr.object_id = mau.object_id
 INNER JOIN sys.assemblies AS sa
  ON mau.assembly_id = sa.assembly_id
WHERE tr.type_desc = N'CLR_TRIGGER'

用户定义函数

标量函数

-- List CLR Scalar Functions
SELECT schema_name(so.schema_id) + N'.' + so.[name] AS [Name]
 , so.create_date, so.modify_date
 , sa.permission_set_desc AS [Access]
FROM sys.objects AS so
 INNER JOIN sys.module_assembly_usages AS sau
  ON so.object_id = sau.object_id
 INNER JOIN sys.assemblies AS sa
  ON sau.assembly_id = sa.assembly_id
WHERE so.type_desc = N'CLR_SCALAR_FUNCTION'

表值函数

-- List CLR Table Functions
SELECT schema_name(so.schema_id) + N'.' + so.[name] AS [Name]
 , so.create_date, so.modify_date
 , sa.permission_set_desc AS [Access]
FROM sys.objects AS so
 INNER JOIN sys.module_assembly_usages AS sau
  ON so.object_id = sau.object_id
 INNER JOIN sys.assemblies AS sa
  ON sau.assembly_id = sa.assembly_id
WHERE so.type_desc = N'CLR_TABLE_VALUED_FUNCTION'

用户定义聚合

-- List CLR Aggregate Functions
SELECT schema_name(so.schema_id) + N'.' + so.[name] AS [Name]
 , so.create_date
 , so.modify_date
 , sa.permission_set_desc AS [Access]
FROM sys.objects AS so
 INNER JOIN sys.module_assembly_usages AS mau
  ON so.object_id = mau.object_id
 INNER JOIN sys.assemblies AS sa
  ON mau.assembly_id = sa.assembly_id
WHERE so.type_desc = N'AGGREGATE_FUNCTION'

#p#

用户定义类型

-- User Defined Type Metadata
-- Includes base assembly information
SELECT st.[name] AS [Type Name]
 , st.max_length
 , st.[precision]
 , st.scale
 , st.collation_name
 , st.is_nullable
 , sa.create_date
 , sa.[name] AS [Assembly Name]
 , sa.permission_set_desc AS [Access]
FROM sys.types AS st
 INNER JOIN sys.type_assembly_usages AS tau
  ON st.user_type_id = tau.user_type_id
 INNER JOIN sys.assemblies AS sa
  ON tau.assembly_id = sa.assembly_id

安全维护

在整合环境的独特安全模式下存在一个潜在的缺点,因为设计上的缺陷使得一方可能危及另一方的安全。例如,一个扩展存储过程必须回连到SQL Server 去访问数据并且必须支持活动的事务去保护修改数据的完整性。任何的数据失败都会导致安全漏洞。

数据库引擎.NET Framework 设计API的架构在安全模式方面是非常注意的。SQL Server 在.NET Framework 代码访问安全方面使用GRANT命令来提供针对特殊对象访问,并且控制在高/低权限模式之间的交互。

一个非管理用户在他们能被使用之前必须获得对日常事务处理的执行权限。

单一化处理代码访问安全模块(定义程序集允许做的事情)。组的权限分为下面三个设置:

SAFE
程序集方法只能和Transact-SQL的存储过程或函数同级别。代码要运行在信任调用下。

EXTERNAL ACCESS
程序集方法可以执行文件和网络的输入/输出。外部代码使用SQL Server 服务帐号权限运行,这样的设置可以在控制用户输入的特定外部资源时确定调用者的权限。

UNSAFE
这个权限延展了外部权限的设置,使得程序集允许不可管理的调用,代码不可控。

注意在UNSAFE模式下,整合代码将阻止一部分对.NET Framework 的库使用。例如,编译器,windows 管理器,企业服务器,和其他一些由于SQL Server 无法发现而被阻止掉的功能。

我们推荐数据库管理员限制External/Unsafe模式的使用,如果开发者要求这些高级别的权限时管理员应该去选择更加严格的环境要求。

源代码管理

CREATE ASSEMBLY在SQL Server 数据库中加载二进制程序集,但没有办法同时加载程序源。因为他是为了数据库管理员创建程序集来管理源代码用的。就好像第三方软件只支持二进制代码,也可以为他们的软件提供专业的技术支持。无论如何,在你的代码发生问题之前让你的数据库管理员可以管理源代码是一件非常重要的事情。

在这篇文章的设计范例部分包括推荐的为应用程序开发者提供的工具。根据这些推荐的内容,数据库管理员对于改变控制策略,程序,以及对开发/测试系统和那些正在运行程序的系统的正确描述这些方面会变的非常的容易,使用SQL Server 2005新的安全特性和DDL触发器可以在生产环境中限制访问和支配(至少是审核)来更好的执行控制策略。如果希望,DDL触发器可以阻止一个数据库中所有的DDL(数据定义语言)声明,或者特殊的某个或者某组声明。

注意没有经过完全的检查的代码是不会从开发阶段送到生产阶段的,我们一定要确保代码万无一失。

尽管如此,我们依然推荐开发者执行Visual Studio的自动部署特性利用最大的生产压力在代码开发周期中来进行测试,在完成后开发者应该将源代码和编译文件传给负责部署的数据库管理员 。

需要注意的是因为.NET Framework的编译器是免费的,所以数据库管理员 没有必要安装Visual Studio 除非他们想利用Visual Studio 中的一些特性来对代码进行检查和调试的处理。

数据库管理员 应该将源文件做好备份,然后将检查后的代码和编译后的文件保存在另外的一个位置,这样可以对代码作一个很好的保护。

我们同样建议副本应该在每台它加载程序集的数据库上进行关联。这意味着在开发代码目录上和多个数据库管理员 目录上执行的是单一副本。如下图,在数据库利用CREATE ASSEMBLY命令加载了程序集后所有的支持文件例如源代码,文档都通过ALTER ASSEMBLY命令加载。

ALTER ASSEMBLY LeastSquaresSqlFunction
ADD FILE FROM 'D:\Production System\Source Code\Least Squares\LS1.cs';

◆Productivity Tip
注意 ALTER ASSEMBLY命令支持在单一语句中加载多个文件。
◆数据库管理员 和开发者都应该在检查完代码后作出一个审核日值改变的注释。
◆WinDiff 工具(或者 Visual SourceSafe Compare) 是一个很好的代码比较的工具,详细信息请查阅:WinDiffhttp://msdn.microsoft.com/library/default.asp?url=/library/en-us/tools/tools/windiff.asp.
◆Productivity Tip

当Visual Studio 使用SQL Server Database Engine .NET Framework 编程 API 编译应用程序时,编译输出面板包括所需的编译器命令行工具。他可以被减切并且复制到一个发布命令文件,数据库管理员可以用它重新编译应用程序。

Release 管理

在源代码在专业的控制保护下,开发者提交了源文件和编译文件。这时release管理器在代码和架构配置不当的情况下就有了很大的作用。如果希望了解它为什么如此重要,可以关注这篇文章下面有关SQL Server 2005 的部分。

SQL Server 2005 的工具设置使得数据库管理员 和开发者可以在一个公用源代码库上协同工作。Microsoft SQL Server Management Studio 可以从Microsoft Visual SourceSafe或者其他地方加载和保存源控制应用的脚本。

图 5

数据库管理员对开发源代码项目有读权限,这样他可以拷贝特定的系统上释放的项目的脚本和源代码。释放管理的另一个选项就是提取适当的源代码的版本并把他们放到一个数据库管理员 可以访问的文件夹里。使他们可以在共享SQL Server 上重新编译和加载。

#p#

控制代码提升也是数据库管理员的一个关键角色。允许开发者直接在共享系统上部署,那么它所导致的最终在生产环境中部署产生的不可控源代码和错误几乎是不可避免的。当建立了一个错误版本的源代码或者创建了一个从未测试过的代码时都会马上要求重编译。最终测试环境中不能再有问题出现,因为在资源不能匹配的时候产品程序集是不能做调试的。

下面的例子例举了 Microsoft® C# 程序编译器 csc.exe (.NET Framework 中的C# 编译器).

Csc.exe /noconfig /nowarn:"1701;1702" /warn:4 /define:DEBUG;

TRACE /reference:C:\WINDOWS\Microsoft.NET\Framework\v2.0.50215\System.Data.dll

/reference:C:\WINDOWS\Microsoft.NET\Framework\v2.0.50215\System.dll

/reference:C:\WINDOWS\Microsoft.NET\Framework\v2.0.50215\System.Web.Services.dll

/reference:C:\WINDOWS\Microsoft.NET\Framework\v2.0.50215\System.XML.dll /debug+

/optimize- /out:obj\Release\MainframeWebService.dll

/target:library IBMSystemCode.cs AssemblyInfo.cs "Web References

\com.Mainframe.webservices\Reference.cs"

这是一个调用web服务的例子,下面的阶段要求连续的代码,这将在下面的例子中提到。这个程序是安装在.NET Framework 2.0 SDK 下,可以在C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin找到。在SQL Server 2005 中使用CREATE ASSEMBLY命令或者用户界面注册一个创建的程序集“MainframeWebService.XmlSerializers.dll”
Sgen.exe /n /f MainframeWebService.dll

使用Transact-SQL 注册程序集。

CREATE ASSEMBLY [MainframeWebService]
  AUTHORIZATION dbo
FROM 'C:\MWS\bin\Release\MainframeWebService.dll'
  WITH permission_set = external access
go
CREATE ASSEMBLY [MainframeWebService.XmlSerializers]
  AUTHORIZATION dbo
FROM 'C:\MWS\bin\Release\MainframeWebService.xmlserializers.dll'
  WITH permission_set = safe
go

上面的代码完成了对开发代码的编译,产生了编译代码,然后通过CREATE FUNCTION/PROCEDURE加载了程序集到SQL Server 2005
 
Productivity Tip
产生的代码会在它的父程序集之后加载。在stealth模式下是相反的,并且父程序集自动加载。要求使用CREATE语句并用ALTER ASSEMBLY … WITH VISIBILITY = ON解锁它。

使用专业工具可以让开发者达到最大的生产力。数据库部署环境也能够被转移到一个好的生产实例上,同时做到控制代码保护。数据库管理员 可以通过配置CLR技术而不会有系统稳定性方面的风险。

性能检测

如果数据库管理员 安装了SQL Server 2005 ,然后开启了Windows System Monitor (PERFMON.EXE),它可能会失望的看到只有一个SQL Server CLR counter (SqlServer:CLR “CLR Execution”)给出了CPU的统计报告。

 

图 6

然而这是一个误导,因为在.NET CLR计算器组中存在着大量的计数器。他们在性能列表里面。他们可以根据SQL Server 服务的名字来做筛选。

Productivity Tip
.一个服务器运行多个SQL Server 实例处理的时候,每个CLR代码在列表中都不显著,这时,应该将某一个实例连接到CLR,然后通过CPU的活动型来判别。

计数器有很多的设置帮助我们了解程序在SQL上运行时的健康性和活动型。

◆.NET CLR Exceptions –Exceptions/Sec 提供了一个对应用程序代码的早期警告,如果这个值比平时高(这个设置也可以用在正常的功能上),应用程序可能会失败。更深入的报告要去看错误日志。
◆.NET CLR Loading – SQL Server 使用AppDomain在数据库之间隔离代码。一个CLR 为程序提供了一个独立运行时。这个设置可以检测AppDomains和系统上加载的程序集的数量。这个值太大意味着“procedure cache”的压力过大。
◆.NET CLR Memory –提供了三种CLR内存的详细信息。这个计数器还可以检测CLR内存的使用情况,可以设置警告值。提示代码的问题,从而使代码使用较低的内存重新设计。

#p#

.NET Data Provider for SQL Server –提供了每秒的连接数和非连接数,在获取数据库级别的活动性方面非常有用。如下图这个计数器是数据库级别的。

  

除了服务监控计数器,我们在SQL Server Dynamic Management Views (DMV)中也可以得到大量SQL Server操作系统的数据的信息。下面是一些有用的查询。

-- Loaded Assemblies (run in each database)
SELECT sa.[name]
 , ad.[appdomain_name]
 , clr.[load_time]
FROM sys.dm_clr_loaded_assemblies AS clr
 INNER JOIN sys.assemblies AS sa
  ON clr.assembly_id = sa.assembly_id
 INNER JOIN sys.dm_clr_appdomains AS ad
  ON clr.appdomain_address = ad.appdomain_address

-- SQL CLR Memory Usage
SELECT mo.[type]
 , sum(mo.pages_allocated_count * mo.page_size_in_bytes/1024)
  AS N'Current KB'
 , sum(mo.max_pages_allocated_count * mo.page_size_in_bytes/1024)
  AS N'Max KB'
FROM sys.dm_os_memory_objects AS mo
WHERE mo.[type] LIKE '%clr%'
GROUP BY mo.[type]
ORDER BY mo.[type]

-- SQL CLR Wait Statistics
SELECT ws.*
FROM sys.dm_os_wait_stats AS ws
WHERE ws.wait_type LIKE '%clr%'

-- Requests that are currently in SQL CLR
SELECT session_id, request_id, start_time, status, command, database_id,
wait_type, wait_time, last_wait_type, wait_resource, cpu_time,
total_elapsed_time, nest_level, executing_managed_code
FROM sys.dm_exec_requests
WHERE executing_managed_code = 1

-- Query performance and time spent in SQL CLR.
SELECT
(SELECT text FROM sys.dm_exec_sql_text(qs.sql_handle)) AS query_text, qs.*
FROM sys.dm_exec_query_stats AS qs
WHERE qs.total_clr_time > 0
ORDER BY qs.total_clr_time desc

-- Obtaining CLR Execution performance counter values.
SELECT object_name, counter_name, cntr_value, cntr_type
FROM sys.dm_os_performance_counters
WHERE counter_name LIKE '%CLR%'

调试代码

SQL Server 2005 和Visual Studio 2005 是紧密整合的。 The SQL Server 的工具以及商业智能部分是为数据库管理员设计的,而Visual Studio 的整合开发环境是为专业开发人员设计的。

调试处理针对数据库管理员和开发人员的功能分割是不同的:

◆数据库管理员 使用SQL Server Profiler测试跟踪数据库的活动性。

 

图 8

◆开发人员使用Visual Studio debugger去跟踪代码执行,在他们自己的SQL Server (开发版)上使用SQL Server Profiler检测数据库的活动性。Debugger可以执行客户端到服务器的端对端的调试。这种模式使得开发过程中的调试变得非常具有生产时效性。

 

图 9

这个工具的联合允许了数据库管理员 能够集中精力到SQL Server的运行上,了解,优化工作的查询,也早期SQL Server 版本将比也提供给开发人员一个工具实现快速的应用程序开发。

Productivity Tip
数据库引擎.NET Framework 规划 API的调试环境并不支持并发调试,推荐开发者准备自己的SQL Server 开发实例来使用Visual Studio debuggers。

#p#

排错

这部分内容给出了数据库管理员对.NET Framework设计API数据库引擎的排错和代码检查的一些指导方针。当然这不是一个完整的列表。我们还是推荐所有的开发者和数据库管理员们应该聚在一起然后制定出符合自己的一个标准。我们以当前流行的Transact-SQL标准作为出发点,来确定一些相对坏的项目的,创建一个好的项目的公认的一些注意点。

Lack of Set-based Operations (Loops within Loops)

那些对于SQL Server 语法并不熟悉的开发者可能不得不用一些非常复杂的语句来替代像JOIN 或者SELECT等语句。例如一个表的处理需要其他外部表的每行数据时,那么下面这种处理方式是正确的,具体代码如下:

 getdata()
 foreach (datarow in datatable)
  getdata()
  foreach (datarow in datatable2)
  etc

它通常是被一个简单的INNER JOIN语句所替代。

这个行为在SQL Server Profiler中很容易被发现,因为其内部的循环会在服务器上产生大量的查询。

在CLR中的CPU-Intensive处理

一些复杂的逻辑结构在.NET Framework 语言中要比在Transact-SQL结构中更容易去处理。所以如果SQL Server 不能像中间服务器一样做一些负载平衡,那么可能会成为瓶颈。在sys.dm_clr_appdomains表中的一列可以列出有关CLR CPU消耗的检测数据。

如果按照文章前面的建议进行使用,那么这点将不是什么大问题。因此,middle-tier的迁移功能将是一个很小的代码任务。

例举内存中的大的对象

在SQL Server 2000中的Transact-SQL并不提供创建大对象的方法。在小的存储过程中加入大的IMAGE 或者 N/TEXT参数这一方法的能力可能是最差的。很多的内容都将作为@TABLE 变量或#TEMP 表贮存在TempDB中。然而在SQL Server 2005 的.NET Framework 运行时中就不是这个样子了,在ADO.NET数据集和用户自产收集中可以放置大的和潜在的大内存要求。你应该使用系统检测计数器来检测代内存的使用情况。因为在从开发到生产的整个过程中我们应该都可以保证代码流的稳定。

这些解决方案与在middle-tier上获得的是相似的。

◆使用分页来得到内存中的数据子集。
◆确认数据已经提交。
◆移动聚合数据替代具体的细节数据。

出错处理

数据库引擎.NET Framework 设计API支持不同语言的出错处理。所以出错处理是非常容易的,任一个外部操作,例如数据库,文件系统或者web服务访问,以及操作的上溢出,下溢出的处理方法都在出错处理中有预先的安装。

结合SQLContext.Pipe.ExecuteAndSend()使用RAISERROR命令可以返回SQL Server 的错误。注意在SQL Server 2005 中Transact-SQL的出错处理有了一个很大的改变。开发者应该对他们的代码使用RAISERRORS这一处理。

提供一个例外比返回错误代码对开发者来说更加有意义。因为开发者可能会忘记标记@@ERROR。

不安全的代码问题

数据库管理员对于UNSAFE注册代码非常难以控制。尤其是在共享实例中。因为在开发者的被允许调用非管理代码。这是一个未经授权的任务。在其他的代码安全模式下,SQL Server 只关注那些注册的程序集和仅授权级别的调用。

Unsafe代码和不可管代码在高权限下可以被完全访问。因此,在部署前应该进行一次全面的代码检查。尤其应该注意所有的参数以及SQL Server 上的连接。在部分升级时确认事务的边界。最后我们应该确任代码在服务器上不会有错误信息提示显示。

用户自定义类型问题

用户自定义类型使用时应特别小心。注意他的8-KB的限制,以及他们的其他限制:

◆他们将作为一个自动对象进行读写。
◆执行代码在架构级别使用,所以对于现有类型的改变的潜在花费是很高的。

Beyond SQL Server 2005

SQL Server 2005 的.NET Framework 运行时环境同时装载了Visual Studio 2005。预期的服务包和热修补并没有改变版本,然而,这对于SQL Server 未来的发展并不是一个好的设定。作为.NET Framework 的发展,未来的SQL Server 版本将会转化到可以使用这些新设备。

下面的表可以用于应用程序开发者使用SQL Server 的.NET Framework 测试应用测试。注意如果CLR不可用,查询将返回一个空的字符串。通常来说,主要的版本都需要做检查,除非只是为了测试某些特性而发布的版本。

-- Will return the version if the .NET Framework has been used
SELECT p.[value]
FROM sys.dm_clr_properties AS p
WHERE p.[name] = N'version'

-- Will return the version even if the .NET Framework is unused
-- Test the version of the Microsoft .NET Runtime Execution Engine
SELECT lm.product_version
FROM sys.dm_os_loaded_modules AS lm
WHERE lm.[name] LIKE N'%\MSCOREE.DLL'

在这个白皮书出版的时候,windows只能处理一个单一的.NET Framework 运行时环境。虽然这一点在今后的版本中还没有被确定。但是未来的SQL Server 版本可能有一下特性:

◆要求代码重编译 – 确定数据库管理员 和加载到SQL Server 上的源代码版本是同步的。同时使得重编译更加简单。
◆要求代码修改– 利用新的API的优势同时为现有的选项设计不当的API增加选项。管理源文件以及API使用的情况。
◆要求多个 .NET Framework运行时在SQL Server “down level” 代码检查时加载。它可以在性能开销方面提供更好的保护。

数据库管理员要管理他们公司的源代码,检测开发API的使用,还要花时间保护代码的修改。及在需要代码重写的情况下保护系统。

概要

这个白皮书从传统的数据库管理员的角度探究了SQL Server 2005 .NET 公共语言时的整合。

下面的部分提供了:

◆使用这个新的能力提供的对于处理和程序的安全以及成功部署的确定。
◆为数据库管理员 提供了更好的目录数量管理和动态管理视图查询的能力。更简单的访问对象列表,了解系统状态的信息。
◆在调试和跟踪方面为数据库管理员 提供可以发挥起最大生产力的工具集。

我们关心的问题是能否提出一个新特性并不适应的例举环境。丰富的SQL Server 2005 CLR整合使得再各种情况都可以很好的满足人们的要求。

在这篇文章中我们要学习的最重要的就是CLR整合提供了一种新的,强有力的应用程序开发工具包,以使得在许多的场景下生产力被大大提高,并且为许多企业环境提供了新的可选项。

SQL Server 2005的额外资料

在Microsoft.com, MSDN和 TechNet上的免费资料

MSDN SQL Server Developer Center

MSDN 白皮书: An Overview of SQL Server 2005 for the Database Developer
MSDN白皮书: Processing XML Showplans Using SQLCLR in SQL Server 2005
MSDN白皮书: Using CLR Integration in SQL Server 2005
MSDN白皮书: XML Support in Microsoft SQL Server 2005
MSDN白皮书: XML Options in Microsoft SQL Server 2005
MSDN白皮书: What's New in FOR XML in Microsoft SQL Server 2005
MSDN白皮书: XML Best Practices for Microsoft SQL Server 2005
MSDN白皮书: Usage Scenarios for SQL Server 2005 Native Web Services
MSDN白皮书: Managed Data Access Inside SQL Server with ADO.NET and SQLCLR
MSDN On-demand Webcasts
MSDN Live Webcasts 
SQL Server 2005 Hands-On Labs
SQLCLR Hands-On Lab Manual
Microsoft SQL Server TechCenter on TechNet

其他资源
Sample Book Chapters for SQL Server 2005 是一个讲述SQL Server 2005 的书目的列表。
Hosting the .NET Runtime in Microsoft SQL Server 在 Association for Computing Machinery (www.ACM.org)上. 要想访问这些资料需要成为SIGMOD, the ACM的会员或者直接购买。
Service Oriented Database Architecture David Campbell编写, 也是在Computing Machinery (www.ACM.org). 上发表。要想访问这些资料需要成为SIGMOD, the ACM的会员或者直接购买。

更多信息:http://www.microsoft.com/sql/

(责任编辑 火凤凰 sunsj@51cto.com  QQ:34067741  TEL:(010)68476636-8007)