Возврат набора записей из Oracle в .Net с использованием функции Oracle, которая принимает аргументы - PullRequest
2 голосов
/ 14 ноября 2011

В настоящее время у меня есть следующая функция в базе данных оракула, которая возвращает объединенную строку, разделенную каналами.Это устаревшее приложение, которое обновляется для использования .net 3.5.Существующее приложение объединяет возвращенный набор результатов в тип данных VARCHAR2.То, что я хочу сделать, это вернуть весь набор результатов обратно в мой клиент .net.Эквивалент MS SQL того, что я пытаюсь сделать, - это простой «SELECT * FROM TBL WHERE id = @id», который я не использую для некоторых концепций, которые использует Oracle.Кажется, я не представлял собой смесь ООП и SQL-запросов.Я прочитал несколько примеров по этому поводу, но не могу найти именно то, что я ищу.Можете ли вы помочь?

CREATE OR REPLACE FUNCTION DOCSADMIN.GET_DOCS (
    RECID IN NUMBER) -- RECORD ID
    RETURN VARCHAR2 -- CONCATENATED STRING WITH PIPES
IS
    RETVAL          VARCHAR2(5000) :='';
    DOCSTRING       VARCHAR2(5000) :='';    
    DOCNAME      VARCHAR2(5000) :='';
    DOCNUMBER    NUMBER;
    STATUS       VARCHAR2(5000) :='';
    DOCTYPE      VARCHAR2(5000) :='';
    EDITDATE     DATE :='';
/******************************************************************************
   NAME:       GET_DOCS
   PURPOSE:    Pulls associated docs from profile table
******************************************************************************/


   CURSOR GETDOCINFO IS SELECT DOCNUMBER, DOCNAME, CUSTOM_STATUS, DOCUMENTTYPES.DESCRIPTION, LAST_EDIT_TIME
        FROM PROFILE, DOCUMENTTYPES, FORMS WHERE NAD_APID = IN_APID AND PROFILE.FORM = FORMS.SYSTEM_ID AND 
        DOCUMENTTYPE = DOCUMENTTYPES.SYSTEM_ID AND FORM_NAME = 'DOCS_PROFILE' ORDER BY DOCNUMBER;

BEGIN

    OPEN GETDOCINFO;
        --GET THE FIRST RECORD
        FETCH GETDOCINFO INTO DOCNUMBER, DOCNAME, STATUS, DOCTYPE, EDITDATE;
        --LOOP THROUGH ALL ASSOCIATED DOCS AND GRAB INFO
        WHILE GETDOCINFO%FOUND LOOP

            BEGIN

                DOCSTRING := DOCNUMBER || '|~|' || DOCNAME || '|~|' || STATUS || '|~|' || DOCTYPE || '|~|' || WS_EDITDATE;

                RETVAL := RETVAL || DOCSTRING || '|^|';

                GOTO STARTOVER;

            END;

            <<STARTOVER>>

            FETCH GETDOCINFO INTO DOCNUMBER, DOCNAME, STATUS, DOCTYPE, EDITDATE;

        END LOOP;

   CLOSE GETDOCINFO;

   RETURN RETVAL;

   EXCEPTION
     WHEN NO_DATA_FOUND THEN
       NULL;
     WHEN OTHERS THEN
       -- Consider logging

 the error and then re-raise
       RAISE;
END GET_DOCS;
/

Ответы [ 2 ]

5 голосов
/ 14 ноября 2011

Ну, вы можете преобразовать функцию в процедуру и иметь параметр OUT типа SYS_REFCURSOR. С помощью Oracle и .Net вы можете передать назад курсор и пройти через него как читатель.

Пример процедуры Oracle:

CREATE OR REPLACE PROCEDURE TEST_SCHEMA.TEST_PROCEDURE (
  out_DATA OUT SYS_REFCURSOR;
) AS
BEGIN
  OPEN out_DATA FOR
  SELECT col1,
         col2
    FROM TEST_SCHEMA.TEST_TABLE;
END test_procedure;

Образец .Net конец:

using (OracleConnection connection = new OracleConnection("connstring"))
using (OracleCommand command = connection.CreateCommand()) {
  command.CommandType = CommandType.StoredProcedure;
  command.CommandText = "TEST_SCHEMA.TEST_PROCEDURE";
  command.Parameters.Add("out_DATA", OracleType.Cursor)
      .Direction = ParameterDirection.Output;

  connection.Open();
  command.ExecuteNonQuery();
  OracleDataReader reader = 
      command.Parameters["out_DATA"].Value as OracleDataReader;

  if (reader != null) {
    using (reader) {
      while(reader.Read()) {
        string col1 = reader["col1"] as string;
        string col2 = reader["col2"] as string;
      }
    }
  }
}

Обязательно закройте курсор после того, как вы его закончили (выполняется выше с помощью оператора using (reader)).

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

0 голосов
/ 14 ноября 2011

То, что у меня есть, прекрасно компилируется.

CREATE OR REPLACE PROCEDURE DOCSADMIN.GET_DOCS_SP  ( IN_APID IN NUMBER,   out_DATA OUT SYS_REFCURSOR ) 

AS 
BEGIN   

OPEN out_DATA FOR   

SELECT DOCNUMBER, DOCNAME, CUSTOM_STATUS, DOCUMENTTYPES.DESCRIPTION, LAST_EDIT_TIME
        FROM PROFILE, DOCUMENTTYPES, FORMS WHERE APID = IN_APID AND PROFILE.FORM = FORMS.SYSTEM_ID AND 
        DOCUMENTTYPE = DOCUMENTTYPES.SYSTEM_ID AND FORM_NAME = 'PROFILE' ORDER BY DOCNUMBER;

END GET_DOCS_SP;

/

Однако я столкнулся с другой ситуацией и был бы признателен за ваш вклад.Если бы я хотел вызвать следующее из базы данных sql, используя OPENQUERY, как бы я это сделал?Устаревшая версия, которая возвращала объединенную строку, выглядела следующим образом:

SELECT * FROM OPENQUERY (TESTSERVER, 'SELECT DOCSADMIN.GET_DOCS_SP (26) AS DOCINFO FROM DUAL')

Должен ли я просто удалить предложение as DOCINFO FROM DUAL?

Спасибо

...