locked
Setting SyncSession.OriginatorId value RRS feed

  • Question

  • How can I set the SyncSession.OriginatorId value in the client and have it propagate to the server via a web service? I can't use SyncClientId or SyncClientIdHash (though I see I could set ClientId in the ClientSyncProvider).

     

    I have to use an integer type because of incompatibilities with Oracle.

     

    Dave

    • Moved by Max Wang_1983 Friday, April 22, 2011 9:27 PM forum consolidation (From:SyncFx - Microsoft Sync Framework Database Providers [ReadOnly])
    Wednesday, December 5, 2007 7:45 PM

Answers

  • That post states the issue well, but doesn't provide a solution for me.

     

    I found a workaround - make a separate web method that has session enabled and recalls an OriginatorId (or makes a new one). For my workaround, the ClientId Guid is passed in and used as a key to obtain an existing OriginatorId. If one doesn't exist, a new one is generated from an Oracle sequence and saved.

     

    Code Block
    <WebMethod(enableSession:=True)> _
        Public Function GetClientId(ByVal clientGuid As Guid) As Integer
            Dim thisDataSession As DataSession = DataSession.Current
            Dim dataTable As New DataTable()
            Using command As IDbCommand = thisDataSession.BuildRawCommand("SELECT * FROM CLIENT WHERE CLIENT_ID = '" & clientGuid.ToString.ToUpper & "'")
                Dim adapter As New Oracle.DataAccess.Client.OracleDataAdapter(command)
                adapter.Fill(dataTable)
            End Using
            If dataTable.Rows.Count > 0 Then
                Session("OriginatorId") = CInt(dataTable.Rows(0)("CLIENT_ORIGINATOR_ID"))
                Return dataTable.Rows(0)("CLIENT_ORIGINATOR_ID")
            Else
                Dim originatorId As Integer = thisDataSession.ExecuteIntegerFunction("Sync.NewClientId")
                Using command As IDbCommand = thisDataSession.BuildRawCommand("INSERT INTO CLIENT (CLIENT_ID,CLIENT_ORIGINATOR_ID,CLIENT_USER) VALUES ('" & clientGuid.ToString.ToUpper & "'," & originatorId & ",'" & HttpContext.Current.User.Identity.Name & "')")
                    If command.ExecuteNonQuery() > 0 Then
                        Session("OriginatorId") = originatorId
                        Return originatorId
                    Else
                        Throw New Exception("OriginatorId insert failed")
                    End If
                End Using
            End If
        End Function

     

     

    I can then set the OriginatorId on each of the four web methods required by SyncServices (note that they also must have session state enabled):

     

    Code Block
      ' Enumerate group changes   
        <WebMethod(enableSession:=True)> _
        Public Function GetChanges(ByVal groupMetadata As SyncGroupMetadata, ByVal syncSession As SyncSession) As SyncContext
            syncSession.OriginatorId = Session("OriginatorId")
            Return GetServerProvider.GetChanges(groupMetadata, syncSession)
        End Function

     

    This is a fairly clean and low impact solution that doesn't require setting SelectClientIdCommand (which doesn't work with with Oracle because the Guid for SyncSession.SyncClientId can't be datatype-coerced into RAW or any other Oracle datatype). See my other posts concerning the RAW/Guid/uniqueidentifier issue for more info.

     

    Dave Michel

    Saturday, December 8, 2007 7:24 PM

All replies

  • You cannot set originator id directly but you can set the ClientID GUID on the client and have that map an int on the server side using the selectclientidcommand. 

     

    Here is the SQL server based sample:
    SqlCommand selectClientIdCommand = new SqlCommand();
    selectClientIdCommand.CommandType = CommandType.StoredProcedure;
    selectClientIdCommand.CommandText = "usp_GetOriginatorId";
    selectClientIdCommand.Parameters.Add("@" + SyncSession.SyncClientId, SqlDbType.UniqueIdentifier);
    selectClientIdCommand.Parameters.Add("@" + SyncSession.SyncOriginatorId, SqlDbType.Int).Direction = ParameterDirection.Output;
    selectClientIdCommand.Connection = serverConn;
    this.SelectClientIdCommand = selectClientIdCommand;
    
    Does that help?
    Wednesday, December 5, 2007 8:58 PM
  • I wish I could do that, but we're using Oracle, and the ClientId Guid must be converted to a byte array to fit into a RAW field.

    Wednesday, December 5, 2007 9:09 PM
  • Wednesday, December 5, 2007 10:11 PM
  • That post states the issue well, but doesn't provide a solution for me.

     

    I found a workaround - make a separate web method that has session enabled and recalls an OriginatorId (or makes a new one). For my workaround, the ClientId Guid is passed in and used as a key to obtain an existing OriginatorId. If one doesn't exist, a new one is generated from an Oracle sequence and saved.

     

    Code Block
    <WebMethod(enableSession:=True)> _
        Public Function GetClientId(ByVal clientGuid As Guid) As Integer
            Dim thisDataSession As DataSession = DataSession.Current
            Dim dataTable As New DataTable()
            Using command As IDbCommand = thisDataSession.BuildRawCommand("SELECT * FROM CLIENT WHERE CLIENT_ID = '" & clientGuid.ToString.ToUpper & "'")
                Dim adapter As New Oracle.DataAccess.Client.OracleDataAdapter(command)
                adapter.Fill(dataTable)
            End Using
            If dataTable.Rows.Count > 0 Then
                Session("OriginatorId") = CInt(dataTable.Rows(0)("CLIENT_ORIGINATOR_ID"))
                Return dataTable.Rows(0)("CLIENT_ORIGINATOR_ID")
            Else
                Dim originatorId As Integer = thisDataSession.ExecuteIntegerFunction("Sync.NewClientId")
                Using command As IDbCommand = thisDataSession.BuildRawCommand("INSERT INTO CLIENT (CLIENT_ID,CLIENT_ORIGINATOR_ID,CLIENT_USER) VALUES ('" & clientGuid.ToString.ToUpper & "'," & originatorId & ",'" & HttpContext.Current.User.Identity.Name & "')")
                    If command.ExecuteNonQuery() > 0 Then
                        Session("OriginatorId") = originatorId
                        Return originatorId
                    Else
                        Throw New Exception("OriginatorId insert failed")
                    End If
                End Using
            End If
        End Function

     

     

    I can then set the OriginatorId on each of the four web methods required by SyncServices (note that they also must have session state enabled):

     

    Code Block
      ' Enumerate group changes   
        <WebMethod(enableSession:=True)> _
        Public Function GetChanges(ByVal groupMetadata As SyncGroupMetadata, ByVal syncSession As SyncSession) As SyncContext
            syncSession.OriginatorId = Session("OriginatorId")
            Return GetServerProvider.GetChanges(groupMetadata, syncSession)
        End Function

     

    This is a fairly clean and low impact solution that doesn't require setting SelectClientIdCommand (which doesn't work with with Oracle because the Guid for SyncSession.SyncClientId can't be datatype-coerced into RAW or any other Oracle datatype). See my other posts concerning the RAW/Guid/uniqueidentifier issue for more info.

     

    Dave Michel

    Saturday, December 8, 2007 7:24 PM