Как перехватить разрыв соединения?

Использую ADO в Delphi для коннекта к бд в MS SQL Server. из-за плохой работы сети или др может разорваться соединение с серваком. Как в TAdoConnection узнать ссостояние соединения? Есть ли какое-нибудь событие которое возвращает ошибку что соединение разорвано?
24 ответа

Проверка соединения осуществляется свойством Connected.An application can check Connected to determine the current status of a connection. If Connected is True, the connection is active; if False, and the KeepConnection property is also False, then the connection is inactive.Можно для всех запросов запихать проверку в событие BeforeOpen.Write a BeforeOpen event handler to take specific action before an application opens a dataset for viewing or editing. BeforeOpen is triggered when an application sets the Active property to True for a dataset or an application calls Open.


Так вот свойство Connected не помогает, так как оно установлено в True всегда, даже если сетевой кабель рубануть топором :о) Единственно, что можно сделать, так это переписать от наследника AdoQuery и в своем компоненте предусмотреть Try-Except. Большего я ничего не смог придумать, все события TADOConnection - не работают при отсутствия связи.


привет. а время от времени делать что-то типа пинга сервера? что-типа малозначительного запроса? версию узнавать или еще чего. это загнать в try except и проверять скажем раз в минуту? хотя в принципе, можно и без постоянных пингов: сделать как Сергей_1 написал. ужесточить проверки :) удачи.


На счет пинга тоже думал, но это не служит гарантией работы самого SQL-сервера. Запросом долбать, тоже не есть хорошо - грузить сервак бестолковой работой, при большом количестве "таких занудных" клиентов сервак будет тормозить. Может быть стоит попробовать "читать" например @@Version ? Потом не ясно как корректно сделать обработку переконнекта ? У всех открытых запросов сделать Connection=false, потом переоткрыть базу, потом у всех запросов Connection=True - пробовал работает криво, так как часто необходима именно последовательность открытия запросов. Попробовал такую конструкцию события OnExecuteCompletе: IF(EventStatus = esErrorsOccured)THEN IF Pos('CONNECTION FAILURE', AnsiUpperCase(Error.Description))>0 THEN BEGIN// Обработка потери связи END Это позволяет, хоть что то приличное сообщить юзеру при невозможности переоткрыть запрос при обрыве связи. На самом деле вопрос очень актуальный, неужели никто не заморачивался ? :о(


Я в свое время заморачивался с этим. Всю документацию по протоколу tcp/ip перерыл. Все очень погано. Когда соединение разрывается со стороны сервера клиенту НИЧЕГО не сообщается, точнее клиент об этом не оповещается. Когда клиент пытается записать в сокет закрытого соединения вываливает ошибка о том, что соединение разорвано. Вот такие дела. Поэтому, единственно правильный совет тебе уже дали. Делать асинхронную систему опроса (в случае СУБД делать запросы к какой-нибудь таблице, типа dual).


Тоже нарвался на такую проблему.Очень странно было нарваться после BDE на такое западло от ADO.При обрыве коннекта ADO, в отличие от BDE самостоятельно коннект не восстанавливает, хуже того, оно не понимает, что коннект потерялся.ADOConnection1.Connected = True, все зашибись.Решил проблему переписыванием TADOQuery:
class
 TCzADOQuery = class(TAdoQuery)
 private
 protected
 public
 procedure NewOpen;
 published
 end;

<i>//-------------
</i>
procedure TCzADOQuery.NewOpen;

 procedure Reconnect(var DB : TAdoConnection);
 var
 Counter: integer;
 List: TList;
 begin
 List := TList.Create;
 try
 for Counter := <b>0</b> to DB.DataSetCount - <b>1</b> do begin
 List.Add(DB.Datasets[Counter]);
 DB.Datasets[Counter].Connection := nil;
 end;
 DB.Close;
 DB.Open;
 for Counter := <b>0</b> to List.Count - <b>1</b> do
 TCustomADODataSet(List[Counter]).Connection := DB;
 List.Clear;
 finally
 List.Free;
 end;
 end;
var
 Conn : TADOConnection;
begin
 Conn := Self.Connection;
 try
 Open;
 except
 On E : EOleException do
 begin
 if E.ErrorCode = -<b>2147467259</b> then <i>// killed process
</i> begin
 Reconnect(Conn);
 Open;
 end ELSE Raise;
 end;
 end;
 inherited Open;
end;


Moriarti:И где это BDE самостоятельно восстанавливало коннект? И как это оно по-вашему делало?А вообще тема обсуждалась неоднократно Nobody faults but mine... (LZ)


Не знаю че вы паритесь, я зделал так:у TADOConnection есть событие OnExecuteComplete, на него вешаем обработчикprocedure TFData.ConnExecuteComplete(Connection: TADOConnection; RecordsAffected: Integer; const Error: Error; var EventStatus: TEventStatus; const Command: _Command; const Recordset: _Recordset);function OpenConn: boolean; begin try Connection.Open; Result:=true; except Result:=false; end; end;begin if (EventStatus = esErrorsOccured) and (Error.Number = -2147467259) then begin Application.CreateForm(TFBusy, FBusy); FBusy.Label1.Caption:='Соединение с сервером БД разорвано....'#13'Попытка восстановить соединение.'; FBusy.Show; FBusy.Repaint; try Connection.Close; while not OpenConn do Delay(10000); finally FBusy.Close; FBusy.Release; end; end;end;


