2010-08-20 2 views
9

У меня есть пакет oracle с процедурой, в которой есть указатель out. Я понимаю, что это довольно стандартно.Выполнить функцию oracle, которая возвращает ссылочный курсор в C#

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

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

Вот функция

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, а с тем же результатом.

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

mypackage.getquestionsForPrint('OMG Poinies'); 

и

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

Использование Аби-х изменение для командного текста

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

привело

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

Я просто лаю по неправильному дереву?

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

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

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

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

Final Edit (надеюсь)

Видимо Guddie задал similar question 3 месяца после того, как я сделал. Он получил ответ, который должен

  • Установите текст команды на анонимный блок
  • Bind параметр в исх задающего направление выхода
  • вызова Execute нон читателя курсора.
  • Затем используйте ваш параметр

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(); 
} 
+0

Нет такой вещи, как «racleCommand», после реального кода. –

+0

Извините, пропустил его на копии, как –

+1

Конрад, вам не нужна обертка - я обновил предыдущий вопрос. Не знаю, C#, поэтому не могу комментировать эту часть. Лично - и я уверен, что многие люди меня застрелили бы - я бы сказал, что процедура должна выполнять некоторую работу и может влиять как на данные, которые есть и не переданы (что вы не делаете обязательно знать), а функция должна возвращать результат на основе переданных данных и предпочтительно не иметь побочных эффектов. Но это то, что наиболее подходит для того, что вы делаете. Возвращение назад и изменение старого кода вряд ли добавят многого, я бы подумал. –

ответ

5

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

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

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

ParameterDirection.ReturnValue 

Я использую Oracle.DataAccess версии 2.111.6.0

+0

Что бы вы ожидали от имени имени вывода параметр должен быть? Я попробовал несколько альтернатив –

+0

@Conrad Frix Я считаю, что вы можете присвоить ему любое имя, которое вы хотите, указав направление параметра в качестве возвращаемого значения, которое оно отобразило бы, я еще не тестировал это. Я также наткнулся на эту ссылку [return ref_cursor from function] (http://stackoverflow.com/questions/4125992/how-to-return-a-refcursor-from-oracle-function/4126886#4126886). Они используют ExecuteNonQuery и получают доступ к курсору через параметр. Это альтернативный способ поиска? –

+0

это сделал. Наслаждайтесь своим значком возрождения –

0

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

0

Я знаю, что это довольно старый пост, но так как он принял мне так долго, чтобы разобраться во всех мелочах, участвующих в том, чтобы .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.

Смежные вопросы