Невозможно получить DBMS_ALERT для приложения на C #

#c# #multithreading #oracle #stored-procedures

#c# #многопоточность #Oracle #хранимые процедуры

Вопрос:

Я пытаюсь использовать DBMS_ALERT для предоставления обратной связи приложению на C # из базы данных Oracle 11g. При тестировании хранимых процедур в инструменте oracle TOAD я не могу получить никаких предупреждений.

Я покажу хранимые процедуры, которые я написал.

Моя причина для этого — предоставить обратную связь для индикатора выполнения в winform.

Я неправильно использую использование DBMS_ALERT ? Я новичок в Oracle, мой опыт работы с сервером MSSQL.

Вот моя хранимая процедура для генерации предупреждения:

 CREATE OR REPLACE PROCEDURE HOWMET.DB_ALERT  (iMsg VARCHAR2) AS
PRAGMA AUTONOMOUS_TRANSACTION;
  BEGIN
    DBMS_ALERT.SIGNAL('ALERT', iMsg);
    COMMIT;
  END DB_ALERT;
  

Вот моя хранимая процедура для чтения предупреждения:

 CREATE OR REPLACE PROCEDURE HOWMET.GET_DB_ALERT_MSG(oMsg    OUT VARCHAR2,
                                                oStatus OUT INTEGER)
AS
  BEGIN
    DBMS_ALERT.REGISTER('ALERT');
    DBMS_ALERT.WAITONE('ALERT', oMsg, oStatus,5);
    DBMS_ALERT.REMOVE('ALERT');
END;
  

Вот основная хранимая процедура, которую я использую для тестирования использования DBMS_ALERT :

 CREATE OR REPLACE PROCEDURE HOWMET.GETDATAWITHALERTS(EmployeeCur           OUT SYS_REFCURSOR,
                                                 EmployeeGridFormatCur OUT SYS_REFCURSOR)
AS
BEGIN

DB_ALERT('Starting Point 1');  <- calling an external sproc to signal the alert
DBMS_LOCK.SLEEP(5);  

OPEN EmployeeCur FOR
SELECT EMPLOYEE_ID,
       FIRST_NAME,
       LAST_NAME,
       EMAIL,
       HIRE_DATE,
       DEPARTMENT_ID,
       CAST(SALARY AS INT) AS "SALARY"
  FROM HR.EMPLOYEES;

DB_ALERT('Mid Point 2'); <- calling an external sproc to signal the alert
DBMS_LOCK.SLEEP(5);

OPEN EmployeeGridFormatCur FOR
SELECT 'Employee ID|Hidden' AS "Employee_ID",
       'First Name' AS "First_Name",
       'Last Name|Width:90' AS "Last_Name",
       'Email|Width:80' AS "Email",
       'Hire Date|Width:80' AS "Hire_Date",
       'Dept Id|Width:65' AS "DEPARTMENT_ID",
       'Salary|Right|Fill|FMT:#`##0.00' AS "Salary"
  FROM DUAL;

DB_ALERT('End 3'); <- calling an external sproc to signal the alert
DBMS_LOCK.SLEEP(5);

END GETDATAWITHALERTS;
  

Вот код C #, в котором я сталкиваюсь с ошибкой. Я продолжаю получать error -> «PL / SQL: числовая ошибка или ошибка значения».

 string Message = "";
int Status = -1;
bool bStatus;
try
{
  using (OracleConnection oCnn = new OracleConnection(_connectionString))
  using (OracleDataAdapter oDataAdapter = new OracleDataAdapter())
  using (OracleCommand dbmsAlert = new OracleCommand("GET_DB_ALERT_MSG", oCnn))
  {
     dbmsAlert.CommandType = CommandType.StoredProcedure;
            // create output parameters
     dbmsAlert.Parameters.Add("oMsg", OracleDbType.Varchar2, 1800, ParameterDirection.Output);
     dbmsAlert.Parameters.Add("oStatus", OracleDbType.Int32, ParameterDirection.Output);
     dbmsAlert.Connection.Open();
     dbmsAlert.ExecuteNonQuery();

     bStatus = int.TryParse(dbmsAlert.Parameters["oStatus"].Value.ToString(), out Status);
     Message = dbmsAlert.Parameters["oMsg"].Value.ToString();

     if (Status == 0)  //0 = Alert Received, 1 = Timed out
     {
        if (Message != null amp;amp; Message != String.Empty amp;amp; Message != "null")
        {
           MessageBox.Show(Message, "Feedback");
        }
        else
        {
           MessageBox.Show(System.String.Format("No Message! Status:{0} Msg:{1}", Status, Message), "Feedback");
        }
     }
  }
}
catch
{
  throw;
  //raise an error
}
  

Комментарии:

1. Итак, что происходит, когда вы вызываете HOWMET. GET_DB_ALERT_MSG только из прямой командной строки sql * plus?

2. Я тестировал в инструменте с именем dbforge studio для Oracle, я не пробовал sql * plus. Тестирование с помощью инструмента GUI, процедура GET_DB_ALERT_MSG работает только в том случае, если я добавляю DBMS_Alert.register в основную хранимую процедуру «GETDATAWITHALERTS» и удаляю DBMS_Alert.register и DBMS_Alert.remove из хранимой процедуры GET_DB_ALERT_MSG. Меня это смущает.

Ответ №1:

Я обнаружил проблему. Это связано с моим использованием метода add для OracleParameterCollection в Oracle.Доступ к данным.Клиентское пространство имен. Мое использование меньшего количества параметров для этого метода привело к реализации неправильного переопределения. В моем исходном сообщении у меня была следующая строка для указания выходного параметра хранимой процедуры, извлекающей предупреждение СУБД.

 dbmsAlert.Parameters.Add("oMsg", OracleDbType.Varchar2, 1800, ParameterDirection.Output);
  

При этом используется следующее переопределение:

 public OracleParameter Add(string name, OracleDbType dbType, int size, 
string srcColumn);
  

Я должен был написать это вместо:

 dbmsAlert.Parameters.Add("oMsg", OracleDbType.Varchar2, 1800, Message, ParameterDirection.Output);
  

При этом используется требуемое переопределение:

 public OracleParameter Add(string name, OracleDbType dbType, int size, 
object val, ParameterDirection dir;
  

Мое приложение на C # теперь может обнаруживать DBMS_ALERTs из Oracle.