C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
Моделирование ситуации, сбой в сети
Лена
Отправлено: 26.12.2006, 14:25


Мастер участка

Группа: Участник
Сообщений: 501



В грид при старте приложения загружаются данный из ClientDataset. Допустим пользователь редактирует запись в гриде. В это время прерывается связь с сервером. Обрабатываю эту ситуацию в событии ClientDataSetBeforePost:
CODE

try{
      ADOQueryKey->Open();
     }
     catch(...)
         {
            ShowMessage("Не удалось записать в базу. Проверти связь с сервером");
            DataSet->Cancel();
            //ADOQueryKey->Close();
            Abort();
            return;
         }

Все нормально код отрабатывает. Теперь пусть неожиданно связь с сервером появляется, как это обработать, ведь теперь постоянно я получаю ShowMessage не взирая на то, что связь с сервером восстановилась?

Полностью обработчик выглядит так:
CODE

void __fastcall TDataModule2::ClientDataSetKeyBeforePost(TDataSet *DataSet)
{

 if(Form1->DBGrid1->Fields[0]->Value.IsNull() || Form1->DBGrid1->Fields[2]->Value.IsNull()
     || Form1->DBGrid1->Fields[3]->Value.IsNull())
   {
    sShowMessage("Поля \"Код\", \"Доступ\", и \"Владелец\" должны быть заполнены");
    Abort();
   }

  try{
      ADOQueryKey->Open();
     }
     catch(...)
         {
            sShowMessage("Не удалось отправить запись в базу. Проверти подключение к серверу");
            DataSet->Cancel();
            //ADOQueryKey->Close();
            Abort();
            return;
         }
  Variant Rez = ADOQueryKey->Lookup("code", Form1->DBGrid1->Fields[0]->AsString, "code");
  if(!Rez.IsNull() && Form1->DBGrid1->SelectedIndex == 0)
            {
            sShowMessage("Такая запись уже есть. Введите другую");
            DataSet->Cancel();
            ADOQueryKey->Close();
            Abort();
            }
  ADOQueryKey->Close();
Tantos
Отправлено: 26.12.2006, 14:50


Станционный диспетчер

Группа: Участник
Сообщений: 108



Может, тебе попробовать отключаться от сервера и закрывать все датасеты?
Лена
Отправлено: 26.12.2006, 15:50


Мастер участка

Группа: Участник
Сообщений: 501



QUOTE (Tantos @ 26.12.2006, 14:50)
Может, тебе попробовать отключаться от сервера и закрывать все датасеты?

Как в этом случае правильно написать обработчик ClientDataSetBeforePost?
Окончательно мне надо, чтобы программа умела правильно обрабатывать сбои в сети. Если сбой то откат записи, если связь появилась, то и приложение ожило.
Tantos
Отправлено: 27.12.2006, 05:01


Станционный диспетчер

Группа: Участник
Сообщений: 108



ИМХО, в блоке catch прописывай закрытие все датасетов и соединений. А как ты хочешь выполнить откат, если нет соединения с базой? Кстати, а что за СУБД ты используешь? Если это IB/FB, то в компонентах FIBPLus подобная обработка предусмотрена. Да, рекомендую использовать CachedUpdates, тогда данные в локальном буфере останутся.

Отредактировано Tantos — 27.12.2006, 12:05
Лена
Отправлено: 27.12.2006, 17:49


Мастер участка

Группа: Участник
Сообщений: 501



QUOTE (Tantos @ 27.12.2006, 05:01)
ИМХО, в блоке catch прописывай закрытие все датасетов и соединений. А как ты хочешь выполнить откат, если нет соединения с базой? Кстати, а что за СУБД ты используешь? Если это IB/FB, то в компонентах FIBPLus подобная обработка предусмотрена. Да, рекомендую использовать CachedUpdates, тогда данные в локальном буфере останутся.

Редактирую запись, к примеру, пропала связь с сервером. При переходе курсора на новую строку. Возникает событие отправки в базу. В catch можно для отката написать ClientDataSet1->CancelUpdates(); Все это прекрасно работает, но если связь с сервером восстановилась, то для дальнейшей работы приложения необходимо перезапустить все приложение, в противном случае все время продолжает срабатывать catch.

Написала такой обработчик:
CODE

void __fastcall TDataModule2::ADOConnection1AfterDisconnect(
TObject *Sender)
{
ShowMessage("Пропала связь с сервером");
}

Умышленно отключила сеть. Никакого сообщения ShowMessage("Пропала связь с сервером") не появилось.
Оно появиться, если принудительно устанавливать: DataModule2->ADOConnection1->Connected = false;
Мне же, надо отловить в фоновом режиме работы приложения разрыв связи с сервером и сообщить об этом пользователю, а при восстановлении связи с сервером, хочется, чтобы приложение продолжило свою нормальную работу без перезапуска. База данных PostgreSQL.
Есть стандартные решения обработки ситуации проподания связи с сервером базы данныхи затем ее восстановление?

Отредактировано Лена — 27.12.2006, 17:51
olegenty
Отправлено: 28.12.2006, 08:54


Ветеран

Группа: Модератор
Сообщений: 2412



разрыв ты и сейчас отлавливаешь. при разрыве (ИМХО) надо "разорвать" связи всех компонентов с Connection и врубить таймер, по которому будет производиться попытка соединения. в случае, если соединение прошло успешно, вырубить таймер, восстановить все разорванные связи с Connection и продолжить работу. вот как-то так.
Лена
Отправлено: 28.12.2006, 10:55


Мастер участка

Группа: Участник
Сообщений: 501



Может положить на форму компонет Indy и переодически пинговать сервер? В случае пропажи связи, просто сообщить пользователю и предложить закрыть приложение?
Думала есть какие-то стандаратные решения.
olegenty
Отправлено: 28.12.2006, 14:01


Ветеран

Группа: Модератор
Сообщений: 2412



то, что сервер пингуется, не означает, что доступен интересующий тебя сервис. в общем случае пингование ничего не даёт. другое дело, что ты можешь сделать два таймера, один — для пингования, другой для попыток соединения после того, как пинг прошёл.
Gedeon
Отправлено: 29.12.2006, 16:22


Ветеран

Группа: Модератор
Сообщений: 1742



Я уже где-то писал, но повторюсь, лучше всего с каким-то периодом выполнять простой запрос, типа SELECT GETDATE()

Вернуться в Работа с базами данных в C++Builder