65.9K
CodeProject 正在变化。 阅读更多。
Home

如何将 OLE 对象集成到 SQL Server

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.92/5 (31投票s)

2009年6月15日

CPOL

3分钟阅读

viewsIcon

66851

downloadIcon

1221

本文将演示如何将 T-SQL 与外部应用程序集成。

引言

本文将演示如何将 T-SQL 与外部应用程序集成。

背景

当我们需要在 SQL Server 数据库中存储或检索数据时,我们会使用 T-SQL。但关键是如何将 T-SQL 与外部应用程序集成?例如,我们想将 SQL Server 与 Microsoft Word、Excel 或 Microsoft Exchange Server 集成。那么如何实现呢?

Using the Code

有七个扩展存储过程可以调用外部应用程序,例如 DLL。这些存储过程的名称和描述如下:

存储过程 描述
sp_OACreate 在 Microsoft SQL Server 的实例上创建 OLE 对象实例
sp_OADestroy 销毁已创建的 OLE 对象
sp_OAGetErrorInfo 获取 OLE 自动化错误信息
sp_OAGetProperty 获取 OLE 对象的属性值
sp_OASetProperty 将 OLE 对象的属性设置为新值
sp_OAMethod 调用 OLE 对象的方法
sp_OAStop 停止全局 OLE 自动化存储过程执行环境

参考:SQL Server Books Online。

让我们用一个简单的例子来实现这一点。我们的要求是从 SQL Server 存储过程中访问第三方 DLL。

以下是使用 C# .NET 开发的两个函数。
函数 (a) getOSPlatform 将返回系统平台,函数 (b) writeToFile 将使用参数给定的值将文本写入名为 CLRTempE.txt 的文本文件中。

示例 COM+ 代码 (C#. NET)

public string getOSPlatform()
{    // Return the System Platform. 
      return Convert.ToString(System.Environment.OSVersion.Platform);      
}
          
public int writeToFile(
                        string strPath
                      , string strText)
{
    int intResult = -1;
    try
    {
        if (strPath != "")
        {
            if (System.IO.File.Exists(strPath))
            {
                FileStream stream = new FileStream(
                                            strPath
                                          , FileMode.Open
                                          , FileAccess.Write);

                StreamWriter writer = new StreamWriter(stream);
                writer.BaseStream.Seek(0, SeekOrigin.End);
                writer.Write("TimeStamp: [ "
                                    + Convert.ToString(System.DateTime.Now)
                                    + " ] "
                                    + strText
                                    + " || (:-> || Info ! [Successfully inserted.]");
                writer.Write(Environment.NewLine);
                writer.Flush();
                writer.Close();

              }
               else
                    {
                        FileStream stream = new FileStream(
                            strPath
                          , FileMode.CreateNew
                          , FileAccess.Write);

                        StreamWriter writer = new StreamWriter(stream);
                        writer.BaseStream.Seek(0, SeekOrigin.End);
                        writer.Write("TimeStamp: [ "
                                    + Convert.ToString(System.DateTime.Now)
                                    + " ] "
                                    + strText
                                    + " || (:-> || Info ! [Successfully inserted.]");
                        writer.Write(Environment.NewLine);
                        writer.Flush();
                        writer.Close();

                    }
                    intResult = 0;
         }
    }
         catch (Exception ex)
         { throw ex; }

            return intResult;
}

示例 SQL 存储过程

--EXEC dbo.spCLRExample
CREATE PROCEDURE dbo.spCLRExample
AS
BEGIN

DECLARE @intResult INT
DECLARE @comHandle INT
DECLARE @errorSource VARCHAR(8000)
DECLARE @errorDescription VARCHAR(8000)
DECLARE @inputText VARCHAR(500)
DECLARE @OSPlatform VARCHAR(500)
DECLARE @isSuccess INT     

    set @inputText = 'This is a simple text.' 

    EXEC @intResult = sp_OACreate 'CLRExample.Example', @comHandle OUTPUT, 4

    IF (@intResult <> 0)
        BEGIN
        -- Error Handling 
            EXEC sp_OAGetErrorInfo @comHandle, @errorSource OUTPUT, _
				@errorDescription OUTPUT
            SELECT [Error Source] = @errorSource, [Description] = @errorDescription
            RETURN
        END
    
    -- Call a method into the component
    EXEC @intResult = sp_OAMethod @comHandle, 'getOSPlatform',@OSPlatform OUTPUT

    Print @OSPlatform

    IF (@intResult <> 0)
        BEGIN
        -- Error Handling 
            EXEC sp_OAGetErrorInfo @comHandle, @errorSource OUTPUT, _
					@errorDescription OUTPUT
            SELECT [Error Source] = @errorSource, [Description] = @errorDescription
            RETURN
        END

     -- Call a method into the component
      EXEC @intResult = sp_OAMethod @comHandle, _
	'writeToFile',@isSuccess OUTPUT, 'C:\CLRTempE.txt', @inputText

    IF (@intResult <> 0)
        BEGIN
        -- Error Handling 
            EXEC sp_OAGetErrorInfo @comHandle, _
		@errorSource OUTPUT, @errorDescription OUTPUT
            SELECT [Error Source] = @errorSource, [Description] = @errorDescription
            RETURN
        END

    -- Release the reference to the COM object */
    EXEC sp_OADestroy @comHandle

END

GO

现在我们将讨论上述代码的工作原理。sp_OACreate 将创建 DLL 到 SQL Server 的实例。如果成功创建,则输出为 0。如果非零,则将其发送到 sp_OAGetErrorInfo 并获取错误消息。sp_OAMethod 用于调用 DLL 的方法。在第一种情况下,我们调用只具有返回值的方法 getOSPlatformsp_OACreate 的最后一个参数必须是 1、4 或 5。它指定新创建的 OLE 对象运行的执行上下文。如果指定,此值必须是以下值之一:

  • 1 = 仅进程内 (.dll) OLE 服务器
  • 4 = 仅本地 (.exe) OLE 服务器
  • 5 = 允许进程内和本地 OLE 服务器

如果未指定,则默认值为 5。

如果允许进程内 OLE 服务器(通过使用上下文值 15 或不指定上下文值),它就可以访问 SQL Server 拥有的内存和其他资源。进程内 OLE 服务器可能会损坏 SQL Server 内存或资源,并导致不可预测的结果,例如 SQL Server 访问冲突。

当我们指定上下文值 4 时,本地 OLE 服务器无法访问任何 SQL Server 资源,也无法损坏 SQL Server 内存或资源。最后,sp_OADestroy 将销毁 SQL Server 中已创建的 OLE 对象。

参考 SQL Server Books Online。

兴趣点 

注册 COM+ 时,我们必须使用 Visual Studio 命令提示符执行以下命令:

Commands
C:\Program Files\Microsoft Visual Studio 9.0\VC> RegAsm CLRExample.dll \ tlb: CLRExample.tlb \ codebase
注意:注册 COM+ 时不要使用 regsvr32

结论

我希望这篇文章对您有所帮助。尽情享受吧! 

历史

  • 2009 年 6 月 15 日: 初始发布
© . All rights reserved.