在 Oracle 产品中使用 .NET 存储过程
转贴前言
现在Oracle 10g2 和IBM最新的DB2都支持.NET的存储过程了。剩下好像只有Sybase了。
前言:
对于 .NET 开发人员而言,针对 Windows 的 Oracle 数据库 10g 第 2 版中最激动人心的特性之一是,能够通过Oracle Database Extensions for .NET使用选择的 .NET 语言来实施存储过程。
在掌握使用 Oracle 产品进行 .NET 应用程序开发这一部分中,介绍了如何在应用程序中使用 .NET 存储过程的分步方法。 您将了解到如何支持 .NET 存储过程,如何安装和配置 Oracle 数据库来支持 .NET 存储过程,如何开发和部署 .NET 存储过程,以及如何调试 .NET 存储过程。
支持体系结构
PL/SQL 存储过程和函数在与 Oracle 数据库相同的进程中运行,并且存储在 Oracle 内部。 另一方面,.NET 存储过程在外部进程中运行,.NET 代码将被编译成“.NET 程序集”,后者是存储在文件系统中的动态链接库 (DLL) 文件(通常存储在与数据库相同的机器上)。 .NET 程序集将被加载到一个名为 extproc.exe 的“CLR 宿主”外部进程中并在其中运行,该进程由名为 <OracleHomeName>ClrAgnt 的 Windows 服务衍生而来。 当执行 .NET 存储过程调用时,Oracle 将与这个外部进程通信,传入参数并检索结果。 这种通信将由 Oracle 多线程代理体系结构来处理。 对于最终用户而言,.NET 存储过程调用看起来与任何其他类型的存储过程调用没有什么区别。 实际上,您可以从能够调用 PL/SQL 或 Java 存储过程的任何环境中调用 .NET 存储过程。
安装和配置:
如果您使用的是 Oracle 数据库 10g Express 版本,那么,.NET 存储过程将自动进行安装和配置 — 无需额外的配置。 但是,在标准版和企业版中,默认情况下不会安装和配置 .NET 存储过程。 以下是使这些安装正常运行的基本指导:
- 下载针对 Windows 平台的 Oracle 数据库 10.2 或更高版本。(注意: 其他任何平台都不支持 .NET 存储过程!)
- 运行安装程序 (setup.exe)。
- 选择 Advanced Installation,然后选择 Custom。
- 请务必和其他的安装选择一起勾上 Oracle Database Extensions for .NET。
- 当安装完成时,运行 Database Configuration Assistant(从开始菜单中选择 Oracle > Configuration > Migration Tools)。
- 在配置助手中,选择配置 Oracle Database Extensions for .NET 数据库选项。
- 当完成时,请确保 <OracleHome>ClrAgent 服务已启动。
- 下载 Oracle Developer Tools for Visual Studio .NET 版本 10.2 或更高版本,并进行安装。 需要该版本才能部署 .NET 存储过程。
开发和部署 .NET 存储过程
您将开发和部署一个简单但功能齐全的 .NET 存储过程,该过程将根据国家/地区代码来检索国家/地区名称。 您将使用 HR 示例模式中的 Countries 表,Oracle 数据库 10g 第 2 版包含了该示例模式。Countries 表结构如下:
SQL> desc countries Name Null?Type -------------- -------- ------------ COUNTRY_ID NOT NULL CHAR(2) COUNTRY_NAME VARCHAR2(40) REGION_ID NUMBER要创建存储过程,请使用 Visual Studio .NET 2003 中的一种新项目类型 — "Oracle Project":
创建一个新的 Oracle 项目(名称为 "MyStoredProcedure"),您将看到项目向导已经添加了一条到 Oracle Data Provider for .NET 程序集的引用,并将 ODP.NET 命名空间添加到了类文件中。 Visual Studio .NET 2003 开发环境应与下图类似:
您用您的代码来替换由项目向导创建的 StoredProcedure1 过程,以从 Countries 表中获取国家/地区名称。 您的新过程将接收国家/地区 ID 作为一个整型参数,并将国家/地区名称作为一个字符串值返回。 在开发过程时要注意的关键一点是 .NET 存储过程中的代码与您在独立的程序中使用的代码几乎相同。 事实上,唯一的区别是用来建立与数据库的连接的连接字符串。 下面是完整的代码:
using System; using System.Data; using Oracle.DataAccess.Client; using Oracle.DataAccess.Types; namespace MyStoredProcedure { ///同样,除了特殊的连接字符串之外,这些代码和您要在客户端应用程序中包含的代码是相同的。 通过上下文 connection=true,您将指定代码使用调用它的进程的连接,并且您只可以在存储过程内部指定上下文 connection=true。 OracleConnection 有一个名为 IsAvailable 的新属性,您可以用它来确定代码是否在存储过程的上下文中运行。 如果 IsAvailable 属性返回 true,那么代码是在存储过程的上下文中运行的。 否则该属性将返回 false。 根据代码是在存储过程中运行还是在独立的应用程序中运行,您可以轻松地使用该属性来构建连接字符串。 这使您只需进行少许修改就可重用代码。/// Summary description for Class1. /// public class Class1 { public static string GetCountryName(string CountryID) { // used to return the country name string CountryName = ""; // Get a connection to the db // context connection is used in a stored procedure OracleConnection con = new OracleConnection(); con.ConnectionString = "context connection=true"; con.Open(); // Create command and parameter objects OracleCommand cmd = con.CreateCommand(); cmd.CommandText = "select country_name from countries where country_id = :1"; cmd.Parameters.Add(":1", OracleDbType.Varchar2, CountryID, ParameterDirection.Input); // get a data reader OracleDataReader rdr = cmd.ExecuteReader(); // get the country name from the data reader if(rdr.Read()) { CountryName = rdr.GetString(0); } // clean up objects rdr.Close(); cmd.Dispose(); // Return the country name return CountryName; } } }
在部署存储过程之前,您必须首先构建该项目。 因为您将在部署过程之后对其进行调试,因此请务必对项目执行调试编译。 在构建项目之后,您将利用部署向导来将其部署至数据库。 这时,您必须使用到数据库的 SYSDBA 连接,以部署存储过程。 如果在 Oracle Developer Tools for Visual Studio .NET 内部的 Data Connection 节点中没有提供 SYSDBA 连接,那么您可通过该向导创建一个。
要部署存储过程,请从 Visual Studio .NET 2003 菜单栏中选择 Build→ Deploy Solution。 这将启动部署向导:
阅读完向导第一步中的信息之后,请单击 Next。 然后,向导将提示您选择要使用的数据库连接。 如果您还没有定义数据库连接,那么请单击 New Connection 按钮。 否则,请选择您想使用支持 SYSDBA 的连接。
选择了要使用的数据库连接之后,请单击 Next 按钮。 您可在向导中的这一步中选择希望使用的部署选项。 因为您还没有部署该过程,所以请接受默认选项来部署该程序集,并在数据库中创建存储过程包装程序:
单击 Next 按钮继续。 指定将在部署项目之后使用的 DLL 的名称:
接受由向导提供的默认值,并单击 Next,指定要将项目部署至其中的目录:
只需单击 Next,接受默认值。 这将把项目部署至 %ORACLE_HOME%\bin\clr 目录。 下一步中,您可以指定要部署哪些方法、方法应被部署到哪个模式中、数据库中的方法名、安全级别和类型映射:
要正确地部署项目,请选择 GetCountryName 方法,选择 HR 作为模式,接受提供的数据库方法名,并接受提供的安全级别。
以下是三种可用的安全级别:
- 安全 (Safe): 只允许访问数据库资源。 不允许访问诸如本地文件系统或网络连接之类的资源
- 外部 (External): 允许访问诸如文件系统和网络连接之类的资源
- 不安全 (Unsafe): 无限制
向导将根据代码中的 .NET 类型来选择值。 如果这些值正确,即可接受它们。
部署向导中的最后一步概述了选择的选项,并允许您查看要执行的操作的脚本。 要执行实际的部署,请单击 Finish 按钮。 一旦部署完成,您可通过查看部署目录来验证是否已创建文件:
C:\>dir c:\oracle\10.2\database\bin\clr Volume in drive C is Local Disk Volume Serial Number is 94FF-538C Directory of c:\oracle\10.2\database\bin\clr 09/10/2005 07:18 PM <DIR> . 09/10/2005 07:18 PM <DIR> .. 09/10/2005 07:18 PM 16,384 MyStoredProcedure.dll 1 File(s) 16,384 bytes 2 Dir(s) 26,689,114,112 bytes free您可以使用 SQL*Plus 来验证过程是否被正确部署以及是否运行正常:
SQL*Plus: Release 10.2.0.1.0 - Production on Sat Sep 10 19:21:47 2005 Copyright (c) 1982, 2005, Oracle.All rights reserved. SQL> connect hr Enter password: Connected. SQL> select GetCountryName('FR') from dual; GETCOUNTRYNAME('FR') --------------------------------------------------------------------- France 1 row selected.您还可以使用 Oracle Developer Tools for Visual Studio .NET 来运行该过程。 要执行这一操作,请展开 HR 连接,展开 Functions 节点,选择 GETCOUNTRYNAME 函数,单击右键,并选择 Run:
这将生成 Run Function 对话框:
输入 FR 并单击 OK 按钮。 这将在 Visual Studio .NET 2003 IDE 中生成以下结果窗口:
调试 .NET 存储过程
要从 Visual Studio .NET 2003 IDE 内部调试已部署的存储过程,您需要将程序调试数据库 (Program Debug Database) 文件复制到部署 DLL 的目录中。 将 MyStoredProcedure.pdb 文件复制到 %ORACLE_HOME%\bin\clr 目录中:
C:\>dir c:\oracle\10.2\database\bin\clr Volume in drive C is Local Disk Volume Serial Number is 94FF-538C Directory of c:\oracle\10.2\database\bin\clr 09/10/2005 07:32 PM <DIR> . 09/10/2005 07:32 PM <DIR> .. 09/10/2005 07:18 PM 16,384 MyStoredProcedure.dll 09/10/2005 06:44 PM 11,776 MyStoredProcedure.pdb 2 File(s) 28,160 bytes 2 Dir(s) 26,681,720,832 bytes free该目录现在包含 DLL 和 .pdb 文件。
因为 DLL 文件是由 extproc.exe 进程加载的,因此您必须在 Visual Studio .NET 2003 中附加到该进程上去,以对其进行调试。 因为在前一步中执行了存储过程,因此 extproc.exe 进程应当正在运行。 但是,如果还没有执行该过程,那么该进程就没有处于运行中。 因此,在试图调试代码之前,应当通过 SQL*Plus 或 Oracle Developer Tools for Visual Studio .NET 来执行该过程。
要调试该过程,请在源代码中设置断点,如下所示:
接下来,请从 Visual Studio .NET 2003 菜单栏中选择 Tools → Debug Processes。 这将生成 Process 对话框。 向下滚动 Available Processes 的列表,并选择 extproc.exe:
单击 Attach 按钮,附加到 extproc.exe 进程上去。 这将生成 Attach to Process 对话框:
因为您开发的过程是一个 .NET 过程,所以请确保选中了 Common Language Runtime 复选框,并取消选择其他所有的复选框。 单击 OK 按钮,关闭“Attach to Process”对话框,并返回至“Processes”对话框。 在“Process”对话框中单击 Close 按钮,开始调试过程。
要启动进程并触发断点,您必须调用过程。 在 Visual Studio 的 Oracle Query 窗口中或从 SQL*Plus 会话中调用过程,如下所示:
SQL> select GetCountryName('FR') from dual;注意: 如果 .NET 过程的断点是在 Visual Studio 的同一个例程中设置的,那么请不要使用 Oracle Explorer“Run”菜单项来启动该过程。 这将由于死锁而挂起 Visual Studio。
该调用操作将调用过程,SQL*Plus 将看起来是挂起状态。 不过,该过程将在 Visual Studio .NET 2003 中停止在断点处。
您现在可以象通常处理独立代码一样来调试过程。
在调试附加进程与调试独立代码之间有一个重要的区别。 因为 extproc.exe 进程是在开发环境外部的,因此进程可能终止或被破坏,而调试环境检测不到这种情况。 在这种情况下,您将看到如下所示的错误:
SQL> select GetCountryName('FR') from dual * ERROR at line 1: ORA-28576: lost RPC connection to external procedure agent ORA-06512: at SYS.DBMS_CLR, line 234 ORA-06512: at HR.GETCOUNTRYNAME, line 7如果您遇到这种错误,请重新执行对存储过程的调用,这一般将重启 extproc.exe 进程。 其他的故障诊断技巧包括:关闭和重连调用程序的连接以及破坏 extproc.exe 并重启 CLR 服务(强迫重新衍生 extproc.exe)。
结论
在这篇介绍性的文章中,我们着眼于针对 Windows 平台的 Oracle 数据库 10g 第 2 版中对 .NET 存储过程的支持,并介绍了如何支持 .NET 存储过程,如何配置 Oracle 网络连接组件,如何开发和部署 .NET 存储过程,以及如何调试部署的过程。 您现在应当已经能够在自己的环境中开发和部署 .NET 存储过程了。
来源:
http://www.oracle.com/technology/global/cn/pub/articles/mastering_dotnet_oracle/williams_sps.html