Как "выбросить"%Status в%ETN?

Многие из методов API Caché возвращают объект%Status, который указывает, является ли это ошибкой. Дело в том, что, когда это неизвестная ошибка, я не знаю, как ее обработать (например, сбой сети), что я действительно хочу сделать, это "выбросить" ошибку, чтобы мой код прекратил свою работу, и ошибка была обнаружена некоторыми более высокими обработчик ошибок уровня (и / или встроенный журнал ошибок%ETN).

Я мог бы использовать ztrap лайк:

s status = someObject.someMethod()
ztrap:$$$ISERR(status)

Но это не дает подробностей (в отличие, скажем, от.NET, где я могу выбросить исключение вплоть до вершины стека), и мне интересно, есть ли более эффективные способы сделать это.

2 ответа

Взгляните на ссылку класса для%Exception.StatusException. Вы можете создать исключение из вашего статуса и выбросить его в любую ловушку ошибок, активную в данный момент (поэтому поток управления будет таким же, как в вашем примере ZTRAP), например так

set sc = someobj.MethodReturningStatus()
if $$$ISERR(sc) {
   set exception = ##class(%Exception.StatusException).CreateFromStatus(sc)
   throw exception
}

Однако для того, чтобы восстановить информацию об исключении внутри кода прерывания ошибки, который перехватывает это исключение, должно быть установлено прерывание ошибки с помощью try/catch. Старые обработчики ошибок, $ztrap и $etrap, не предоставляют вам объект исключения, и вы только увидите, что у вас есть ошибка в качестве значения $ZERROR. Даже в этом случае поток управления будет работать так, как вы хотите, но без try / catch вам будет не лучше, чем с ZTRAP

Это два разных механизма ошибок, и их нельзя объединить таким образом. ztrap и%ETN для ошибок уровня кэша (ошибки угловых скобок, такие как <UNDEFINED>). Объекты%Status предназначены для ошибок уровня приложения (включая ошибки, возникшие в результате использования библиотеки классов кэша), и вы можете сами выбирать, как их обрабатывать. В действительности не имеет смысла обрабатывать плохой%Status с помощью механизма ошибок Cache, потому что ошибки Cache не произошло.

Вообще то, что делает большинство людей, это что-то вроде:

d: $$$ ISERR (статус) $$$SomeMacroRelevantToMyAppThatWillHandleThisStatus(статус)

Для вашего приложения можно создать собственный домен с собственным хостом кодов%Status с соответствующими значениями%msg. Возможно, ваше приложение пыталось подключиться к FTP-серверу и имело неверный пароль, но это не <DISCONNECT> и нет причины исследовать стек, только ошибка уровня приложения, которую необходимо обработать, возможно, попросив пользователя ввести новый пароль.

Может показаться странным, что существуют эти два параллельных механизма ошибок, но они описывают два разных типа ошибок. Думайте, что одна из них - это ошибки уровня "платформы", а другая - "ошибки уровня приложения"

Изменить: Одна вещь, которую я забыл, попробуйте DecomposeStatus^%apiOBJ(статус) или ##class(%Status).LogicalToOdbc(статус), чтобы преобразовать объект статуса в удобочитаемую строку. Кроме того, если вы выполняете отладку командной строки или просто хотите распечатать читаемую форму на основном устройстве, вы можете использовать $system.OBJ.DisplayError(status).

Другие вопросы по тегам