Вызов параметризованной хранимой процедуры в C #, которая возвращает значения через курсор и сохраняет ее в DataTable - PullRequest
0 голосов
/ 03 мая 2018

У меня есть хранимая процедура, которая запускает запрос на выборку через курсор и возвращает курсор (запрос на оригинальный выбор более сложный, я его сократил).

CREATE OR REPLACE PROCEDURE GETASSIGNEDROLES(IN V_USER_ID INTEGER) SPECIFIC GETASSIGNEDROLES DYNAMIC RESULT SETS 1 LANGUAGE SQL NOT DETERMINISTIC EXTERNAL ACTION READS SQL DATA CALLED ON NULL INPUT INHERIT SPECIAL REGISTERS 
BEGIN 
    DECLARE TEMP_CURSOR CURSOR WITH HOLD WITH RETURN TO CLIENT FOR 
        SELECT DISTINCT ROLE_ID, ROLE_NAME FROM ROLE ORDER BY ROLE_NAME FOR READ ONLY WITH UR; 
    IF V_USER_ID IS NOT NULL AND V_USER_ID > 0 THEN 
        OPEN TEMP_CURSOR; 
    END IF; 
END;

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

Кроме того, моя база данных - DB2, поэтому синтаксис немного другой. Пока у меня есть следующий код после просмотра нескольких вопросов по SO. Но я не нашел вопроса об использовании Datatable и передачи параметров в CMD, это правильно?

DataTable DT = new DataTable();
using (var connection = new DB2Connection(ConnectionString))
{
  //connection.Open(); //open/close connection will be done implicitely by the DataAdapter.
  using (DB2Command cmd = connection.CreateCommand())
  {
      cmd.CommandText = "GETASSIGNEDROLES";
      cmd.CommandType = CommandType.StoredProcedure;
      cmd.Parameters.Add(new DB2Parameter(DataBaseObjects.ParamVUserID, DB2Type.Integer)).Value = userDo.User_ID;
      //cmd.CommandTimeout = CommandTimeout; //wait time before terminating the attempt to execute a command and generating an error in secs

      using (var da = new DB2DataAdapter(cmd))
      {
          da.Fill(DT);
      }
      DT.TableName = TableName;
      return DT;
  }
}

Ответы [ 2 ]

0 голосов
/ 22 мая 2018

Итак, я наконец-то начал работать. Что касается открытых курсоров, по-видимому, именно так вы делаете это в DB2. Курсор остается открытым для чтения клиентским приложением. Помогла эта ссылка: https://bytes.com/topic/db2/answers/465403-how-do-well-anything-db2-sql

Используемая хранимая процедура (изменено из вопроса):

CREATE OR REPLACE PROCEDURE GETASSIGNEDROLES(IN V_USER_ID INTEGER, IN V_BUSINESS_ENTITY_ID INTEGER) SPECIFIC GETASSIGNEDROLES DYNAMIC RESULT SETS 1 LANGUAGE SQL NOT DETERMINISTIC EXTERNAL ACTION READS SQL DATA CALLED ON NULL INPUT INHERIT SPECIAL REGISTERS 
BEGIN 
    DECLARE TEMP_CURSOR CURSOR WITH HOLD WITH RETURN TO CLIENT FOR 
        SELECT DISTINCT ROLE_ID, ROLE_NAME FROM ROLE ORDER BY ROLE_NAME FOR READ ONLY WITH UR; 
    IF V_USER_ID IS NOT NULL AND V_USER_ID > 0 THEN 
        OPEN TEMP_CURSOR; 
    END IF; 
END;

Функция в C # для вызова хранимой процедуры и сохранения полученных данных в таблице данных:

public DataTable GetAssignedRolesForUser(string ConnectionString, string TableName, User userDo)
        {
            //LogManager.EventLog("Inside GetAssignedRolesForUser");
            try
            {
                DataTable DTT = new DataTable();
                //See if UserID exists check is required here
                using (var connection = new DB2Connection(ConnectionString))
                {
                    //connection.Open(); //open/close connection will be done implicitely by the DataAdapter.
                    using (DB2Command cmd = connection.CreateCommand())
                    {
                        cmd.CommandText = DataBaseObjects.spGetAssignedRoles;
                        cmd.CommandType = CommandType.StoredProcedure;
                        cmd.Parameters.Add(new DB2Parameter(DataBaseObjects.ParamVUserID, DB2Type.Integer)).Value = userDo.User_ID;
                        cmd.Parameters.Add(new DB2Parameter(DataBaseObjects.ParamVBusinessEntityID, DB2Type.Integer)).Value = ConfigurationManager.AppSettings["BusinessEntity"];
                        //cmd.CommandTimeout = CommandTimeout; //wait time before terminating the attempt to execute a command and generating an error in secs

                        using (var da = new DB2DataAdapter(cmd))
                        {
                            da.Fill(DTT);
                        }
                        DTT.TableName = TableName;
                        return DTT;
                    }
                }
            }
            catch (Exception)
            {
                //LogManager.EventLog("[Error] Inside GetAssignedRolesForUser: " + ex.Message);
                throw;
            }
        }

Код для вызова функции C #:

DataTable DtRoles = <Call function here>
                foreach (DataRow row in DtRoles.Rows)
                {
                    list.Add(Convert.ToInt32(row["ROLE_ID"].ToString()));
                }
0 голосов
/ 03 мая 2018

Необходимо изучить все связанные / связанные страницы Центра знаний Db2 для вашей версии Db2, описывающей общеязыковые процедуры C # .net.

Запустите здесь и изучите каждую связанную страницу, чтобы примеры работали в вашей среде.

Если ваш Db2-сервер работает под управлением Microsoft-Windows или если вы установили специфичные для Windows образцы Db2 с вашим полным сервером данных-клиента (расположение по умолчанию:

\ program files \ ibm \ sqllib \ samples \ dotnet \ cs

) тогда вы можете увидеть примеры DataTable для C # там, а также онлайн в Центре знаний - «DbDatMap.cs» и связанные файлы и «SpClient.cs» и его зависимости

Пожалуйста, уточните, почему вы заполняете DataTable DT, но return DTT.

Если вы отлаживаете свой код, вы должны иметь возможность перебирать строки в DT после da.Fill (DT); завершается успешно.

Для меня consoleApp, использующий большую часть вашего синтаксиса, работает нормально, единственное отличие состоит в том, что я использовал ранее существующее соединение и предоставлял параметр varchar для своей хранимой процедуры вместо целого числа (но это не может изменить ситуацию).

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