Click here to view and discuss this page in DocCommentXchange. In the future, you will be sent there automatically.

SQL Anywhere 11.0.1 (日本語) » Mobile Link - サーバ管理 » Mobile Link サーバ API » ダイレクト・ロー・ハンドリング » ダイレクト・アップロードの処理

 

ダイレクト・アップロードでの競合の処理

Mobile Link クライアントが更新済みのローを Mobile Link サーバに送信するときは、更新された値 (更新後または新しいイメージ・ロー) だけでなく、Mobile Link サーバとの最後の同期で得た古いローの値 (更新前または古いイメージ・ロー) のコピーも含まれています。更新前イメージ・ローが中央データ・ソースの現在の値と一致しないと、競合が検出されます。

SQL ベースの競合解決

SQL ベースのアップロードの場合、Mobile Link 統合データベースが中央データ・ソースであり、Mobile Link は競合の検出と解決用に特別なイベントを提供しています。

競合の解決を参照してください。

ダイレクト・ロー・ハンドリングを使用した競合解決

ダイレクト・アップロードの場合、新しいローと古いローにプログラムを使用してアクセスして、競合の検出と解決に使用できます。

UpdateResultSet (UploadedTableData.getUpdates メソッドが返す) は、競合処理に使用する特別なメソッドが含まれるように、Java または .NET 標準の結果セットを拡張したものです。setNewRowValues は、リモート・クライアントからの新しい更新された値を返すように UpdateResultSet を設定します (デフォルト・モード)。setOldRowValues は、古いロー値を返すように UpdateResultSet を設定します。

ダイレクト・ロー・ハンドリングを使用した競合検出

UpdateResultSet のメソッド .setOldRowValues を使用することによって、リモートのローの変更される前の値を取得します。返された値をデータ・ソースの既存のロー値と比較します。比較したローが同じではない場合、競合が存在しています。

ダイレクト・ロー・ハンドリングを使用した競合解決

アップロード中に競合を検出したら、カスタム・ビジネス論理を使用して競合を解決できます。競合は、Java コードまたは .NET コードによって処理されます。

XML ドキュメント内の在庫を追跡していて、XML ドキュメントを中央データ・ソースとして使用すると仮定します。User1 は、リモート・データベースの 1 つである Remote1 を使用します。User2 は、別のデータベースである Remote2 を使用します。

XML ドキュメント、User1、User2 の最初の在庫数はすべて 10 個です。User1 が、3 個を販売し、Remote1 にある在庫数を 7 個に更新します。User2 は 4 個販売し、Remote2 にある在庫数を 6 個に更新します。Remote1 が同期を実行すると、中央データベースは 7 個に更新されます。Remote2 が同期を実行すると、在庫の値が 10 個ではなくなっているため、競合が検出されます。この競合をプログラムで解決するには、次のような 3 つのロー値が必要となります。

  • 中央データ・ソースにある現在の値。

  • Remote2 がアップロードした新しいローの値。

  • Remote2 が最後の同期中に取得した古いローの値。

この場合、ビジネス論理は新しい在庫数を計算し、競合を解決するために次の式を使用します。

current data source - (old remote - new remote)
-> 7 - (10-6) = 3

Java と .NET の次のプロシージャでは、ダイレクト・アップロードでのこのような競合を解決する方法を、次のテーブルを例に示しています。

