【问题标题】:Executing procedure from Visual Studio从 Visual Studio 执行过程
【发布时间】:2018-11-09 15:49:30
【问题描述】:

我正在尝试从 Visual Studio 执行 pl\sql 过程。基本上我想要做的是传递一些参数并使用它们我试图将值插入到不同的表中。该过程使用游标并将值插入表中,之后我将删除该表以供下次使用。使用 cursor 获得的表格需要最终显示在 gridbox 上。但是下面的程序没有显示任何内容。有人可以帮我解决这个问题吗?

DB_connect();

String x3 = "google";
String x1;
String x2;

String s1 = "delete from temp";

OracleCommand comm = new OracleCommand(s1, conn);
comm.ExecuteNonQuery();

System.Data.OracleClient.OracleCommand comm2 = new System.Data.OracleClient.OracleCommand();
String s2 = "exec cv";

comm2.CommandText = s2;
comm2.CommandType = CommandType.StoredProcedure;
comm2.Parameters.Add("x", System.Data.OracleClient.OracleType.Number).Value = comboBox1.Text;
comm2.Parameters.Add("y", System.Data.OracleClient.OracleType.Number).Value = comboBox2.Text;
comm2.ExecuteNonQuery();

String s3 = "select * from temp";

OracleCommand comm3 = new OracleCommand(s3, conn);
OracleDataAdapter MyAdapter3 = new OracleDataAdapter();//adapter acts as interface btw database and dataset(which is collectio of tables)
MyAdapter3.SelectCommand = comm;

DataTable dTable3 = new DataTable();//datatable represents a single table in database 
MyAdapter3.Fill(dTable3);

dataGridView1.DataSource = dTable3;
conn.Close();

这是我的存储过程:

create or replace procedure cv(x in int, y in int, z in varchar)
as
    cursor c
    is
        select email, collegename, cgpa, compname
        from student_cv
        where (cgpa >= x and yearsofexp >= y) and compname = z;

    tem c%rowtype;

    begin
       open c;
       loop
           fetch c into tem;
           exit when c%notfound;

           insert into temp 
           values(tem.email, tem.collegename, tem.cgpa, tem.compname);
       end loop;
    end;
/

编辑

【问题讨论】:

  • 您是否测试过该过程实际上返回了任何值?
  • 我的程序在 sql plus 中运行,但在从 Visual Studio 执行此程序时出现此错误
  • 一般来说,最好只运行一个查询或一个视图,甚至创建一个返回对象/行类型、对象表,甚至是你的引用的函数可以打开和阅读。写入临时数据只是为了在另一端读取它应该是最后的后备。
  • 打开您的连接:conn.Open(); 您对数据存储执行任何操作之前。也不清楚conn 的位置。这是某个地方的全局(静态)字段吗?如果是这样,可能存在多个线程同时尝试打开/关闭此连接的竞争条件(例如具有多个请求的 Web 应用程序)。

标签: c# sql .net oracle visual-studio


【解决方案1】:

如果将类型设置为存储过程,则只需要存储过程的名称即可。所以命令文本应该是cv 而不是exec cv

-编辑-

虽然上述问题也是一个问题,但您在更新中发布的屏幕截图表明,当您致电 ExecuteNonQuery 时,连接尚未打开。

或者它可能已打开,但未分配给命令。由于应用程序理论上可以有多个连接,因此您必须告诉命令使用哪一个。该命令将隐式使用的连接没有全局引用。 The example given in Oracle's documentation 显示了如何通过属性来完成此操作,尽管显然您也可以在构造函数中设置它,您可以为连接 1 和 3 而不是连接 2。我猜有问题。 :o)

【讨论】:

  • 连接在 Db_connect 函数中打开
  • 是的,但请查看错误。它说“连接已关闭”。此错误不在存储过程中,甚至可能不在您调用存储过程的方式中(除了我提到的内容),但事实上您的应用程序(或您的命令或查询,准确地说)没有有一个数据库连接。
  • no 已连接,我在数据连接中检查了它
  • 连接是否分配给命令?再看一下代码,好像没有给comm2赋值。
【解决方案2】:

您的方法并不是真正的“直接路径”,我会这样做。要么直接选择表:

var s1 = "select email, collegename, cgpa, compname from student_cv 
       where (cgpa >= :x and yearsofexp >= :y) and compname = :z";
OracleCommand comm = new OracleCommand(s1, conn);
comm.Parameters.Add("x", OracleType.Number).Value = comboBox1.Text;
comm.Parameters.Add("y", OracleType.Number).Value = comboBox2.Text;
comm.Parameters.Add("z", OracleType.VarChar2).Value = "some text";

OracleDataAdapter da = new OracleDataAdapter(comm);
DataTable dt = new DataTable();
da.Fill(dt);
dataGridView1.DataSource = dt;

您也可以使用OracleDataAdapterOracleDataAdapter 代替OracleDataReader

OracleDataReader dr = comm.ExecuteReader();
while ( dr.Read() ) {
   // loop through the rows and process the rows one-by-one
}
dr.close();

另一种方法是使用这样的函数或过程:

create or replace FUNCTION cv (x in int, y in int, z in varchar2) RETURN SYS_REFCURSOR as
   res SYS_REFCURSOR;
BEGIN
   OPEN res FOR
   select email, collegename, cgpa, compname
   from student_cv
   where (cgpa >= x and yearsofexp >= y) and compname = z;

   RETURN res;
end;

然后在 C# 中这样调用它:

comm.CommandType = CommandType.Text;
comm.CommandText = "BEGIN :ret := cv(:x, :y, :z); END;";
comm.Parameters.Add("x", OracleType.Number).Value = comboBox1.Text;
comm.Parameters.Add("y", OracleType.Number).Value = comboBox2.Text;
comm.Parameters.Add("z", OracleType.VarChar2).Value = "some text";
comm.Parameters.Add("ret", OracleDbType.RefCursor, ParameterDirection.ReturnValue);

OracleDataAdapter da = new OracleDataAdapter(comm);
DataTable dt = new DataTable();
da.Fill(dt);
dataGridView1.DataSource = dt;

当然,你也可以像上面一样使用OracleDataReader

请注意,我面前没有用于任何测试的计算机,所以如果我在代码示例中出现一两个错别字,请见谅。

关于您的实际错误信息,请确保顺序正确:

  1. 打开连接
  2. 执行命令(或多个命令)
  3. 关闭连接

由于OracleConnection 实现IDisposal,您应该像这样用using 将其括起来

using (var conn = new OracleConnection() ) {
   conn.ConnectionString = "Data Source=...";
   conn.Open();
   // Code from above

   conn.Close();
}

OracleDataReaderOracleDataAdapter 也实现了IDisposal,所以也应该用using 括起来

【讨论】:

    【解决方案3】:

    您可能需要提交;结束前; ?

    【讨论】:

      猜你喜欢
      • 2021-05-27
      • 2013-05-11
      • 1970-01-01
      • 2018-02-09
      • 1970-01-01
      • 2014-05-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多