ADO.Net(C#)中怎么执行Oracle的存储过程

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ADO.Net(C#)中怎么执行Oracle的存储过程相关的知识,希望对你有一定的参考价值。

创建一个Oracle的存储过程,能完成根据id来查询,并在ADO.Net中获取它所返回的值,比如:表table1中有id,name,age,sex,email 字段,然后我要根据所传入存储过程的id来查出这些值,就像(select * from table where id = 所传入的值),这样的类型。求高手指点,谢谢。

SqlConnection conn=new SqlConnection ();
SqlCommand cmd = conn.CreateCommand();
cmd.CommandType = CommandType.StoredProcedure; //命令类型是存储过程
cmd.CommandText = "存储过程的名字";追问

是Oracle的,尤其是建立Oracle的存储过程,应为有返回集,所以不知道怎么弄了,还有怎么获取返回集,继续等高手指导,完成后加分。

参考技术A
这种问题我早就碰过了,使用多线程是一种非常不好的选择,你的系统随时都会崩溃。
办法其实非常简单,你只要使用ADO异步操作就可以了,完全不必建立多线程,当然这涉及ADO的高级应用,今天心情好,教你几招!(下面是我在VB中使用过的方法,DELPHI中同样也能使用ADO异步操作访问SQLSERVER)
之前先与SQL SERVER建立一个CONNECTION对象,将其CURSORLOCATION属性设置为adUseClient 然后用ADO CONNECTION的Execute方法异步执行存储过程即可
例如:con.CursorLocation = adUseClient
dim strSQL as String
strSQL="SQL语句或存储过程名及其参数" '语法必须正确
con.Execute strSQL, , adAsyncExecute 'adAsyncExecute指令异步操作
这样你的应用程序就不用等待存储过程执行完毕后才可执行后续代码了。

你还可以使用ADO CONNECTION对象的ExecuteComplete事件在执行完存储过程后
通知你的应用程序执行相应的动作,例如MSGBOX等之类的东西,具体的实现代码你自己去查ADO联机手册。

另外顺便提一下,如果对于一个执行了很长时间都未能完成的查询,你别指望使用貌似很行的ADO的CANCEL方法,立即取消一个正在执行的ADO异步操作,即使在更新版本的ADO.net 3.5也是如此(非要等到超时后才能生效),真不明白微软的工程师们是如何想的!谁要是能给出解决方法,我奖他300分,外加现金若干。
答复补充问题:
“四楼的大哥 我还想问一下 如果我在这个存储过程还没有执行完成的时候 其他客户端又调用了这个存储过程 会不会出错呢???我不太清楚一个存储过程还没有执行完的时候 是否可以再次调用 请指教 谢谢!!!!”
不会的,因为SQLSERVER引擎会处理这些并发问题(自动使用事务处理,微软的工程师们早就想到这些问题了,请放心使用)追问

、、、copy 也不能这么搞啊,继续等高手解答。

从 C# 执行 Oracle 存储过程 - 调用中的参数数量或类型错误

【中文标题】从 C# 执行 Oracle 存储过程 - 调用中的参数数量或类型错误【英文标题】:Executing Oracle stored procedure from C# - wrong number or types of arguments in call 【发布时间】:2018-06-20 14:55:58 【问题描述】:

这是我描述存储过程时的输出:

 desc procedure_name  

 VCOMPTE    VARCHAR2                 IN            
 VRESULT    REF CURSOR               OUT           
 CLIENT_NO  VARCHAR2(6)              OUT           
 ACCT_NAME  VARCHAR2(35)             OUT           
 NCG        VARCHAR2(6)              OUT           
 NCG_DESC   VARCHAR2(35)             OUT           
 AGENCE     VARCHAR2(5)              OUT           
 TEL        VARCHAR2(50)             OUT

这是我用来执行它的 C# 代码:

public void Validate(string account_num)

    OracleConnection conn = new OracleConnection(HelperClass.GetConstring());         

    OracleCommand _cmdObj = conn.CreateCommand();
    _cmdObj.CommandText = "pk_xxx.procedure_name";
    _cmdObj.CommandTimeout = 1680;
    _cmdObj.CommandType = System.Data.CommandType.StoredProcedure;

    OracleParameter para_account_num = new OracleParameter();
    para_account_num.ParameterName = "VCOMPTE"; 
    para_account_num.OracleDbType = OracleDbType.Varchar2;
    para_account_num.Direction = System.Data.ParameterDirection.Input; 
    para_account_num.Value = account_num; 
    _cmdObj.Parameters.Add(para_account_num);

    OracleParameter VRESULT = new OracleParameter();
    VRESULT.ParameterName = "VRESULT";
    VRESULT.OracleDbType = OracleDbType.RefCursor;
    VRESULT.Direction = System.Data.ParameterDirection.ReturnValue;
    _cmdObj.Parameters.Add(VRESULT);

    OracleParameter client_no = new OracleParameter();
    client_no.ParameterName = "CLIENT_NO"; 
    client_no.OracleDbType = OracleDbType.Varchar2;
    client_no.Direction = System.Data.ParameterDirection.ReturnValue;
    _cmdObj.Parameters.Add(client_no);

    OracleParameter acct_name = new OracleParameter();
    acct_name.ParameterName = "ACCT_NAME";
    acct_name.OracleDbType = OracleDbType.Varchar2;
    acct_name.Direction = System.Data.ParameterDirection.ReturnValue;
    _cmdObj.Parameters.Add(acct_name);

    OracleParameter ncg = new OracleParameter();
    ncg.ParameterName = "NCG";
    ncg.OracleDbType = OracleDbType.Varchar2;
    ncg.Direction = System.Data.ParameterDirection.ReturnValue;
    _cmdObj.Parameters.Add(ncg);

    OracleParameter tr_desc = new OracleParameter();
    tr_desc.ParameterName = "NCG_DESC";
    tr_desc.OracleDbType = OracleDbType.Varchar2;
    tr_desc.Direction = System.Data.ParameterDirection.ReturnValue;
    _cmdObj.Parameters.Add(tr_desc);

    OracleParameter AGENCE = new OracleParameter();
    AGENCE.ParameterName = "AGENCE";
    AGENCE.OracleDbType = OracleDbType.Varchar2;
    AGENCE.Direction = System.Data.ParameterDirection.ReturnValue;
    _cmdObj.Parameters.Add(AGENCE);

    OracleParameter TEL = new OracleParameter();
    TEL.ParameterName = "TEL";
    TEL.OracleDbType = OracleDbType.Varchar2;
    TEL.Direction = System.Data.ParameterDirection.ReturnValue;
    _cmdObj.Parameters.Add(TEL);

    try
    
        conn.Open();

        OracleDataReader reader = _cmdObj.ExecuteReader();

        while (reader.Read())
        
            //I will use the data 
        
    
    catch (Exception xc)
    
        //catch xc 
    

但我得到一个错误

调用“procedure_name”时参数的数量或类型错误。”

调试对我来说很困难,因为我无法直接访问 Oracle 数据库,而且我不确定自己做错了什么。我已经在同一个数据库中成功执行了其他存储过程。提前致谢!

【问题讨论】:

ParameterDirection.ReturnValue只能有一个参数,即函数的返回值。使用ParameterDirection.Output 但是我的过程返回行而不是单个值。所有的输出类型实际上都是字段 无论如何,它们仍然是输出参数,而不是返回值。 ParameterDirection.ReturnValue只能用于函数,不能用于没有任何返回值的过程。 我已经尝试过了,但仍然没有运气。 【参考方案1】:

ExecuteReader() 仅用于函数,不用于过程。你必须使用ExecuteNonQuery()

ExecuteNonQuery() 之后你必须读取结果,例如

_cmdObj.ExecuteNonQuery();
OracleDataReader reader = ((OracleRefCursor)VRESULT.Value).GetDataReader();

或者创建一个类似

的函数
FUNCTION function_name RETURNS SYS_REFCURSOR

 VCOMPTE    VARCHAR2                 IN            
 CLIENT_NO  VARCHAR2(6)              OUT           
 ACCT_NAME  VARCHAR2(35)             OUT           
 NCG        VARCHAR2(6)              OUT           
 NCG_DESC   VARCHAR2(35)             OUT           
 AGENCE     VARCHAR2(5)              OUT           
 TEL        VARCHAR2(50)             OUT

然后这样称呼它

OracleCommand _cmdObj = conn.CreateCommand();
_cmdObj.CommandText = "pk_xxx.procedure_name";
_cmdObj.CommandType = CommandType.StoredProcedure;

_cmdObj.Parameters.Add("res", OracleDbType.RefCursor, ParameterDirection.ReturnValue);
_cmdObj.Parameters.Add("VCOMPTE", OracleDbType.Varchar2, ParameterDirection.Input).Value = account_num;
_cmdObj.Parameters.Add("CLIENT_NO", OracleDbType.Varchar2, ParameterDirection.Output);
_cmdObj.Parameters.Add("ACCT_NAME", OracleDbType.Varchar2, ParameterDirection.Output);
...
OracleDataReader reader = _cmdObj.ExecuteReader();

也许看看Data Provider for .NET Developer's Guide

【讨论】:

以上是关于ADO.Net(C#)中怎么执行Oracle的存储过程的主要内容,如果未能解决你的问题,请参考以下文章

使用 ADO.NET 获取 Oracle 包中过程的存储过程元数据

从 C# 调用 Oracle 存储过程?

由于C#中ADO.NET对Oracle的命名空间引用时提示过时,为此想用Linq对数据库的连接等操作(见补充)

ADO.NET操作Oracle问题

C#:通过 ADO.NET 在 SQL Server 2008 上运行事务

c#基础之ADO.NET