`
wsql
  • 浏览: 12102062 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
文章分类
社区版块
存档分类
最新评论

在.NET中调用Oracle9i存储过程经验总结

阅读更多

.NET中调用Oracle9i存储过程经验总结<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

.NET中调用Oracle9i存储过程可以用多个数据提供者,比如OralceClientOleDb。本文将用OralceClient为例。.NET语言用C#

一、调用一个带输入、输出参数的存储过程

首先,在Oralce中创建存储过程如下:

create or replace procedure GetRecords(name_out out varchar2,age_in in varchar2) as

begin

select NAME into name_out from test where AGE = age_in;

end;

然后,在C#项目中作如下调用:

string connectionString = "Data Source=YXZHANG;User ID=YXZHANG;Password=YXZHANG";

string queryString = "getrecords";

OracleConnection cn = new OracleConnection(connectionString);

OracleCommand cmd = new OracleCommand(queryString,cn);

cmd.CommandType = CommandType.StoredProcedure;

cmd.Parameters.Add("name_out",OracleType.VarChar,20);

cmd.Parameters["name_out"].Direction = ParameterDirection.Output;

cmd.Parameters.Add("age_in",21);

try

{

cn.Open();

cmd.ExecuteNonQuery();

Console.WriteLine("Name is:{0}",cmd.Parameters["name_out"].Value.ToString());

cn.Close();

}

catch( OracleException ex )

{

Console.WriteLine("Exception occurred!");

Console.WriteLine("The exception message is:{0}",ex.Message.ToString());

}

finally

{

Console.WriteLine("------------------End-------------------");

}

小结:

以上是很平常的调用方法,但是我在做这个示例程序的时候,却不是那么一帆风顺。这里要指出OracleClient的一个不尽如人意之处,就是对于参数名称,必须和存储过程定义中的参数同名,否则就会报错。比如将代码中的“name_out”改为别的名称的话,就会报异常。但我试着用OleDb代替OralceClient,却没有这个问题。不知道在新版本的数据提供程序中会否改进这一点?

二、调用不返回数据的存储过程

首先,在Oralce中创建存储过程如下:

create or replace procedure insertRecord(UserID in varchar2,

UserName in varchar2,
UserAge in varchar2) is
begin
insert into
test values (UserID, UserName, UserAge);
end;

然后,在C#项目中作如下调用:

string connectionString = "Data Source=YXZHANG;User ID=YXZHANG;Password=YXZHANG";

string queryString = "insertRecord";

OracleConnection cn = new OracleConnection(connectionString);

OracleCommand cmd = new OracleCommand(queryString,cn);

cmd.CommandType = CommandType.StoredProcedure;

cmd.Parameters.Add("UserID","007");

cmd.Parameters.Add("UserName","Dell");

cmd.Parameters.Add("UserAge","40");

try

{

cn.Open();

cmd.ExecuteNonQuery();

Console.WriteLine("Record inserted!");

cn.Close();

}

catch( OracleException ex )

{

Console.WriteLine("Exception occurred!");

Console.WriteLine("The exception message is:{0}",ex.Message.ToString());

}

finally

{

Console.WriteLine("------------------End-------------------");

}

小结:

不返回数据的存储过程一般有Delete, Insert, Update等。虽然它们的SQL语句不同,但是调用方面都是一样的。只要传入正确的参数,一般不会出什么问题。不过还是要注意,在使用OralceClient作为数据提供者的时候,参数名称一定要和存储过程定义中的一致!至于参数添加的顺序倒是无所谓的,因为有参数名称作为区别。

三、IDENTITY SEQUENCE

Sql Server中,定义一个列为递增列很容易,但我在Oracle中却怎么也找不到设置的方法。不过查了点资料后知道Oracle中有个叫Sequence的对象,产生一个唯一的序列号,类似于Sql Server中的IDENTITY。于是,我做了如下实验:

首先,在Oracle中创建了一个名为TEST_SEQSequence对象,SQL语句如下:

create sequence TEST_SEQ

minvalue 100

maxvalue 999

start with 102

increment by 1

nocache;

语法应该是比较易懂的,最小最大值分别用minvalue,maxvalue表示,初始值是102(这个数字是动态变化的,我创建的时候设的是100,后因插入了2条数据后就自动增加了2),increment当然就是步长了。在PL/SQL中可以用test_seq.nextval访问下一个序列号,用test_seq.currval访问当前的序列号。

定义完了Sequence,接下来就是创建一个存储过程InsertRecordWithSequence

--这次我修改了test表的定义,和前面的示例不同。其中,UserIDPK

create or replace procedure InsertRecordWithSequence(UserID out number,

UserName in varchar2,

UserAge in number)

is

begin

insert into test(id, name, age) --插入一条记录,PK值从Sequece获取

values(test_seq.nextval, UserName, UserAge);

/*返回PK值。注意Dual表的用法*/

select test_seq.currval into UserID from dual;

end InsertRecordWithSequence;

接下来,就是在C#中进行调用了:

string connectionString = "Data Source=YXZHANG;User ID=YXZHANG;Password=YXZHANG";

string queryString = "InsertRecordWithSequence";

OracleConnection cn = new OracleConnection(connectionString);

OracleCommand cmd = new OracleCommand(queryString,cn);

cmd.CommandType = CommandType.StoredProcedure;

cmd.Parameters.Add("UserID",OracleType.Number);

cmd.Parameters["UserID"].Direction = ParameterDirection.Output;

cmd.Parameters.Add("UserName","Jack");

cmd.Parameters.Add("UserAge",40);

try

{

cn.Open();

int rowAffected = cmd.ExecuteNonQuery();

Console.WriteLine("{0}行已插入。",rowAffected);

Console.WriteLine("插入行的ID为:{0}",cmd.Parameters["UserID"].Value.ToString());

cn.Close();

}

catch( OracleException ex )

{

Console.WriteLine("Exception occurred!");

Console.WriteLine("The exception message is:{0}",ex.Message.ToString());

}

finally

{

Console.WriteLine("------------------End-------------------");

}

小结:

使用Sequece对象可以很容易地创建唯一序列,在存储过程中的调用也十分方便,只要sequence_name.nextval以及sequence.currval就能得到下一个以及当前的序列值。倒是Dual表值得注意。

四、使用DataReader读取返回的结果集

为了让存储过程返回结果集,必须定义一个游标变量作为输出参数。这和Sql Server中有着很大的不同!并且还要用到Oracle中“包”(Package)的概念,似乎有点繁琐,但熟悉后也会觉得很方便。

关于“包”的概念,有很多内容可以参考,在此就不赘述了。首先,我创建了一个名为TestPackage的包,包头是这么定义的:

create or replace package TestPackage is

type mycursor is ref cursor; -- 定义游标变量

procedure GetRecords(ret_cursor out mycursor); -- 定义过程,用游标变量作为返回参数

end TestPackage;

包体是这么定义的:

create or replace package body TestPackage is

/*过程体*/

procedure GetRecords(ret_cursor out mycursor) as

begin

open ret_cursor for select * from test;

end GetRecords;

end TestPackage;

已经万事具备了,让我们前台调用试试:

string connectionString = "Data Source=YXZHANG;User ID=YXZHANG;Password=YXZHANG";

string queryString = "TestPackage.GetRecords"; //注意调用方法

OracleConnection cn = new OracleConnection(connectionString);

OracleCommand cmd = new OracleCommand(queryString,cn);

cmd.CommandType = CommandType.StoredProcedure;

cmd.Parameters.Add("ret_cursor",OracleType.Cursor); //注意这里的类型

cmd.Parameters["ret_cursor"].Direction = ParameterDirection.Output;

try

{

cn.Open();

OracleDataReader dr = cmd.ExecuteReader();

int i = 1;

while( dr.Read() )

{

Console.WriteLine("Record {0}:",i++);

Console.WriteLine("ID:{0} Name:{1} Age:{2}",

dr.GetOracleNumber(0),

dr.GetOracleString(1),

dr.GetOracleNumber(2));

Console.WriteLine();

}

dr.Close(); //用完DataReader对象要记得及时关闭

cn.Close(); //DataReader对象未关闭之前,不能关闭连接

}

catch( OracleException ex )

{

Console.WriteLine("Exception occurred!");

Console.WriteLine("The exception message is:{0}",ex.Message.ToString());

}

finally

{

Console.WriteLine("------------------End-------------------");

}

请看结果:

Record 1:

ID:100 Name:Tony Age:23

Record 2:

ID:101 Name:Jack Age:40

------------------End-------------------

小结:

包是Oracle特有的概念,Sql Server中找不到相匹配的东西。在我看来,包有点像VC++的类,包头就是.h文件,包体就是.cpp文件。包头只负责定义,包体则负责具体实现。如果包返回多个游标,则DataReader会按照您向参数集合中添加它们的顺序来访问这些游标,而不是按照它们在过程中出现的顺序来访问。可使用DataReaderNextResult()方法前进到下一个游标。

五、用返回的结果集填充DataSet

ADO.NET舍弃了原来ADORecordSet的概念,而使用全新的DataSet来替代。DataSet可以提供更加强大的功能!有了前面的基础,利用ADO.NETOralce返回DataSet也是非常简单的。主要思想就是用DataAdapter接收返回的游标,再用DataAdapterFill()方法填充数据集。在下面的例子中,我仍用了前一个例子中建好的TestPackage包。

下面是前台调用主要代码:

string connectionString = "Data Source=YXZHANG;User ID=YXZHANG;Password=YXZHANG";

string queryString = "TestPackage.GetRecords";

OracleConnection cn = new OracleConnection(connectionString);

OracleCommand cmd = new OracleCommand(queryString,cn);

cmd.CommandType = CommandType.StoredProcedure;

cmd.Parameters.Add("ret_cursor",OracleType.Cursor);

cmd.Parameters["ret_cursor"].Direction = ParameterDirection.Output;

try

{

cn.Open();

OracleDataAdapter da = new OracleDataAdapter(cmd);

DataSet ds = new DataSet();

da.Fill(ds,"TestTable");

cn.Close();

for( int i = 0;i <= ds.Tables["TestTable"].Rows.Count-1;i++ )

{

string id = ds.Tables["TestTable"].Rows[i]["ID"].ToString();

string name = ds.Tables["TestTable"].Rows[i]["NAME"].ToString();

string age = ds.Tables["TestTable"].Rows[i]["AGE"].ToString();

Console.WriteLine("Record {0}:",i+1);

Console.WriteLine("ID:{0}\tName:{1}\tAge:{2}\n",id,name,age);

}

}

catch( OracleException ex )

{

Console.WriteLine("Exception occurred!");

Console.WriteLine("The exception message is:{0}",ex.Message.ToString());

}

finally

{

Console.WriteLine("------------------End-------------------");

}

小结:

程序调用后的结果和刚才用DataReader调用的结果一样。这里只说明怎样利用ADO.NET调用Oracle存储过程,以及怎样填充至数据集中。至于怎样操纵DataSet,不是本文的讨论范围。有兴趣的读者可以参考MSDN以及相关书籍。

六、DataAdapter更新数据库

通常用DataAdapter取回DataSet,将会对DataSet进行一些修改,继而更新数据库(如果只是为了获取数据,微软推荐使用DataReader代替DataSet)。然而,通过存储过程更新数据库,并不是那么简单,不能简单地通过DataAdapterUpdate()方法进行更新。必须手动为DataAdapter添加InsertCommand, DeleteCommand, UpdateCommand,因为存储过程对这些操作的细节是不知情的,必须人为给出。

为了达成这个目标,我完善了之前的TestPackage包,包头如下:

create or replace package TestPackage is

background: #e6e6e6; margin: 0cm 0cm 0p

分享到:
评论

相关推荐

    在.NET中调用Oracle存储过程经验总结.doc

    ### 在.NET中调用Oracle存储过程经验总结 #### 一、引言 随着.NET平台的广泛应用,越来越多的应用程序选择.NET框架进行开发。与此同时,Oracle数据库因其高性能和稳定性被广泛采用。因此,在.NET环境中如何有效地...

    vb.net操作Oracle数据库增删改查以及存储过程调用1

    在 VB.NET 中,我们可以使用 OracleCommand 对象来调用存储过程。例如,我们可以使用以下代码来调用一个存储过程: ``` Dim cmd As New OracleCommand("my_procedure", Oracon) cmd.CommandType = CommandType....

    asp.net中调用oracle存储过程的方法

    在ASP.NET中调用Oracle存储过程是开发数据库驱动的应用程序时常见的操作。Oracle存储过程是一组预先编译的SQL和PL/SQL语句,能够提高性能、安全性,并简化复杂的数据库操作。以下是如何在ASP.NET中调用Oracle存储...

    Oracle9i安装 有图安装

    • 在.NET中调用Oracle9i存储过程经验 • Windows下Oracle9i数据库文件的自 • 图解Oracle9i在Windows2000下的安 • Linux环境下oracle9i的Dataguard配 • 修改oracle9i数据库字符集的方法 • windows优化系统...

    C#调用oracle方法(包括调用存储过程)

    ### C#调用Oracle方法(包括调用存储过程) 在.NET框架中,使用C#语言进行数据库操作是一项常见的任务。本文将详细介绍如何使用C#语言连接Oracle数据库,并演示如何调用Oracle存储过程,特别是带有输出参数的情况。...

    在ASP.NET中调用基于HTTP基本认证的WebService接口

    在 ASP.NET 中调用基于 HTTP 基本认证的WebService 接口 在 ASP.NET 中调用基于 HTTP 基本认证的WebService 接口是指在 ASP.NET 应用程序中调用基于 HTTP 基本认证的 Web 服务接口的方法。HTTP 基本认证是一种常用...

    springboot mybatis 动态调用oracle存储过程,通过存储过程名称,就能动态调用存储过程、java动态调用or

    能不能写个动态的业务,只输入存储过程名称,自动获取存储过程参数,并且参数的数据从前台传递过来...只根据输入不同的存储过程名称、参数内容,自动调用不同的存储过程。 已经使用在多个项目中 全开源项目 请放心下载

    asp.net使用oracle分页存储过程查询数据

    1、请先在Oracle数据中新建存储过程 2、修改代码中的相关参数。比如,连接数据库字符串,查询的sql语句等 注意:查询sql语句中必须包含rownum字段,别名是rn。rownum是Oracle关键字。 存储是来自...

    .Net动态调用WebService

    在.NET框架中,动态调用WebService是一项常见的任务,它允许开发者在运行时根据需要与Web服务进行交互,而无需在编译时明确指定服务接口。这通常涉及到使用System.Web.Services.ProtocolsSoapHttpClientProtocol类...

    Asp.Net中调用google地图(GooleMap)实例

    Asp.Net中调用GooleMap Asp.Net中调用google地图GooleMap实例 google地图 GooleMap实例 请访问:http://www.veisun.com(网站建设,软件开发)

    asp.net通过WebService调用Java接口全过程

    总结来说,ASP.NET通过WebService调用Java接口的过程主要包括:部署Java WebService、在.NET项目中添加Web引用、配置项目设置、在代码中实例化并调用服务方法,以及理解背后涉及的SOAP和RMI通信机制。这个过程允许...

    VB 调用oracle 带返回值的存储过程

    3. **调用存储过程**: 在VB中,我们需要创建一个OracleCommand对象,设置其CommandType为StoredProcedure,并指定存储过程的名称。然后,创建OracleParameter对象来处理存储过程的输入和输出参数。 ```vb Dim cmd ...

    用ADO.NET调用存储过程.ppt

    ADO.NET调用存储过程是数据库操作中的常见任务,它允许开发者高效地执行预编译的SQL语句集合,即存储过程。本章的目标是教会读者如何利用ADO.NET调用无参和带参的存储过程。 首先,回顾.NET数据提供程序的核心对象...

    asp.net网页调用本地摄像头源码

    在这个"asp.net网页调用本地摄像头源码"的项目中,开发者提供了一种方法让ASP.NET网页能够调用用户计算机上的摄像头。 首先,`index.html`是网页的主入口文件,可能包含了HTML代码以及JavaScript脚本,用于初始化...

    ASP.NET中调用存储过程的例子

    ASP.NET中调用存储过程的例子 ASP.NET中调用存储过程是一种常用的数据库交互方式。通过调用存储过程,可以实现复杂的业务逻辑和...在ASP.NET中,我们可以使用ADO.NET来调用存储过程,来实现复杂的业务逻辑和数据操作。

    asp.net前台调用后台方法传参数

    以上示例展示了如何在ASP.NET Web Forms项目中从前端调用后台方法并传递参数。需要注意的是,在实际开发中,这种方式并不推荐用于复杂的业务逻辑处理,因为这可能会导致安全性和可维护性方面的问题。对于更复杂的...

    asp.net实现oracle存储过程增删改查示例

    asp.net实现oracle存储过程增删改查示例 (1)三层架构实现 (2)oracle存储过程实现增删改查 (3)oracle sql语句实现增删改查 (4)asp.net代码调用 (5)ibatis框实现增删改查 我在公司学习了一个星期的作品,...

    VB.NET 2008调用SQL存储过程并返回值示例

    在VB.NET 2008中,调用SQL Server存储过程是常见的数据库操作之一,它允许程序员通过预先定义好的数据库函数来执行复杂的数据处理任务。本示例将深入讲解如何在VB.NET中调用存储过程,包括参数传递、接收返回值、...

    VB.net 调用本地摄像头实例

    在VB.NET编程中,调用本地摄像头是一项常见的需求,特别是在开发视频聊天、监控或图像处理应用时。本实例通过引入Windows API(用户界面程序设计接口)中的user32.dll和avicap32.dll动态链接库,实现了对摄像头硬件...

Global site tag (gtag.js) - Google Analytics