在 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 存储过程。 以下是使这些安装正常运行的基本指导:
  1. 下载针对 Windows 平台的 Oracle 数据库 10.2 或更高版本。(注意: 其他任何平台都不支持 .NET 存储过程!)
  2. 运行安装程序 (setup.exe)。
  3. 选择 Advanced Installation,然后选择 Custom。
  4. 请务必和其他的安装选择一起勾上 Oracle Database Extensions for .NET。
  5. 当安装完成时,运行 Database Configuration Assistant(从开始菜单中选择 Oracle > Configuration > Migration Tools)。
  6. 在配置助手中,选择配置 Oracle Database Extensions for .NET 数据库选项。
  7. 当完成时,请确保 <OracleHome>ClrAgent 服务已启动。
  8. 下载 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":

 

图 1

 

创建一个新的 Oracle 项目(名称为 "MyStoredProcedure"),您将看到项目向导已经添加了一条到 Oracle Data Provider for .NET 程序集的引用,并将 ODP.NET 命名空间添加到了类文件中。 Visual Studio .NET 2003 开发环境应与下图类似:

 

图 2

 

您用您的代码来替换由项目向导创建的 StoredProcedure1 过程,以从 Countries 表中获取国家/地区名称。 您的新过程将接收国家/地区 ID 作为一个整型参数,并将国家/地区名称作为一个字符串值返回。 在开发过程时要注意的关键一点是 .NET 存储过程中的代码与您在独立的程序中使用的代码几乎相同。 事实上,唯一的区别是用来建立与数据库的连接的连接字符串。 下面是完整的代码:
using System;
using System.Data;
using Oracle.DataAccess.Client;
using Oracle.DataAccess.Types;
namespace MyStoredProcedure
{
/// 
/// 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;
}
}
}
同样,除了特殊的连接字符串之外,这些代码和您要在客户端应用程序中包含的代码是相同的。 通过上下文 connection=true,您将指定代码使用调用它的进程的连接,并且您只可以在存储过程内部指定上下文 connection=trueOracleConnection 有一个名为 IsAvailable 的新属性,您可以用它来确定代码是否在存储过程的上下文中运行。 如果 IsAvailable 属性返回 true,那么代码是在存储过程的上下文中运行的。 否则该属性将返回 false。 根据代码是在存储过程中运行还是在独立的应用程序中运行,您可以轻松地使用该属性来构建连接字符串。 这使您只需进行少许修改就可重用代码。

 

在部署存储过程之前,您必须首先构建该项目。 因为您将在部署过程之后对其进行调试,因此请务必对项目执行调试编译。 在构建项目之后,您将利用部署向导来将其部署至数据库。 这时,您必须使用到数据库的 SYSDBA 连接,以部署存储过程。 如果在 Oracle Developer Tools for Visual Studio .NET 内部的 Data Connection 节点中没有提供 SYSDBA 连接,那么您可通过该向导创建一个。

 

要部署存储过程,请从 Visual Studio .NET 2003 菜单栏中选择 Build→ Deploy Solution。 这将启动部署向导:

 

图 3

 

阅读完向导第一步中的信息之后,请单击 Next。 然后,向导将提示您选择要使用的数据库连接。 如果您还没有定义数据库连接,那么请单击 New Connection 按钮。 否则,请选择您想使用支持 SYSDBA 的连接。

 

图 4

 

选择了要使用的数据库连接之后,请单击 Next 按钮。 您可在向导中的这一步中选择希望使用的部署选项。 因为您还没有部署该过程,所以请接受默认选项来部署该程序集,并在数据库中创建存储过程包装程序:

 

图 5

 

单击 Next 按钮继续。 指定将在部署项目之后使用的 DLL 的名称:

 

图 6

 

接受由向导提供的默认值,并单击 Next,指定要将项目部署至其中的目录:

 

图 7

 

只需单击 Next,接受默认值。 这将把项目部署至 %ORACLE_HOME%\bin\clr 目录。 下一步中,您可以指定要部署哪些方法、方法应被部署到哪个模式中、数据库中的方法名、安全级别和类型映射:

 

图 8

 

要正确地部署项目,请选择 GetCountryName 方法,选择 HR 作为模式,接受提供的数据库方法名,并接受提供的安全级别。

 

以下是三种可用的安全级别:
  • 安全 (Safe): 只允许访问数据库资源。 不允许访问诸如本地文件系统或网络连接之类的资源
  • 外部 (External): 允许访问诸如文件系统和网络连接之类的资源
  • 不安全 (Unsafe): 无限制
要指定数据库和 .NET 数据类型之间的输入和输出参数映射,请单击 Parameter Type Mapping 按钮:

 

图 9

 

向导将根据代码中的 .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

 

图 10

 

这将生成 Run Function 对话框:

 

图 11

 

输入 FR 并单击 OK 按钮。 这将在 Visual Studio .NET 2003 IDE 中生成以下结果窗口:

 

图 12

 

调试 .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 来执行该过程。

 

要调试该过程,请在源代码中设置断点,如下所示:

 

图 13

 

接下来,请从 Visual Studio .NET 2003 菜单栏中选择 Tools → Debug Processes。 这将生成 Process 对话框。 向下滚动 Available Processes 的列表,并选择 extproc.exe

 

图 14

 

单击 Attach 按钮,附加到 extproc.exe 进程上去。 这将生成 Attach to Process 对话框:

 

图 15

 

因为您开发的过程是一个 .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 中停止在断点处。

 

图 16

 

您现在可以象通常处理独立代码一样来调试过程。

 

在调试附加进程与调试独立代码之间有一个重要的区别。 因为 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

posted on 2006-05-14 10:54  Hussar  阅读(1472)  评论(0编辑  收藏  举报

导航