2015-06-24 2 views
5

У меня есть модуль данных с глобальным TADOConnection (по умолчанию KeepConnection установить значение true). В моем существующем приложении есть множество наборов данных и запросов, которые используют этот глобальный TADOConnection.Как возобновить/повторить разбитое TADOConnection через приложение?

Мне было интересно, если есть какой-то умный способ возобновить/повторить соединение ado в случае короткого отключения сети? (эта ситуация иногда случается с клиентами, у которых есть не очень стабильные соединения).

Его легко воспроизвести то, что мне нужно. просто откройте TADOConnection при запуске. откройте TADODataSet, а затем отключите и включите «Подключение по локальной сети». если вы пытаетесь обновить набор данных, EOleException возбуждается исключение

"Ошибка подключения"

или

«[DBNETLIB] [ConnectionWrite (отправить()).] Общие сетевой ошибки. Проверьте свою сетевую документацию «

Если я перезапущу приложение, все хорошо.

Во время сетевых отключений события TADOConnection не регистрируются. и TADOConnection.Connected остается true

, конечно, я мог бы использовать TRY/поймать для каждого TDataSet.Open или Execute но я ищу какое-то «централизованное» решения для моего большого приложения. поэтому в случае «сбоя подключения» я мог бы знать, какой набор данных пытается открыть, и повторите попытку.

+1

Поймать исключение на уровне приложения, а затем повторно попробовать «MyConnection.Connected: = False; MyConnection.Connected: = True; 'для записи наше устаревшее программное обеспечение делает то же самое, и при повторном подключении, из того, что я понимаю, все связанные с ним запросы не имеют другого выбора, кроме как обновляться (открываться снова) вручную - так что держите отслеживать их .. –

+2

Вы мой мой ответ на [этот вопрос] (http://stackoverflow.com/questions/30479459/microsoft-alwayson-failover-solution-and-delphi/30494221#30494221) полезный. Это, по сути, отвечает на один и тот же вопрос, но в контексте SQL Server Always On. Я подозреваю, что переключение AlwaysOn генерирует именно те симптомы, которые вы пытаетесь решить – Kanitatlan

+0

@JerryDodge, я нашел этот похожий ответ: http://stackoverflow.com/a/2291917/3906993 Проблема в том, что вы не знаете, какой набор данных или запрос вызвал исключение. поэтому вы не можете повторить попытку, если вы не отслеживаете каждый набор данных/запрос до и Open/Exec – zig

ответ

0

Идея может заключаться в том, чтобы поймать ошибку соединения, а затем управлять ею с помощью попыток. Предположение:

Эта функция возвращает Descripion за исключением

function GetStrException(ExceptObject: TObject; ExceptAddr: Pointer):String; 
var 
    Buffer: array[0..1023] of Char; 
begin 
    ExceptionErrorMessage(ExceptObject, ExceptAddr, Buffer, SizeOf(Buffer)); 
    Result:=Buffer; 
end; 

это простая идея, чтобы проверить!

procedure TForm1.Button2Click(Sender: TObject); 
var 
s,error:String; 
begin 
//a select as an example 
S := 'SELECT COUNT(*) FROM MyTable'; 
TRY 
    WITH ADOQuery1 DO BEGIN SQL.Clear; SQL.Add(s);OPEN;END; 
    Memo1.Lines.ADD(ADOQuery1.Fields[0].AsString); 
EXCEPT 
    error:=(GetStrException(ExceptObject,ExceptAddr)); 
    //using MySql my error case is when the connection is lost, so the error is "Server has gone away" 
    if pos(error,'has gone away')>0 then 
    begin 
     Showmessage('Connection Error, please try again'); 
     try 
      sleep(1000) 
      AdoConnection1.close; 
      AdoConnection1.open; 
     except 
     Showmessage('The connection Error persists, please contact the support'); 
     end; 
    end; 
END; 
end; 

Хорошим решением является централизация вставки/обновления и выберите процедуру, а затем поймать ошибку и попытаться подстраивать ситуацию один или два раза, прежде чем показать сообщение пользователю не

1

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

Если вы хотите централизованное решение, и у вас есть 1 Connection, вы можете сделать это вот так:

Const 
    ConnectionTestString=' '; //Yes, it's work on Sql Server. If doesnt your db, you can use 'Select 1' 

Процедуры;

Procedure TDM.GetCommandResult_Conn(CText:String;Connection : TAdoConnection); 
var Ado_Ds_Tmp:TAdoCommand; 
Begin 
    Ado_Ds_Tmp:=TAdoCommand.Create(self); 
    try 
     Ado_Ds_Tmp.Connection:=Connection; 
     Ado_Ds_Tmp.ParamCheck := False; 
     Ado_Ds_Tmp.CommandText:=CText; 
     try 
     Ado_Ds_Tmp.Execute; 
     except 
     DM.RaiseExceptionCreate('Error ! Command, ('+StrToList(CText, ' ')[0]+')'); 
     end; 
    finally 
     Ado_Ds_Tmp.Destroy; 
    end; 
end; 

procedure TDM.ADOConnection1WillExecute(Connection: TADOConnection; 
    var CommandText: WideString; var CursorType: TCursorType; 
    var LockType: TADOLockType; var CommandType: TCommandType; 
    var ExecuteOptions: TExecuteOptions; var EventStatus: TEventStatus; 
    const Command: _Command; const Recordset: _Recordset); 
var 
    ErrorLogFileName : string; 
    ErrorFile : TextFile; 
    ErrorData : string; 
    Msg : String; 
begin 
    try 
    if (CommandText<>ConnectionTestString) then begin 
     DM.GetCommandResult_Conn(ConnectionTestString, Connection); 
    end; 
    except 
    try 
     try 
     Connection.Connected := False; 
     except 
     end; 
     try 
     Connection.ConnectionString := AdoConnectionString; 
     Connection.Mode:=cmShareDenyNone; 
     finally 
     try 
      Connection.Connected := True; 
      // If you wanna log for frequency 
      ErrorLogFileName := ChangeFileExt(Application.ExeName,'.error.log'); 
      AssignFile(ErrorFile, ErrorLogFileName); 
      if FileExists(ErrorLogFileName) then 
      Append(ErrorFile) 
      else 
      Rewrite(ErrorFile); 
      try 
      ErrorData := Format('%s : %s : %s (%s/%s)',[DateTimeToStr(Now), 'Disconnected but we reconnect.', '', 'UserName : '+DBUser, 'Client : '+GetComputerNetName]); 
      WriteLn(ErrorFile,ErrorData); 
      finally 
      CloseFile(ErrorFile) 
      end; 
     except 
      DM.RaiseExceptionCreate('ReConnection Failed!'); 
     end; 
     end; 
    except 
    end; 
    end; 
end; 

Есть вопросы?

+0

Хорошая идея. но это не позволит мне снова открыть набор данных, как только он потерпит неудачу. исключение для DataSet.Open все равно будет происходить. – zig

+0

Да, это позволит. когда Dataset.Open; первое срабатывание WillExecute и проверка тестового кода существует с ConnectionTestString. Если не удается восстановить соединение AdoConnection. После WillExecute код продолжит работу с Dataset.Open ... конечный пользователь не знает повторного подключения. –

+0

Но я изменил этот код в своей программе. 1-) в sql server # temp table auto-drop при изменении идентификатора соединения. Поэтому я больше не могу получить доступ к новому соединению. И 2) когда потерянные данные часто из-за плохой сети пользователя, они должны это знать. Если я спрячу проблему, это может привести к большим проблемам позже ... –

Смежные вопросы