Выполнение процедуры из Visual Studio - PullRequest
0 голосов
/ 09 ноября 2018

Я пытаюсь выполнить процедуру pl \ sql из Visual Studio. По сути, я пытаюсь передать некоторые параметры и, используя их, пытаюсь вставить значения в другую таблицу. Процедура использует курсор и вставляет значения в таблицу, после чего я удаляю эту таблицу, чтобы использовать ее в следующий раз. Таблица, полученная с помощью курсора, должна быть окончательно отображена в сетке. Но приведенная ниже программа ничего не отображает. Может ли кто-нибудь помочь мне с этим?

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

Редактировать

enter image description here

Ответы [ 3 ]

0 голосов
/ 09 ноября 2018

Если вы установите тип хранимой процедуры, все, что вам нужно, это имя хранимой процедуры. Таким образом, командный текст должен быть cv, а не exec cv.

-edit-

Хотя вышеуказанная проблема также является проблемой, на скриншоте, который вы разместили в своем обновлении, предполагается, что соединение еще не открывается при вызове ExecuteNonQuery.

Или, может быть, он открыт, но не назначен команде. Поскольку приложение теоретически может иметь несколько соединений, вы должны указать команде, какое из них использовать. Не существует глобальной ссылки на соединение, которое команда будет использовать неявно. Пример, приведенный в документации Oracle , показывает, как это можно сделать с помощью свойства, хотя, очевидно, вы также можете установить его в конструкторе, что вы делаете для соединений 1 и 3, но не для соединения 2. Я думаю, что там это проблема. : О)

0 голосов
/ 09 ноября 2018

Ваш подход на самом деле не является "прямым путем", я бы сделал это так. Либо выберите таблицу напрямую:

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;

Вместо OracleDataAdapter и OracleDataAdapter вы также можете использовать 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();
}

OracleDataReader и OracleDataAdapter также реализуют IDisposal, поэтому он также должен быть заключен в using

0 голосов
/ 09 ноября 2018

Вам может понадобиться коммит; до конца;

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...