Страница 1 из 1

ODBC ошибка - закрыть приложение в тихую

Добавлено: 17 Август 2019, 8:45
gopstop2007
При работе с удаленным сервером, редко, может произойти обрыв соединения (моргнул свет - перезагрузка роутера и т.п.). После которого, начинают вываливаться ошибки, программа не видит обрыв соединения и продолжает коннектиться к серверу.
Не подскажите или может у кого то есть готовое решение, как сразу закрыть программу, не закрывая ...надцадь сообщений об ошибке, или как правильно сделать реконект?
Спасибо за внимание

ODBC ошибка - закрыть приложение в тихую

Добавлено: 17 Август 2019, 8:47
Игорь Столяров
gopstop2007 писал(а): 17 Август 2019, 8:45как сразу закрыть программу, не закрывая ...надцадь сообщений об ошибке
HALT ? ;)

ODBC ошибка - закрыть приложение в тихую

Добавлено: 17 Август 2019, 8:53
gopstop2007
Игорь Столяров писал(а): 17 Август 2019, 8:47HALT ? ;)
Вы предлагаете пробежаться по всему коду multi-dll приложения и прописать везде HALT :( , а нет более "красивого" решения? :)

ODBC ошибка - закрыть приложение в тихую

Добавлено: 17 Август 2019, 9:00
Игорь Столяров
gopstop2007 писал(а): 17 Август 2019, 8:53Вы предлагаете пробежаться по всему коду multi-dll приложения и прописать везде HALT
Нет. Я предлагаю все запросы к удалённой БД выполнять через одну процедуру-коннектор, в которой будет проверка
подключения к БД перед выполнением запроса и выгрузка приложения в случае его обрыва.

ODBC ошибка - закрыть приложение в тихую

Добавлено: 17 Август 2019, 9:20
gopstop2007
я не везде использую конструкцию file{PROP:SQL}
например для

Код: Выделить всё

select ... from ... where
используется

Код: Выделить всё

LoadQueueFromSQL('select ... from ... where',Queue)
будет ли коннектор срабатывать?

ODBC ошибка - закрыть приложение в тихую

Добавлено: 17 Август 2019, 9:32
Игорь Столяров
А почему нет ? Если Вы завернёте вызов:

Код: Выделить всё

CheckAndLoadSQL Procedure('select ... from ... where',Queue)
  Code
  
  If ПРОВЕРКА ДОСТУПНОСТИ ИСТОЧНИКА
     LoadQueueFromSQL('select ... from ... where',Queue)  
  else
     HALT('У НАС ПРОБЛЕМЫ С ПОДКЛЮЧЕНИЕМ - ВЫРУБАЕМ ПРОГРАММУ !')
  end   
и вместо LoadQueueFromSQL будите везде вызывать CheckAndLoadSQL - то какие могут быть проблемы в принципе ?

ODBC ошибка - закрыть приложение в тихую

Добавлено: 17 Август 2019, 13:20
kreator
gopstop2007, посмотрите вот сюда - https://clarionhub.com/t/handling-disco ... halts/1591 или https://clarionhub.com/t/errorcode-90-c ... ction/2561. Мне тоже нужно будет совсем в недалёком будущем, но скорее как временное решение. Руки пока не дошли.

ODBC ошибка - закрыть приложение в тихую

Добавлено: 17 Август 2019, 19:51
Yufil
А я где-то здесь писал. Перехватываю Message() с заменой на свою функцию, смотрю сообщение об ошибке и ищу в тексте сообщения определённый фрагмент (туда дублируется сообщение сервера ) и код FileErrorCode(). Если есть в тексте сообщения - HALT ( точнее, вопрос оператору и варианты - HALT/ рестарт программы и HALT/попытка продолжить работу ), если нет - снимаем перехват с Message и выводим повторно текст сообщения. Ещё пользовал метод Throw, но там была другая идея - выдача разумного сообщения при нарушении ссылочной целостности ( выводится сообщение примерно такого вида "Введено недопустимое или дублирующее значение - нарушена уникальность записи-Запись используется в таблице "Персонал" ' ), может быть, и здесь можно попробовать.

К сожалению, за давностью лет ...Старик Альцгеймер... Но поищу...

ODBC ошибка - закрыть приложение в тихую

Добавлено: 17 Август 2019, 22:24
Yufil
Ага, нашёл кое-что...
Вот перехват Message

! LocalMessage FUNCTION(STRING,<STRING>,<STRING>,<STRING>,UNSIGNED=0,UNSIGNED=0),UNSIGNED,PROC !Перехват Message

Код: Выделить всё

LocalMessage         PROCEDURE  (STRING Msg,<STRING Header>,<STRING Icon>,<STRING Buttons>,UNSIGNED Default,UNSIGNED Modal) ! Declare Procedure
! Before Embed Point: %DataSection) DESC(Data Section) ARG()
SaveErr   Group,Pre(SE)
Error     Cstring(300)
ErrorCode Long
FileError Cstring(1000)
FileErrorCode Long
          End

