9

私の Datasnap クライアント アプリケーションでは、メソッドと ProviderConnection に 1 つの TSQLConnection を使用しています。

接続が失われると問題が発生します。TSQLConnection.Connected と TSQLConnection.ConnectionState の両方がこれをキャッチしません。

TSQL 接続が開いていても、インターネット接続が失われたり、サーバーが停止したりすると、Datasnap クライアント アプリケーションで多くのエラーが発生します。(サーバー メソッドまたは ClientDatasets)

サーバー メソッドの SQL 接続を管理する関数を作成しました。ただし、たとえば、TDSProviderConnection を介して接続されている ClientDataset を閉じると、さらに問題が発生します。

Q:クライアント アプリケーションを管理して、TSQL 接続の切断を安全にキャッチするにはどうすればよいですか。
Q : ダウンタイムをどのように管理していますか? また、保存されていないクライアントの状態をどのように処理していますか?

ダウンタイム後の再接続は問題ありません。

サーバーメソッドを呼び出す場合: これは例外をスローします。

tmpM:=TServerMethodsClient.Create(MYTSQLCONNECTION.dbxconnection,true);

そこで、ダミー メソッドを使用してデータ モジュールから TSQLCONNECTION を取得する次のメソッドを作成しました。

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;

接続が失われたかどうかを確認する唯一の方法は、同じエラーをスローするダミーメソッドを使用することであるため、この方法でメソッドを作成しました...その後、再接続を照会したり、プログラムを閉じたりできます。

編集:ある種の一般的な回答とガイドラインを期待しています。すべきこととすべきでないこと。私のコードの修正ではありません。これは、私が現在行っていることを示すためのものです。

4

1 に答える 1

4

同じ問題に苦労しました。接続が切断されたことを検出する方法と、正常に再接続する方法です。これが私たちがやったことであり、私たちにとって非常に成功していることが証明されています。

ユーザーはDataSnapサーバーに接続して、データを取得して変更を加えます。OnBeforePostすべてのレコードの作成、更新、および削除は、のおよびOnBeforeDeleteイベントハンドラーを介してデータベースにすぐに送られますTClientDataSet

サーバーとの通信を試みて接続が切断されたことを確認するまで、クライアントがDataSnapサーバーから強制的に切断されたことを検出できないため、TApplicationEventsアプリのメインフォームにを追加し、イベントハンドラーを作成しましたOnExceptionイベントのために。が表示されると、接続が切断されていることがわかります。そのため、ユーザーにメッセージを表示してから、ローカルデータセットでまたはが発生しないようにEIdSocketError呼び出します。ユーザーは、再ログインしてから、[保存]または[削除]をもう一度クリックして、前のアクションを完了することができます。AbortPostDelete

グローバル例外ハンドラは次のようになります。

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;

これTDBXErrorは、通常、外部キーや一意キー違反などのDBエラーが発生したことを意味するため、トラップするもう1つの方法です。変更はデータベースで行われなかったため、Abortローカルで変更し、データベースとの同期を維持します。

dbとの同期を処理する方法(およびを介しOnBeforePostOnBeforeDelete)により、接続が切断され、ユーザーが再接続して新しいDataSnapセッションを取得することは問題ではありません。ユーザーが変更を失うことなく、DataSnapサーバーを再起動することもできます。ユーザーは再度ログインして[保存]をクリックするだけです。失われるものはありません。

これらすべてが最初の質問に答えます...いつか、TClientDataSetユーザーのHDDに保存できるオフラインモードを実装し、次にユーザーがログインしたときに、ローカルに保存されたすべての変更を適用するために同期を実行します。しかし、まだそれを行っていません。そのため、2番目の質問に対する適切な回答はありません。

于 2012-12-13T23:44:13.170 に答える