文章作者 100test 发表时间 2007:03:13 21:46:58
来源 100Test.Com百考试题网
在项目中加入类型后,定义public static(VB.NET 的声明是 Shared)函数,也就是 SQL Server 在调用这个函数时,无须先建立该类型的实例(instance),就可以直接调用该函数。在函数前通过 SqlProcedure 特性(Attribute)告知该函数是用作创建存储过程。在同一个类型中,可以声明多个函数,注册该函数到 SQL Server 时,会用到程序集在 SQL Server 注册的名称、命名空间(namespace)、类型,以及函数名称,以指定函数当作某个存储过程。
当你通过 Visual Studio 2005 创建“SQL Server Project”项目时,可以通过在项目中新建“Stored Procedure”模板的方式加入含有相关定义的类,你只须将函数的主体编写完毕即可。在此示范一个通过网络访问数据的简单存储过程范例,内容如程序代码列表11-3所示:
程序代码列表11-3 通过.NET的XPathNavigator 解析 XML 文件,并以记录的方式返回
Partial Public Class myStoredProcedures
Public Shared Sub RetrieveRSS(ByVal strURL As SqlString)
Try
Dim strRSS As String
通过 MSDN 提供的 RSS(Really Simple Syndication)
取得关于 SQL Server 各种技术信息的列表
将该 XML 的文件转成一条条的记录,通过 Pipe 返回到前端
If strURL.IsNull Then
strRSS = "http://msdn.microsoft.com/sql/rss.xml"
Else
strRSS = strURL.Value
End If
************************************************************************
通过 XPathDocument 类型 通过 Internet 访问XML文件
Dim doc As New XPathDocument(strRSS)
***********************************************************************
Dim nav As XPathNavigator = doc.CreateNavigator
Dim i As XPathNodeIterator = nav.Select("//item")
Dim rss_results(4) As SqlMetaData
rss_results(0) = New SqlMetaData("名称", SqlDbType.NVarChar, 250)
rss_results(1) = New SqlMetaData("发布日期", SqlDbType.DateTime)
rss_results(2) = New SqlMetaData("说明", SqlDbType.NVarChar, 2000)
rss_results(3) = New SqlMetaData("连接", SqlDbType.NVarChar, 300)
rss_results(4) = New SqlMetaData("RSS 原始节点", SqlDbType.Xml)
定义存放结果的每一条记录的数据结构
Dim record As New Microsoft.SqlServer.Server.SqlDataRecord(rss_results)
***********************************************************************
将SQL Server收到的数据结果返回到前端
Dim pipe As SqlPipe = SqlContext.Pipe
将 Record 结构传回到前端
pipe.SendResultsStart(record)
While i.MoveNext
将 XML 数据通过 XPath 语法取出,并放入记录中
record.SetString(0, CType(i.Current.Evaluate("string(title[1]/text())"), String))
record.SetDateTime(1, DateTime.Parse( _
CType(i.Current.Evaluate("string(pubDate[1]/text())"), String)))
record.SetString(2, _
CType(i.Current.Evaluate("string(description[1]/text())"), String))
record.SetString(3, CType(i.Current.Evaluate("string(link[1]/text())"), String))
record.SetString(4, CType(i.Current.InnerXml, String))
将结果通过 Pipe 传回到调用端
pipe.SendResultsRow(record)
End While
***********************************************************************
pipe.SendResultsEnd()
Catch ex As Exception
Dim pipe As SqlPipe = SqlContext.Pipe
pipe.Send(ex.ToString())
End Try
End Sub
End Class
在上述程序代码中,我们通过 XPathDocument 对象实例,通过网络取回微软放在 MSDN 网站上关于各产品的技术文件,在此取得的是与 SQL Server 有关的技术资料。由于该文件是 XML 格式,所以可通过 XPathNavigator 和XPathNodeIterator 对象实例查找文件内所需的节点元素
以 SqlMetaData 对象实例定义每条记录各字段的结构后,赋予 SqlMetaData 实例所形成的数组到 SqlDataRecord 对象的构造函数中,据此创建出符合该结构的单录记录实例,接着以 XPathNodeIterator 实例取得整篇 XML 文件中所有的 item 节点,逐笔赋予节点内子节点的数据到 SqlDataRecord 实例,并直接通过 SqlPipe 对象实例将该条记录返回到用户手上。
你可以通过 Visual Studio 2005 所提供的部署功能将程序代码列表 11-3 所建立的函数注册成 SQL Server 内的存储过程,也可以通过以下的 T-SQL 语法完成注册。
程序代码列表11-4 通过T-SQL 注册程序集和存储过程
--让该数据库的 .NET 对象可以访问 SQL Server 之外的资源
ALTER DATABASE AdventureWorks SET TRUSTWORTHY ON
--将 Assembly 加入到 SQL Server
CREATE ASSEMBLY YukonCLR FROM C:\BookSamples\SQL 2005 Dev\Ch11_Clr\YukonCLR\bin\YukonCLR.dll
WITH PERMISSION_SET=external_access
GO
--创建一个名为 RetrieveRSS 的存储过程
CREATE PROC RetrieveRSS @strURL NVARCHAR(100)=NULL
AS
EXTERNAL NAME
YukonCLR.[YukonCLR.myStoredProcedures].RetrieveRSS
GO
注册完成后,使用下列T-SQL语法调用存储过程,测试执行结果。
EXEC RetrieveRSS
由于范例中的存储过程会读取因特网上的 RSS XML 文件,此为 SQL Server 外部的资源,所以该组件注册时要设置 PERMISSION_SET 为 external_access。
但若要使用 PERMISSION_SET 为 external_access 或 unsafe 等级的数据集时,该数据库的 TRUSTWORTHY 属性必须设为 ON。默认这个属性设置为 OFF,以此来防护 DBA 附加数据库时,如果该数据库已经存在了功能强大而且可以访问外部资源的 .NET 程序,这将会危害到数据库服务器的安全。由于附加数据库时,该数据库的 TRUSTWORTHY 属性为 OFF,所以这些用 .NET 编写的数据库对象将没有权限来执行。若 DBA 确认这些对象没有问题,再自行打开该选项,以减少 .NET 所带来的风险。
在指定组件中函数当作存储过程的完整名称结构如程序代码列表11-4:
程序代码列表11-4
< 注册到 SQL Server 2005 的 Assembly 名称 >.< [命名空间.类型名称] >.< 函数名称 >
事实上,Visual Studio 2005 就是引用我们在各函数或类定义的 Attribute,先移除 SQL Server 服务器上已经存在的同名对象,然后用与我们手动注册相似的 T-SQL 语法完成注册。布署完毕后,通过 Sql 语法调用上述存储过程的结果如图11-13所示:
在图11-13 中可以看到逐条返回来的记录结构与一般的SQL语法执行结果无异。前端应用程序调用时,并不知道该存储过程是以 T-SQL 实际操作的,有可能是通过 .NET 语言编写的。而在此我们通过 .NET CLR 扩展了 SQL Server 2005 的功能,让它可以访问网络上的数据。
图11-13 通过存储过程显示 MSDN RSS 的记录
若你要删除已注册的存储过程与程序集,记得要先删除存储过程,所有依附该程序集相关的对象全部删除后,最后才可以删除该程序集。语法如下:
DROP PROCEDURE RetrieveRSS
DROP ASSEMBLY YukonClr
看完了存储过程后,接着来创建系统在某个数据表添加、修改、删除记录后,自动调用的触发器(Trigger)。
与前述创建存储过程的方式相同,在类中声明 public static 方法。通过 SqlTrigger 属性告知该方法是在某个数据表在添加、删除或修改时,SQL Server 需自动调用的触发器。并利用 SqlPipe 与 SqlCommand 两种对象分别将结果显示给前端应用程序,最后记录更改过程到我们自定义的数据表 tblAuditSalesPerson 中。简单的程序范例如程序代码列表11-5:
程序代码列表11-5 通过 .NET的 SqlTriggerContext 对象取得触发器的相关数据
Public Class Trigger