ErrLevel  Long,Static,Thread  ! Чтобы не отрабатывать повторную ошибку
FstrCount Long
Q         Queue,Pre(Q)
N         Long
          End
! After Embed Point: %DataSection) DESC(Data Section) ARG()
  CODE
! Before Embed Point: %ProcessedCode) DESC(Processed Code) ARG()
!       Ret#=Message(Msg,Header,Icon,Buttons,Default,Modal)
!       Return Ret#
       Se:ErrorCode = ErrorCode()
       Se:Error = Error()
       Se:FileErrorCode = FileErrorCode()
       Se:FileError = FileError()
       ! Переключаемся на стандартный Message
       System{Prop:MessageHook}=0
       ! Выдаём стандартное сообщение
       Ret#=Message(Msg,Header,Icon,Buttons,Default,Modal)
       !SetErrorCode(0)
       Add(Q) ! Чтобы ErrorCode сбросить в 0
       !SetPath(LongPath())
       N# = Records(Config)
       If ErrorCode() ! Or Inlist(ErrorCode(),90,47)
          Case Message('Нет доступа к серверу или базе данных .|' & |
             Choose(Se:Error & Se:FileError<>'', ' Ошибка ' & Se:Error & ' ' & Se:FileError,''),  |
             'Внимание!',Icon:Question,'Перезапуск|Завершить|Дальше')
          Of 1
            Do RunCommand
          Of 2
            Halt(0)
          Of 3
          END
       End
       !etErrorCode(Se:ErrorCode)
       System{Prop:MessageHook} = Address(LocalMessage)
       Return Ret#
Запускается командой

Код: Выделить всё

System{Prop:MessageHook} = Address(LocalMessage)
После этого если ErrorCode() = 90 и FileErrorCode() > 0 - то облом...
А теперь насчёт Throw

Декларируется функция

Код: Выделить всё

FileThrow              FUNCTION(*FIleManager Fm,<String FIleName>),Long   !Вывод сообщений об ошибке

Код: Выделить всё

FileThrow            PROCEDURE  (*FIleManager Fm,<String FileName>) ! Declare Procedure
! Before Embed Point: %DataSection) DESC(Data Section) ARG()
Loc:FileName         Cstring(100)
Loc:FileError        Cstring(500)
Loc:Info             Cstring(100)

A                    Any
Loc:Pos              Long
TextGroup            Group
                      String('unique key|Нарушена уникальность записи')
                      String('table reference|Запись используется в другой таблице БД')
                     End
Loc:Msg              Cstring(100)
! After Embed Point: %DataSection) DESC(Data Section) ARG()
  CODE
