Выполните функцию oracle, которая возвращает ссылочный курсор в C#

у меня есть пакет oracle с процедурой, которая имеет курсор ссылки in out. Насколько я понимаю, это довольно стандартно.

что мне не понравилось, так это то, что мне пришлось писать кучу кода, чтобы просто увидеть результат. поэтому я задал этот вопрос и оказывается, я могу получить то, что хочу, создав функцию, которая обертывает процедуру.

обновление: Похоже, мне больше не нужна функция, но, возможно, стоит знать во всяком случае, для любопытных см. оригинальные обновления вопросов и ответов.

здесь функция

FUNCTION GetQuestionsForPrint (user in varchar2)
  RETURN MYPACKAGE.refcur_question
AS  

    OUTPUT MYPACKAGE.refcur_question;

BEGIN 

      MYPACKAGE.GETQUESTIONS(p_OUTPUT => OUTPUT, 
      p_USER=> USER ) ;


  RETURN OUTPUT;
END;

и вот что я делаю, чтобы выполнить его в SQL Developer

var r refcursor;
exec :r := mypackage.getquestionsForPrint('OMG Ponies');
print r;

поэтому с этого момента я, вероятно, добавлю функции ForPrint ко всем моим процедурам.

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

чтобы проверить это, я попытался выполнить функцию из .NET, за исключением того, что я не могу сделать он. Это действительно так.

using (OracleConnection cnn = new OracleConnection("Data Source=Test;User Id=Test;Password=Test;"))
{
    cnn.Open();
    OracleCommand cmd = new OracleCommand("mypackage.getquestionsForPrint");
    cmd.CommandType = System.Data.CommandType.StoredProcedure;

    cmd.Parameters.Add ( "p_USER", "OMG Ponies");

    cmd.Connection = cnn;
    OracleDataReader rdr = cmd.ExecuteReader();

    while (rdr.Read())
    {
        Console.WriteLine(rdr.GetOracleValue(0));
    }

    Console.ReadLine();
}

Итак, я получаю ошибку.

getquestionsForPrint is not a procedure or is undefined

Я также попробовал ExecuteScalar с тем же результатом.

редактировать принимая совет Slider345, я также попытался установить тип команды в текст и использовать следующий оператор, и я получаю неверный SQL запрос:

mypackage.getquestionsForPrint('OMG Poinies');

и

var r refcursor; exec :r :=  mypackage.getquestionsForPrint('OMG Poinies'); 

использование варианта Abhi для текста команды

select mypackage.getquestionsForPrint('OMG Poinies') from dual

в результате

инструкция на " 0x61c4aca5" ссылочная память в "0x00000ce1". Этот память не может быть "прочитана".

Я просто обозналась?

обновление Попытка добавить выходной параметр не помогает.

cmd.Parameters.Add(null, OracleDbType.RefCursor, ParameterDirection.Output);

не уверен, что имя должно быть так как его возвращаемое значение функции (у меня есть пробовал null, пустую строку, mypackage.getquestionsForPrint), но во всех случаях это просто приводит к

ORA-06550: строка 1, колонка 7: PLS-00306: неправильный номер или типы аргументы в вызове 'getquestionsForPrint'

окончательное редактирование (надеюсь)

видимо Guddie спросил аналогичный вопрос через 3 месяца после меня. Он получил ответ:

  • установите текст команды в анонимный блок
  • привязать параметр к курсору ref, устанавливающему направление вывода
  • вызов Execute non reader.
  • тогда используйте свой параметр

using (OracleConnection cnn = new OracleConnection("Data Source=Test;User Id=Test;Password=Test;"))
{
    cnn.Open();
    OracleCommand cmd = new OracleCommand("mypackage.getquestionsForPrint");
    cmd.CommandType = CommandType.Text;

    cmd.CommandText = "begin " +
              "    :refcursor1 := mypackage.getquestionsForPrint('OMG Ponies') ;"  +
              "end;";

    cmd.Connection = cnn;
    OracleDataAdapter da = new OracleDataAdapter(cmd);
    cmd.ExecuteNonQuery();

    Oracle.DataAccess.Types.OracleRefCursor t = (Oracle.DataAccess.Types.OracleRefCursor)cmd.Parameters[0].Value;
    OracleDataReader rdr = t.GetDataReader();
    while(rdr.Read())
        Console.WriteLine(rdr.GetOracleValue(0));

    Console.ReadLine();
}

3 ответов


Я не тестировал это с помощью функции, но для моих хранимых процедур. Я указываю параметр out для refCursor.

command.Parameters.Add(new OracleParameter("refcur_questions", OracleDbType.RefCursor, ParameterDirection.Output));

Если вы можете заставить функцию работать с CommandType.Текст. Интересно, можете ли вы попробовать добавить параметр выше, кроме направления как:

ParameterDirection.ReturnValue

Я использую Oracle.Доступа к данным версия 2.111.6.0


Я предполагаю, что вы не можете вызвать функцию с объектом команды типа "StoredProcedure". Можете ли вы попробовать объект команды типа "текст" и выполнить функцию в тексте команды?


Я знаю, что это довольно старый пост, но так как мне потребовалось так много времени, чтобы выяснить все мелочи, связанные с получением .NET, чтобы "хорошо сражаться" с Oracle, я решил, что я бы поставил этот совет там для кого-либо еще в этой липкой ситуации.

Я часто вызываю хранимые процедуры Oracle, которые возвращают REF_CURSOR в нашей среде (.NET 3.5 против Oracle 11g). Для функции вы действительно можете назвать параметр как угодно, но затем вам нужно установить его System.Data.ParameterDirection = ParameterDirection.ReturnValue тогда ExecuteNonQuery на OracleCommand "объект". В этот момент значением этого параметра будет ref_cursor, возвращаемый функцией Oracle. Просто приведите значение как OracleDataReader и петля через OracleDataReader.

Я бы опубликовал полный код, но я написал уровень доступа к данным в VB.NET много лет назад, и основная часть кода, потребляющего уровень доступа к данным (наша корпоративная интрасеть), находится в C#. Я решил, что смешивание языков в одном ответе будет большим faux pas.