#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.