! Before Embed Point: %ProcessedCode) DESC(Processed Code) ARG()
    Loc:FileError=Lower(FileError())
    Loop Row# =1 to 1000
      A &= What(TextGroup,Row#)
      If A &= Null
        Loc:Pos = 0
        Break
      End
      Loc:Msg = A
      Loc:Pos = Instring('|',Loc:Msg,1,1)
      If Loc:Pos>0
        If Instring(Loc:Msg[1 : Loc:Pos-1], Loc:FileError,1,1)
          Break
        End
      End
    End
    If Omitted(2)
      GlobalErrors.SetFile(Fm.GetName())
      Loc:FileName = Fm.GetName()
    Else
      GlobalErrors.SetFile(FileName)
      Loc:FileName = FileName
    End
    Case FM.GetError()
    Of Msg:DeleteFailed
      Case FileErrorCode()
      Of 23000
        Message('Ошибка при удалении строки ' |
         & 'из справочника "' & Loc:FileName & '"|' |
         & Choose(Loc:Pos>0, Loc:Msg[Loc:Pos+1 : Len(Loc:Msg)],'') & '|' |
         |!& 'Сообщение сервера:' & FileError()
         ,'Ошибка удаления записи',Icon:Exclamation)
        Return Level:Notify
      End
    Of Msg:AddFailed Orof Msg:PutFailed
      Case FileErrorCode()
      Of 23000
        Message('Введено дублирующее или недопустимое значение ' |
         & 'для справочника "' & Loc:FileName & '"|' |
         & Choose(Loc:Pos>0, Loc:Msg[Loc:Pos+1 : Len(Loc:Msg)],'') & '|' |
         |!& 'Сообщение сервера:' & FileError()
         ,'Ошибка создания записи',Icon:Exclamation)
        Return Level:Notify
      Else
        Message('Введено дублирующее или недопустимое значение ' |
         & 'для справочника "' & Loc:FileName & '"|' |
         & Choose(Loc:Pos>0, Loc:Msg[Loc:Pos+1 : Len(Loc:Msg)],'') & '|' |
         |!& 'Сообщение сервера:' & FileError()
         ,'Ошибка сохранения записи',Icon:Exclamation)
        Return Level:Notify
      End
    End
    !Stop('FileError=' & FileError() & ' FileErrorCode=' & FileErrorCode())
    RETURN GlobalErrors.ThrowMessage(Fm.GetError(),FileName)
Для таблиц вносится вставка для метода Throw ( пример для таблицы VID_KONTR )

Код: Выделить всё

Hide:Access:VID_KONTR.Throw PROCEDURE
ReturnValue          BYTE,AUTO

  CODE
      Return Self.FileThrow('Виды контроля') ! *** Наша вставка *** 
  ReturnValue = PARENT.Throw()
  RETURN ReturnValue
Коды ошибок для MS SQL, для других серверов будет по-другому.
После этого сообщение принимает намного более содержательный вид

ODBC ошибка - закрыть приложение в тихую

Добавлено: 18 Август 2019, 8:29
Yufil
gopstop2007 писал(а): 17 Август 2019, 9:20 я не везде использую конструкцию file{PROP:SQL}
например для

Код: Выделить всё

select ... from ... where
используется

Код: Выделить всё

LoadQueueFromSQL('select ... from ... where',Queue)
будет ли коннектор срабатывать?
LoadQueueFromSQL содержит самые обычные операции с кларионовскими БД - Open, Close, File{Prop:SQL}, Next. После каждой добавить адекватную проверку и обработку ErrorCode() - обычно равно 90, FileErrorCode и FileError. Или просто вывести Message, как указано выше...

ODBC ошибка - закрыть приложение в тихую

Добавлено: 18 Август 2019, 15:35
gopstop2007
Yufil писал(а): 17 Август 2019, 22:24 Ага, нашёл кое-что...
Вот перехват Message
Спасибо большое, интересное решение!

ODBC ошибка - закрыть приложение в тихую

Добавлено: 18 Август 2019, 15:36
gopstop2007
kreator писал(а): 17 Август 2019, 13:20gopstop2007, посмотрите вот сюда - https://clarionhub.com/t/handling-disco ... halts/1591 или https://clarionhub.com/t/errorcode-90-c ... ction/2561. Мне тоже нужно будет совсем в недалёком будущем, но скорее как временное решение. Руки пока не дошли.
Спасибо kreator, там пишут, что не всегда помогает :(

ODBC ошибка - закрыть приложение в тихую

Добавлено: 18 Август 2019, 16:21
kreator
gopstop2007 писал(а): 18 Август 2019, 15:36 Спасибо kreator, там пишут, что не всегда помогает
Какое решение не помогает? По-моему, решение ДП то, что надо.
Забыл в предыдущем своём посте заметить, что наш планшетный модуль (написанный в основном мной) похоже идёт в урну. На конец 2019 года он не удовлетворяет требованиям. Клиент просит немного доработать и начать смотреть на смартфоны. Поэтому тратить время на "доработать" не очень хочется.

ODBC ошибка - закрыть приложение в тихую

Добавлено: 18 Август 2019, 16:29
gopstop2007
kreator писал(а): 18 Август 2019, 16:21Какое решение не помогает? По-моему, решение ДП то, что надо.
Насчет ДП и не сомневаюсь, я с ним уже связался :)
kreator писал(а): 18 Август 2019, 16:21 Забыл в предыдущем своём посте заметить, что наш планшетный модуль (написанный в основном мной) похоже идёт в урну. На конец 2019 года он не удовлетворяет требованиям. Клиент просит немного доработать и начать смотреть на смартфоны. Поэтому тратить время на "доработать" не очень хочется.
У меня похожий результат :( Советую смотреть в сторону React Native.

ODBC ошибка - закрыть приложение в тихую

Добавлено: 21 Август 2019, 20:02
kreator
gopstop2007 писал(а): 18 Август 2019, 16:29У меня похожий результат Советую смотреть в сторону React Native.
Велосипедистов не ждать? На чистом Реакте попробовать?