从C#调用Oracle存储过程?

35

如何在C#中从Oracle调用存储过程?


2
你能发布存储过程吗?你使用哪些库来连接数据库?ADO.NET?ORM(nHibernate,EF)?如果你想得到满意的答案,你需要提供更多的细节。 - Oded
如果您期望得到Oracle特定的答案,请将您的问题标记为Oracle。谢谢! - tsimbalar
我以前使用过基本的SQL查询。但是现在我想使用C#代码调用已经编写好的Oracle存储过程。 - Rohan
8个回答

39
请访问由 Oracle 设立的 ODP 网站,以供 Microsoft OracleClient 开发人员使用: http://www.oracle.com/technetwork/topics/dotnet/index-085703.html 此外,下面提供了一个示例代码,可以帮助你从 C# 调用存储过程到 Oracle。PKG_COLLECTION.CSP_COLLECTION_HDR_SELECT 是在 Oracle 上构建的存储过程,接受参数 PUNIT、POFFICE、PRECEIPT_NBR,并将结果返回为 T_CURSOR。
using Oracle.DataAccess;
using Oracle.DataAccess.Client;

public DataTable GetHeader_BySproc(string unit, string office, string receiptno)
{
    using (OracleConnection cn = new OracleConnection(DatabaseHelper.GetConnectionString()))
    {
        OracleDataAdapter da = new OracleDataAdapter();
        OracleCommand cmd = new OracleCommand();
        cmd.Connection = cn;
        cmd.InitialLONGFetchSize = 1000;
        cmd.CommandText = DatabaseHelper.GetDBOwner() + "PKG_COLLECTION.CSP_COLLECTION_HDR_SELECT";
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.Parameters.Add("PUNIT", OracleDbType.Char).Value = unit;
        cmd.Parameters.Add("POFFICE", OracleDbType.Char).Value = office;
        cmd.Parameters.Add("PRECEIPT_NBR", OracleDbType.Int32).Value = receiptno;
        cmd.Parameters.Add("T_CURSOR", OracleDbType.RefCursor).Direction = ParameterDirection.Output;

        da.SelectCommand = cmd;
        DataTable dt = new DataTable();
        da.Fill(dt);
        return dt;
    }
}

为什么首选 InitialLONGFetchSize = 1000?来自文档的说明:默认值为 0。将此属性设置为 0 将完全推迟 LONG 和 LONG RAW 数据的检索,直到应用程序明确请求为止。 - KLIM8D

23

我现在已经掌握了从C#调用过程所需的步骤。

   //GIVE PROCEDURE NAME
   cmd = new OracleCommand("PROCEDURE_NAME", con);
   cmd.CommandType = CommandType.StoredProcedure;

   //ASSIGN PARAMETERS TO BE PASSED
   cmd.Parameters.Add("PARAM1",OracleDbType.Varchar2).Value = VAL1;
   cmd.Parameters.Add("PARAM2",OracleDbType.Varchar2).Value = VAL2;

   //THIS PARAMETER MAY BE USED TO RETURN RESULT OF PROCEDURE CALL
   cmd.Parameters.Add("vSUCCESS", OracleDbType.Varchar2, 1);
   cmd.Parameters["vSUCCESS"].Direction = ParameterDirection.Output;

   //USE THIS PARAMETER CASE CURSOR IS RETURNED FROM PROCEDURE
   cmd.Parameters.Add("vCHASSIS_RESULT",OracleDbType.RefCursor,ParameterDirection.InputOutput); 

   //CALL PROCEDURE
   con.Open();
   OracleDataAdapter da = new OracleDataAdapter(cmd);
   cmd.ExecuteNonQuery();

   //RETURN VALUE
   if (cmd.Parameters["vSUCCESS"].Value.ToString().Equals("T"))
   {
      //YOUR CODE
   }
   //OR
   //IN CASE CURSOR IS TO BE USED, STORE IT IN DATATABLE
   con.Open();
   OracleDataAdapter da = new OracleDataAdapter(cmd);
   da.Fill(dt);

希望这能有所帮助。

你能告诉我 OracleDataAdapter da = new OracleDataAdatper(cmd); 的目的是什么吗?这行代码是必需的吗? - AlbatrossCafe

8

连接Oracle很麻烦。以下代码使用了using语句,更加简洁。许多其他示例没有调用它们创建的对象上的IDisposable方法。

using (OracleConnection connection = new OracleConnection("ConnectionString"))
    using (OracleCommand command = new OracleCommand("ProcName", connection))             
    {
          command.CommandType = CommandType.StoredProcedure;
          command.Parameters.Add("ParameterName", OracleDbType.Varchar2).Value = "Your Data Here";
          command.Parameters.Add("SomeOutVar", OracleDbType.Varchar2, 120);
          command.Parameters["return_out"].Direction = ParameterDirection.Output;
          command.Parameters.Add("SomeOutVar1", OracleDbType.Varchar2, 120);
          command.Parameters["return_out2"].Direction = ParameterDirection.Output;
          connection.Open();
          command.ExecuteNonQuery();
          string SomeOutVar = command.Parameters["SomeOutVar"].Value.ToString();
          string SomeOutVar1 = command.Parameters["SomeOutVar1"].Value.ToString();
    }

