【问题标题】:Calling Oracle stored procedure from C#?从 C# 调用 Oracle 存储过程?
【发布时间】:2011-04-25 19:56:42
【问题描述】:

如何从C#调用oracle中的存储过程?

【问题讨论】:

  • 你能发布存储过程吗?您使用哪些库来连接数据库? ADO.NET? ORM(nHibernate,EF)?如果您想要一个适合您需求的答案,您需要提供更多详细信息。
  • 如果您希望得到特定于 Oracle 的答案,请将您的问题标记为 Oracle。谢谢!
  • 我以前使用过基本的 SQL 查询。但是,现在我想调用已经编写好的 Oracle 过程,使用 C# 代码。

标签: c# .net oracle stored-procedures ado.net


【解决方案1】:

请访问这个由 oracle 为 Microsoft OracleClient 开发人员设置的 ODP 站点: 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?来自文档Default = 0. Setting this property to 0 defers the LONG and LONG RAW data retrieval entirely until the application specifically requests it.
【解决方案2】:

我现在已经掌握了从 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);的目的是什么吗?需要这条线吗?
【解决方案3】:

这与非查询命令的机制基本相同:

  • command.CommandText = 的名称 存储过程
  • command.CommandType = CommandType.StoredProcedure
  • 对 command.Parameters.Add 的调用次数与 sp 所需的参数数量一样
  • command.ExecuteNonQuery

有很多例子,谷歌返回的第一个是this one

还有一个你可能会陷入的小陷阱,如果你的 SP 是一个函数,你的返回值参数必须在参数集合中排在第一位

【讨论】:

    【解决方案4】:

    这段代码很适合我调用 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# 进行愉快的编码

    【讨论】:

      【解决方案5】:

      连接到 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();
          }
      

      【讨论】:

      • 谢谢,这真的很整洁。
      • 请注意,此示例使用 Oracle.ManagedDataAccess.Core nuget 包
      【解决方案6】:

      在 .Net 至版本 4 中,这可以与 SQL Server 存储过程相同的方式完成,但请注意您需要:

      using System.Data.OracleClient;
      

      some system requirements here,您应该验证在您的场景中是否正常。

      Microsoft 是deprecating this namespace as of .Net 4,因此将来需要第三方提供商。考虑到这一点,您最好使用 go 一词中的Oracle Data Provider for .Net (ODP.NET) - 这具有 Microsoft 类中没有的优化。还有其他第三方选项,但甲骨文在保留 .Net 开发人员方面拥有强大的既得利益,因此他们应该是好的。

      【讨论】:

        【解决方案7】:

        代替

        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);
        

        【讨论】:

          【解决方案8】:

          以下在 .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();
                          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2012-06-24
            • 1970-01-01
            • 1970-01-01
            • 2015-05-22
            • 2012-01-27
            • 2017-05-21
            • 1970-01-01
            相关资源
            最近更新 更多