2012-12-12 18 views
9

In meiner Datasnap Client-Anwendung verwende ich 1 TSQLConnection für meine Methoden und ProviderConnection. Probleme treten auf, wenn die Verbindung unterbrochen wird. Sowohl TSQLConnection.Connected als auch TSQLConnection.ConnectionState fangen das nicht ein.Mannaging SQLConnection/Datasnap durch Client-Server trennt

Wenn meine TSQL-Verbindung offen ist, aber ich die Internetverbindung verliere, oder der Server stoppt. Die Datasnap Client-Anwendung gibt viele Fehler. (Server-Methoden oder ClientDatasets)

Ich habe eine Funktion zum Verwalten meiner SQL-Verbindung für meine Servermethoden erstellt. Weitere Probleme treten auf, wenn beispielsweise ein ClientDataset geschlossen wird, das über eine TDSProviderConnection verbunden ist.

F: Wie verwalten Sie Ihre Clientanwendung zum sicheren Abfangen von Verbindungsabbrüchen auf der TSQL-Verbindung. Q: Wie verwalten Sie Ausfallzeiten und was tun Sie mit dem Status nicht gespeicherter Clients?

Wiederverbindung nach Ausfall ist nicht das Problem.

Beim Aufruf einer Servermethode: Dies würde eine Ausnahme auslösen.

Also ich schreibe nächste Methode, um die TSQLCONNECTION von meinem Datamodul mit Dummy-Methode zu erhalten.

function TDMForm.DSConnection: TSQLConnection; 
var 
    tmpM:TServerMethodsClient; 
begin 
    result:=nil; 
    if assigned(MYTSQLCONNECTION) then begin 
    tmpM:=TServerMethodsClient.Create(MYTSQLCONNECTION.dbxconnection,true); 
    try 
     try 
     tmpM.Ping; 
     result:=MYTSQLCONNECTION 
     except 
     ReconnectForm.ShowModal; // has a reconnect button that tries to reconnect + shutdownbutton 
     if ReconnectForm.modalresult=mrOK then 
      result:=MYTSQLCONNECTION 
     else 
      MainForm.Close; 
     end; 
    finally 
     tmpm.Free; 
    end; 
    end; 
end; 

Ich schrieb die Methode so, weil nur Ausweg zu finden, wenn durch Dummy-Methode Weicht Verbindung verloren geht ist die gleichen Fehler werfen würde ... dann kann ich für Reconnect oder in der Nähe Programm abfragen.

Edit: (Ich erwarte eine Art allgemeiner Antwort und Richtlinien, Empfehlungen und Einschränkungen nicht keine Korrektur meines Codes, das ist nur zu zeigen, was ich im Moment tue..)

Antwort

3

Wir haben mit dem gleichen Problem gekämpft - wie man erkennt, wenn die Verbindung getrennt wird, und wie man sich anmutig wieder verbindet. Das haben wir getan, was sich für uns als sehr erfolgreich erwiesen hat.

Unsere Benutzer stellen eine Verbindung zum DataSnap-Server her, um Daten abzurufen und Änderungen vorzunehmen. Alle Record-Creates, Updates und Deletes werden sofort über die OnBeforePost und OnBeforeDelete Event-Handler in der TClientDataSet in die Datenbank eingespeist.

Da Sie nicht feststellen können, wann der Client zwangsweise vom DataSnap-Server getrennt wurde, bis Sie versuchen, mit dem Server zu kommunizieren und feststellen, dass die Verbindung getrennt wurde, haben wir dem Hauptformular in unserer App TApplicationEvents hinzugefügt und schrieb einen Event-Handler für das Ereignis OnException. Wenn wir eine EIdSocketError sehen, wissen wir, dass die Verbindung tot ist, also zeigen wir eine Nachricht an den Benutzer, die so viel sagt, und rufen dann Abort auf, so dass die Post oder Delete nicht im lokalen Dataset vorkommen wird. Der Benutzer kann sich erneut anmelden und anschließend erneut auf speichern oder löschen, um die vorherige Aktion abzuschließen.

Unsere globale Exception-Handler sieht ungefähr wie folgt aus:

procedure TMainForm.AppEventsException(Sender: TObject; E: Exception); 
begin 
    if E is EIdSocketError then 
    begin 
    AppEvents.CancelDispatch; 
    MessageDlg('The connection to the database was lost. You must log in before you retry the failed action. Actual error message:'#13#10#13#10 + E.Message, mtError, [mbOK], 0); 
    Abort; 
    end; 

    if E is TDBXError then 
    begin 
    AppEvents.CancelDispatch; 
    MessageDlg('The database returned an error. If you cannot correct the issue, please contact customer service with the following database error message:'#13#10#13#10 + E.Message, mtError, [mbOK], 0); 
    Abort; 
    end; 

    // Show any other unhandled exceptions 
    Application.ShowException(E); 
end; 

Die TDBXError ist ein weiterer wir Falle, da es in der Regel bedeutet, ein DB-Fehler aufgetreten ist, wie ein Fremdschlüssel oder eine eindeutige Schlüsselverletzung. Da die Änderung nicht in der Datenbank vorgenommen wurde, Abort die Änderung lokal, die uns mit der db synchronisiert hält.

Aufgrund der Art und Weise, wie wir die Synchronisation mit der Datenbank handhaben (über OnBeforePost und OnBeforeDelete), spielt es keine Rolle, dass die Verbindung unterbrochen wurde und der Benutzer eine neue DataSnap-Sitzung erneut verbindet. Wir können den DataSnap-Server sogar neu starten, ohne dass Benutzer ihre Änderungen verlieren usw. Sie melden sich einfach erneut an und klicken auf , speichern Sie. Nichts ist jemals verloren.

All das beantwortet Ihre erste Frage ... Eines Tages werden wir einen Offline-Modus implementieren, wo der TClientDataSet kann auf die Benutzer HDD und nächsten Anmeldung in gespeichert werden, werden wir eine Synchronisierung alles tun, die lokal anwenden gespeicherte Änderungen Aber das haben wir noch nicht gemacht - also habe ich keine gute Antwort auf Ihre zweite Frage.

+0

Sie sagen "Der Benutzer kann sich erneut anmelden", aber Sie sagen nicht, wie Sie das gemacht haben? In meiner eigenen Datasnap-Anwendung löst sogar ein Aufruf von TSQLConnection1.Connected: = False eine Ausnahme aus (10053), da versucht wird, dem Server (der nicht mehr da ist) etwas mitzuteilen. Ich bin hier im Fang. Wie bist du um _that_ herumgekommen? – nolaspeaker

+1

@nolaspeaker - Da ich weiß, dass ich mich erneut authentifizieren werde, ist mir die Ausnahme nicht wirklich wichtig. Also benutze ich 'try sqlcon.Close; außer Ende; ', die irgendwelche Ausnahmen isst. Dann kann ich mich erneut authentifizieren oder dem Benutzer den Login-Dialog erneut zeigen, damit er sich manuell einloggen kann. –

+0

Ja, diese Handhabung ist mir auch aufgefallen - nachdem ich dir die Frage gestellt habe! :-) Danke für die Antwort. – nolaspeaker