谢谢,这真的很棒。 - Dave
1
请注意,此示例使用Oracle.ManagedDataAccess.Core NuGet包。 - Matthew

8

这基本上与非查询命令相同,具体操作如下:

  • command.CommandText = 存储过程的名称
  • command.CommandType = CommandType.StoredProcedure
  • 调用 command.Parameters.Add 函数添加所有存储过程所需的参数
  • command.ExecuteNonQuery

有很多示例可供参考,可以通过谷歌搜索获得。其中第一个示例链接是:这个

还有一个小陷阱,如果你的存储过程是一个函数,则返回值参数必须是参数集合中的第一个参数。


7
这段代码对我来说很有效,可以调用Oracle存储过程。
在解决方案资源管理器中右键单击项目名称>添加引用>.Net,然后添加命名空间。
using System.Data.OracleClient;
using System.Data;

然后将此代码粘贴到事件处理程序中。
        string str = "User ID=username;Password=password;Data Source=Test";
        OracleConnection conn = new OracleConnection(str);
        OracleCommand cmd = new OracleCommand("stored_procedure_name", conn);
        cmd.CommandType = CommandType.StoredProcedure;
        --Ad parameter list--
        cmd.Parameters.Add("parameter_name", "varchar2").Value = value;
        ....
        conn.Open();
        cmd.ExecuteNonQuery();

完成了...用C#愉快地编码吧


3
在 .Net 版本 4 及以下,可以像 SQL Server 存储过程一样完成此操作,但请注意需要:
using System.Data.OracleClient;

您需要验证在您的情况下一些系统要求是否OK,这里有一些系统要求

从.Net 4开始,Microsoft将停用此命名空间,因此未来需要第三方提供程序。考虑到这一点,最好从一开始就使用Oracle Data Provider for .Net (ODP.NET) - 它具有Microsoft类中没有的优化。还有其他第三方选项,但Oracle对于让.NET开发人员留在他们的平台上有很强的利益,所以他们的选项应该很不错。


2
最初的回答

与其

cmd = new OracleCommand("ProcName", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("ParName", OracleDbType.Varchar2, ParameterDirection.Input).Value = "foo";

您可以使用以下语法:

您也可以使用此语法:

cmd = new OracleCommand("BEGIN ProcName(:p0); END;", con);
cmd.CommandType = CommandType.Text;
cmd.Parameters.Add("ParName", OracleDbType.Varchar2, ParameterDirection.Input).Value = "foo";

请注意,如果您设置了cmd.BindByName = False(这是默认值),则必须按照命令字符串中编写参数的顺序添加参数,实际名称不相关。对于cmd.BindByName = True,参数名称必须匹配,但顺序无关紧要。
对于函数调用,命令字符串应如下所示:
cmd = new OracleCommand("BEGIN :ret := ProcName(:ParName); END;", con);
cmd.CommandType = CommandType.Text;
cmd.Parameters.Add("ret", OracleDbType.RefCursor, ParameterDirection.ReturnValue);    
cmd.Parameters.Add("ParName", OracleDbType.Varchar2, ParameterDirection.Input).Value = "foo";
// cmd.ExecuteNonQuery(); is not needed, otherwise the function is executed twice!
var da = new OracleDataAdapter(cmd);
da.Fill(dt);

0

以下代码适用于我的.NET Core解决方案。请注意它使用OracleDataReader和Oracle CommandType为CommandType.Text

using Oracle.ManagedDataAccess.Client;

.......

                string spSql = "BEGIN STORED_PROC_NAME(:IN_PARAM, :OUT_PARAM1, :OUT_PARAM2); END; ";

                using (OracleConnection oraCnn = new OracleConnection(cnnString))
                using (OracleCommand oraCommand = new OracleCommand(spSql, oraCnn))
                {
                    await oraCnn.OpenAsync(cancellationToken);
                    oraCommand.CommandType = CommandType.Text;
                    oraCommand.BindByName = true;

                    oraCommand.Parameters.Add("IN_PARAM", OracleDbType.Long, ParameterDirection.Input).Value = 123;
                    oraCommand.Parameters.Add("OUT_PARAM1", OracleDbType.Int32, null, ParameterDirection.Output);
                    oraCommand.Parameters.Add("OUT_PARAM2", OracleDbType.Varchar2, 4000, null, ParameterDirection.Output);

                    OracleDataReader objReader = oraCommand.ExecuteReader();

                    string outParamValue= oraCommand.Parameters["OUT_PARAM2"].Value.ToString();
                }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接