долго я искала... вот вариант: проверила вроде работает как надо!function IsConnectedToInternet: Boolean;var dwConnectionTypes: DWORD;begin dwConnectionTypes := INTERNET_CONNECTION_MODEM + // Для соединения используется модем. INTERNET_CONNECTION_LAN + // Для соединения используется LAN. INTERNET_CONNECTION_PROXY; // Для соединения с используется прокси сервер. Result := InternetGetConnectedState(@dwConnectionTypes, 0);end;procedure TForm1.Timer1Timer(Sender: TObject);begin if (not IsConnectedToInternet) then Recconect else try Query1.Close; Query1.ExecSQL; Query1.Open; Label1.Caption:='БД open'; except On E:Exception Do Label1.Caption:='Приостановите деятельность! сети нет'; end;end;procedure TForm1.Recconect;begin DBase.Close; try DBase.Open; try Query1.Close; Query1.ExecSQL; Query1.Open; Label1.Caption:='Восстановление после сбоя...'; except On E:Exception Do Label1.Caption:='Восстановление после сбоя...'; end; except On E:Exception Do Label1.Caption:='Закрыто'; end;end;procedure TForm1.FormCreate(Sender: TObject);begin DBase.open;end;


Использую ADO в Delphi для коннекта к бд в MS SQL Server. из-за плохой работы сети или др может разорваться соединение с серваком. Как в TAdoConnection узнать ссостояние соединения? Есть ли какое-нибудь событие которое возвращает ошибку что соединение разорвано?
а что отменили обработчики AfterDisconnect, BeforeDisconnect ?


Ramin, а вы попробуйте эти события в действии - просто выдерните сетевой шнурок из компутера во время работы программы - у меня, например, эти события не отстреливаются ... а у Вас?


И не будет.Делай обращение к базе--http://www.podgoretsky.com


И не будет.Делай обращение к базе--http://www.podgoretsky.com
Ну это, наверное, не совсем ко мне, но там, кажется, сначала вылетает ошибка, а уже потом событие


Дело в том, что тебе только кажется.Выдергивание шнурка, никаких событий и исключений не генерирует.--http://www.podgoretsky.com


Дело в том, что тебе только кажется.Выдергивание шнурка, никаких событий и исключений не генерирует.--http://www.podgoretsky.com
а я говорил, что генерирует? Вроде как обсуждали ситуацию с попыткой отослать запрос если перед этим выдернули шнурок, нет? - так вот тогда и получаем ошибку, а потом уже все остальное (если мне память не изменяет - проверить сейчас не могу)


Ramin, а вы попробуйте эти события в действии - просто выдерните сетевой шнурок из компутера во время работы программы - у меня, например, эти события не отстреливаются ... а у Вас?
если шнурок выдернут, никакой обработчик это не может засеч.... ----www.hramin.jino-net.ru


если шнурок выдернут, никакой обработчик это не может засеч....
погоди - так это же и есть пример разрыва сети, по который ТС говорил, а ты ему посоветовал
а что отменили обработчики AfterDisconnect, BeforeDisconnect ?
вот мне и стало интересно - с чего бы это


не понел ... кто такой ТС? ----www.hramin.jino-net.ru


не понел ... кто такой ТС?
Total CommТопик-стартер. Короче, автор темы.


ТС - топикстартер______________________________Чем чаще программист жалуется на чужой soft, тем хуже он делает свой.


а я говорил, что генерирует? Вроде как обсуждали ситуацию с попыткой отослать запрос если перед этим выдернули шнурок, нет?
Это твои фантазии, внимательно перечитай вопрос и вряд ли ему спустя более семи лет это еще интересно.Это Гостя подняла вопрос, за что ей большое ФИ и ответ дала частично работающий, в условиях LAN соединение всегда есть, даже если его нет.


Кстати речь вообще не про шнурок, а про соединение с MS SQL --http://www.podgoretsky.com


Это твои фантазии, внимательно перечитай вопрос и вряд ли ему спустя более семи лет это еще интересно.Это Гостя подняла вопрос, за что ей большое ФИ и ответ дала частично работающий, в условиях LAN соединение всегда есть, даже если его нет.
Да тут уже больше на интерес вопрос пошел. Я, если честно, уже не помню последовательность получения пинков, но у меня застряло в памяти, что при потере физического коннекта (шнурок выпал, сервер свалился и т.п.), АДО вываливало OLE Exception при попытке отправить запрос и при этом никаких событий xxxDisconnet не наблюдалось.Я, собственно, поэтому к Рамину и прицепился - у самого сейчас нет возможности протестить


Да тут уже больше на интерес вопрос пошел. Я, если честно, уже не помню последовательность получения пинков, но у меня застряло в памяти, что при потере физического коннекта (шнурок выпал, сервер свалился и т.п.), АДО вываливало OLE Exception при попытке отправить запрос и при этом никаких событий xxxDisconnet не наблюдалось.Я, собственно, поэтому к Рамину и прицепился - у самого сейчас нет возможности протестить
блин ничерта не понимаю , даже стыдно ... воопшем 1) обработчики разрыва соединение (никогда не тестировал как ведет себя эти обработчики если шнур выдернут или упал сервер)AfterDisconnect, BeforeDisconnect2) если ты писал такую ловушку ну предоставь автору3) в крайнем случаии можно через таймер пинговать сервер если не получаеш ответа значит соединение отсуствует...----www.hramin.jino-net.ru