CREATE TABLE remoteOrders
(
    pk integer primary key not null,
    inventory integer not null
);
♦  直接競合を処理するには、次の手順に従います (Java)。
  1. handle_UploadData 接続イベント用の Java または .NET メソッドを登録します。

    handle_UploadData 接続イベントを参照してください。

    たとえば、次のストアド・プロシージャ・コールは、スクリプト・バージョン ver1 を同期するときに、handle_UploadData 接続イベントに対して HandleUpload という Java メソッドを登録します。Mobile Link 統合データベースに対してこのストアド・プロシージャを実行します。

    call ml_add_java_connection_script( 'ver1',
       'handle_UploadData',
       'OrderProcessor.HandleUpload' )

    同期イベント用のメソッド登録の詳細については、次の項を参照してください。

  2. アップロード内のテーブルの UpdateResultSet を取得します。

    OrderProcessor.HandleUpload メソッドは、remoteOrders テーブルの UpdateResultSet を取得します。

    // method for handle_UploadData event
     public void HandleUpload( UploadData u_data )
     {
     
        // Get UploadedTableData for the remoteOrders table.
          UploadedTableData u_table = u_data.getUploadedTableByName("remoteOrders");
       
        // Get an UpdateResultSet for the remoteOrders table.
        UpdateResultSet update_rs = u_table.getUpdates();
       
        // (Continued...)
  3. 更新ごとに、中央データ・ソースの現在の値を取得します。

    次の例では、UpdateResultSet の getInt メソッドが、プライマリ・キー・カラム (先頭カラム) の整数値を返します。getMyCentralData メソッドを実装し、使用することにより、中央データ・ソースからデータを取得できます。

    while( update_rs.next() )
    {
       // Get central data source values.
    
       // Get the primary key value.
       int pk_value = update_rs.getInt(1);
    
       // Get central data source values.
       int central_value = getMyCentralData(pk_value);
    
       // (Continued...)
  4. 更新ごとに、Mobile Link クライアントによってアップロードされた古い値と新しい値を取得します。

    次の例では、UpdateResultSet の setOldRowValues と setNewRowValues を使用して、それぞれ古い値と新しい値を取得しています。

      // Set mode for old row values.
      update_rs.setOldRowValues();
    
      // Get the _old_ stored value on the remote.
      int old_value = update_rs.getInt(2);
    
      // Set mode for new row values.
      update_rs.setNewRowValues();
    
      // Get the _new_ updated value on the remote.
      int new_value = update_rs.getInt(2);
    
      // (Continued...)
  5. 更新ごとに、競合がないかどうかを確認します。

    古いロー値が中央データ・ソースの現在の値と一致しない場合、競合になります。競合を解決するため、ビジネス論理を使用して解決後の値を計算します。競合がなかった場合、中央データ・ソースは新しいリモート値で更新されます。setMyCentralData メソッドを実装し、使用することにより、更新を実行します。

      // Check if there is a conflict.
    
      if(old_value == central_value)
      {
        // No conflict.
        setMyCentralData(pk_value, new_value);
       
      }
      else
      {
        // Handle the conflict.
        int inventory = old_value - new_value;
        int resolved_value = central_value - inventory;
      
        setMyCentralData(pk_value, resolved_value);
    
      }
    }
♦  直接競合を処理するには、次の手順に従います (.NET)。
  1. handle_UploadData 接続イベント用のメソッドを登録します。

    たとえば、次のストアド・プロシージャ・コールは、スクリプト・バージョン ver1 を同期するときに、handle_UploadData 接続イベントに対して HandleUpload という .NET メソッドを登録します。Mobile Link 統合データベースに対してこのストアド・プロシージャを実行します。

    call ml_add_dnet_connection_script( 'ver1',
       'handle_UploadData',
       'MyScripts.OrderProcessor.HandleUpload' )

    同期イベント用のメソッド登録の詳細については、次の項を参照してください。

  2. アップロード内のテーブルの UpdateDataReader を取得します。

    MyScripts.OrderProcessor.HandleUpload メソッドは、remoteOrders テーブルの UpdateResultSet を取得します。

    // method for handle_UploadData event
     public void HandleUpload( UploadData u_data )
     {
     
        // Get UploadedTableData for the remoteOrders table.
          UploadedTableData u_table = u_data.GetUploadedTableByName("remoteOrders");
       
        // Get an UpdateDataReader for the remoteOrders table.
        UpdateDataReader update_dr = u_table.GetUpdates();
       
        // (Continued...)
  3. 更新ごとに、中央データ・ソースの現在の値を取得します。

    次の例では、UpdateDataReader の GetInt32 メソッドが、プライマリ・キー・カラム (先頭カラム) の整数値を返します。getMyCentralData メソッドを実装し、使用することにより、中央データ・ソースからデータを取得できます。

    while( update_dr.Read() )
    {
       // Get central data source values.
    
       // Get the primary key value.
       int pk_value = update_dr.GetInt32(0);
    
       // Get central data source values.
       int central_value = getMyCentralData(pk_value);
    
       // (Continued...)
  4. 更新ごとに、Mobile Link クライアントによってアップロードされた古い値と新しい値を取得します。

    次の例では、UpdateResultSet の setOldRowValues と setNewRowValues を使用して、それぞれ古い値と新しい値を取得しています。

      // Set mode for old row values.
      update_dr.SetOldRowValues();
    
      // Get an _old_ value.
      int old_value = update_dr.GetInt32(1);
    
      // Set mode for new row values.
      update_dr.SetNewRowValues();
    
      // Get the _new_ updated value.
      int new_value = update_dr.GetInt32(1);
    
      // (Continued...)
  5. 更新ごとに、競合がないかどうかを確認します。

    古いロー値が中央データ・ソースの現在の値と一致しない場合、競合になります。競合を解決するため、ビジネス論理を使用して解決後の値を計算します。競合がなかった場合、中央データ・ソースは新しいリモート値で更新されます。setMyCentralData メソッドを実装し、使用することにより、更新を実行します。

      // Check if there is a conflict.
    
      if(old_value == central_value)
      {
        // No conflict.
        setMyCentralData(pk_value, new_value);
       
      }
      else
      {
        // Handle the conflict.
        int inventory = old_value - new_value;
        int resolved_value = central_value - inventory;
      
        setMyCentralData(pk_value, resolved_value);
    
      }
    }