locked
Is Sync Service on WCF Worth? RRS feed

  • Question

  • Hello,

    I have created a windows desktop application that user would use to create SDF using Sync Services (WCF based). I followed the sample on http://blogs.msdn.com/sync/archive/2008/07/14/using-wcf-for-communcation-in-a-mobile-sync-application.aspx

    to design the sync service. I then added service reference to my desktop project to generate proxies. Here is what GetSchema method in the proxy looks:

    public SyncSchema GetSchema(string[] tableNames, SyncSession syncSession)
        {
            return base.Channel.GetSchema(tableNames, syncSession);
        }
    However I am still getting following error:

    "Object of type 'System.String[]' cannot be converted to type 'System.Collections.ObjectModel.Collection`1[System.String]'."


    "   at System.RuntimeType.CheckValue(Object value, Binder binder, CultureInfo culture, BindingFlags invokeAttr)\r\n   at System.Reflection.MethodBase.CheckArguments(Object[] parameters, Binder binder, BindingFlags invokeAttr, CultureInfo culture, Signature sig)\r\n   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)\r\n   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)\r\n   at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)\r\n   at Microsoft.Synchronization.Data.ServerSyncProviderProxy.GetSchema(Collection`1 tableNames, SyncSession syncSession)\r\n   at Microsoft.Synchronization.SyncAgent.InitClientSchema()\r\n   at Microsoft.Synchronization.SyncAgent.Synchronize()\r\n   at Timmons.VectorControl.Mobile.SDFCreator.SDFCreatorForm.SynchronizeTables() in C:\\Projects\\Newport_News_Mobile\\src\\Timmons.VectorControl.Mobile\\Timmons.VectorControl.Mobile.SDFCreator\\SDFCreatorForm.cs:line 255"

    I have spend hours chasing this down with no luck. I am begining to wonder if getting sync service on WCF is really worth it.

    Here is my Iservice code

    public interface ISyncService
        {
            [OperationContract]
            string GetData(int value);
            [OperationContract]
            CompositeType GetDataUsingDataContract(CompositeType composite);
            #region sync service Server provider abstract methods
            [OperationContract]
            SyncServerInfo GetServerInfo(SyncSession syncSession);
            [OperationContract]
            SyncContext ApplyChanges(Microsoft.Synchronization.Data.SyncGroupMetadata groupMetadata, DataSet dataSet, SyncSession syncSession);
            [OperationContract]
            SyncContext GetChanges(SyncGroupMetadata groupMetadata, SyncSession syncSession);
            [OperationContract]
            SyncSchema GetSchema(string[] tableNames, SyncSession syncSession);
            #endregion
        }
      


    I also tried to create SDF from Mobile app but keep getting same argument exception. Here is the code for the Service.cs

    private void CreateServerProvider()
            {
                SqlConnection serverConnection;
                SqlSyncAdapterBuilder builder;

                //serverConnection = new SqlConnection(_connString);
                serverConnection = new SqlConnection(string.Format("server = {0}; database = {1}; integrated security = true", _server, _db));
                serverConnection.Open();
                _serverSyncProvider = new DbServerSyncProvider();
                _serverSyncProvider.Connection = serverConnection;
              
                #region Download Only Sync
                SyncAdapter adaptorWorkOrder = new SyncAdapter(_tableOwner + TableWorkOrder);

                #region Inserts
                SqlCommand incInsWorkOrderCmd = new SqlCommand();
                incInsWorkOrderCmd.CommandType = CommandType.StoredProcedure;
                incInsWorkOrderCmd.CommandText = _tableOwner + SPWorkOrderIncrementalInsert;
                incInsWorkOrderCmd.Parameters.Add("@" + SyncSession.SyncLastReceivedAnchor, SqlDbType.Binary, 8);
                incInsWorkOrderCmd.Parameters.Add("@" + SyncSession.SyncNewReceivedAnchor, SqlDbType.Binary, 8);

                adaptorWorkOrder.SelectIncrementalInsertsCommand = incInsWorkOrderCmd;
                #endregion

                #region Updates
                SqlCommand incUpdWorkOrderCmd = new SqlCommand();
                incUpdWorkOrderCmd.CommandType = CommandType.StoredProcedure;
                incUpdWorkOrderCmd.CommandText = _tableOwner + SPWorkOrderIncrementalUpdate;
                incUpdWorkOrderCmd.Parameters.Add("@" + SyncSession.SyncLastReceivedAnchor, SqlDbType.Binary, 8);
                incUpdWorkOrderCmd.Parameters.Add("@" + SyncSession.SyncNewReceivedAnchor, SqlDbType.Binary, 8);

                adaptorWorkOrder.SelectIncrementalUpdatesCommand = incUpdWorkOrderCmd;
                #endregion

                #region Deletes
                SqlCommand incDelTimeCodesCmd = new SqlCommand();
                incDelTimeCodesCmd.CommandType = CommandType.StoredProcedure;
                incDelTimeCodesCmd.CommandText = _tableOwner + SPWorkOrderIncrementalDelete;
                incDelTimeCodesCmd.Parameters.Add("@" + SyncSession.SyncLastReceivedAnchor, SqlDbType.Binary, 8);
                incDelTimeCodesCmd.Parameters.Add("@" + SyncSession.SyncNewReceivedAnchor, SqlDbType.Binary, 8);

                adaptorWorkOrder.SelectIncrementalDeletesCommand = incDelTimeCodesCmd;
                #endregion

                _serverSyncProvider.SyncAdapters.Add(adaptorWorkOrder);

                #endregion

                SqlCommand anchorCmd = new SqlCommand();
                anchorCmd.CommandType = CommandType.Text;
                anchorCmd.CommandText = "Select @" + SyncSession.SyncNewReceivedAnchor + " = min_active_rowversion() - 1";
                //anchorCmd.CommandText = "Select @" + SyncSession.SyncNewReceivedAnchor + " = @@DBTS";  // for SQL Server 2005 SP2, use "min_active_rowversion() - 1"

                anchorCmd.Parameters.Add("@" + SyncSession.SyncNewReceivedAnchor, SqlDbType.Timestamp).Direction = ParameterDirection.Output;
                _serverSyncProvider.SelectNewAnchorCommand = anchorCmd;

    Any help is highly appreciated.

    Thanks
    • Moved by Max Wang_1983 Thursday, April 21, 2011 11:20 PM forum consolidation (From:SyncFx - Microsoft Sync Framework Database Providers [ReadOnly])
    Wednesday, September 16, 2009 6:48 PM

All replies

  • Hi,

    Take a look at this thread http://social.microsoft.com/Forums/en-US/uklaunch2007ado.net/thread/95b24ae5-712f-4bb7-8287-5f20ff009756 and see if that solves your problem.

    Thanks,
    Gayathri TK
    • Proposed as answer by Gayathri TK Wednesday, September 16, 2009 9:36 PM
    Wednesday, September 16, 2009 9:36 PM
  • Thanks for the info. However I am getting the same error even after doing the same thing as proposed in this thread. Here is my ISyncService signature:

    public interface ISyncService
        {
            [OperationContract]
            string GetData(int value);
            [OperationContract]
            CompositeType GetDataUsingDataContract(CompositeType composite);
            #region sync service Server provider abstract methods
            [OperationContract]
            SyncServerInfo GetServerInfo(SyncSession syncSession);
            [OperationContract]
            SyncContext ApplyChanges(Microsoft.Synchronization.Data.SyncGroupMetadata groupMetadata, DataSet dataSet, SyncSession syncSession);
            [OperationContract]
            SyncContext GetChanges(SyncGroupMetadata groupMetadata, SyncSession syncSession);
            [OperationContract]
            SyncSchema GetSchema(Object[] tableNames, SyncSession syncSession);
            #endregion
        }

    Here is the code for GetSchema method on SyncService class:

     public SyncSchema GetSchema(Object[] tableNames, SyncSession syncSession)
            {
                try
                {
                   
                    Collection<string> tables = new Collection<string>();
                    foreach (Object x in tableNames)
                    {
                        tables.Add(x.ToString());
                    }
                  
                    return this._serverSyncProvider.GetSchema(tables, syncSession);
                   
                }
                catch (Exception e)
                {
                    Logger.Log(e.ToString());
                    ApplicationException newex = new ApplicationException("failed in GetSchema()", e);
                    throw newex;
                }
            }

    In my proxy (reference.cs) I removed all the duplicate types but left the following code...dont know if that is what is causing this:

    using System.Data;
        using Microsoft.Synchronization.Data;
       
        [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
        [System.ServiceModel.ServiceContractAttribute(Namespace="http://timmons.vectorcontrolmobile/syncservice", ConfigurationName="SyncServiceReference.ISyncService")]
        public interface ISyncService {
           
            [System.ServiceModel.OperationContractAttribute(Action="http://timmons.vectorcontrolmobile/syncservice/ISyncService/GetData", ReplyAction="http://timmons.vectorcontrolmobile/syncservice/ISyncService/GetDataResponse")]
            [System.ServiceModel.XmlSerializerFormatAttribute()]
            string GetData(int value);
           
            [System.ServiceModel.OperationContractAttribute(Action="http://timmons.vectorcontrolmobile/syncservice/ISyncService/GetDataUsingDataContr" +
                "act", ReplyAction="http://timmons.vectorcontrolmobile/syncservice/ISyncService/GetDataUsingDataContr" +
                "actResponse")]
            [System.ServiceModel.XmlSerializerFormatAttribute()]
            CompositeType GetDataUsingDataContract(CompositeType composite);
           
            [System.ServiceModel.OperationContractAttribute(Action="http://timmons.vectorcontrolmobile/syncservice/ISyncService/GetServerInfo", ReplyAction="http://timmons.vectorcontrolmobile/syncservice/ISyncService/GetServerInfoResponse" +
                "")]
            [System.ServiceModel.XmlSerializerFormatAttribute()]
            SyncServerInfo GetServerInfo(SyncSession syncSession);
           
            [System.ServiceModel.OperationContractAttribute(Action="http://timmons.vectorcontrolmobile/syncservice/ISyncService/ApplyChanges", ReplyAction="http://timmons.vectorcontrolmobile/syncservice/ISyncService/ApplyChangesResponse")]
            [System.ServiceModel.XmlSerializerFormatAttribute()]
            SyncContext ApplyChanges(SyncGroupMetadata groupMetadata, System.Data.DataSet dataSet, SyncSession syncSession);
           
            [System.ServiceModel.OperationContractAttribute(Action="http://timmons.vectorcontrolmobile/syncservice/ISyncService/GetChanges", ReplyAction="http://timmons.vectorcontrolmobile/syncservice/ISyncService/GetChangesResponse")]
            [System.ServiceModel.XmlSerializerFormatAttribute()]
            SyncContext GetChanges(SyncGroupMetadata groupMetadata, SyncSession syncSession);
           
            [System.ServiceModel.OperationContractAttribute(Action="http://timmons.vectorcontrolmobile/syncservice/ISyncService/GetSchema", ReplyAction="http://timmons.vectorcontrolmobile/syncservice/ISyncService/GetSchemaResponse")]
            [System.ServiceModel.XmlSerializerFormatAttribute()]
            SyncSchema GetSchema(object[] tableNames, SyncSession syncSession);
        }
       
        /// <remarks/>
        [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "2.0.50727.3082")]
        [System.SerializableAttribute()]
        [System.Diagnostics.DebuggerStepThroughAttribute()]
        [System.ComponentModel.DesignerCategoryAttribute("code")]
        [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://timmons.vectorcontrolmobile/syncservice")]
        public partial class CompositeType : object, System.ComponentModel.INotifyPropertyChanged {
           
            private bool boolValueField;
           
            private string stringValueField;
           
            /// <remarks/>
            [System.Xml.Serialization.XmlElementAttribute(Order=0)]
            public bool BoolValue {
                get {
                    return this.boolValueField;
                }
                set {
                    this.boolValueField = value;
                    this.RaisePropertyChanged("BoolValue");
                }
            }
           
            /// <remarks/>
            [System.Xml.Serialization.XmlElementAttribute(Order=1)]
            public string StringValue {
                get {
                    return this.stringValueField;
                }
                set {
                    this.stringValueField = value;
                    this.RaisePropertyChanged("StringValue");
                }
            }
           
            public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
           
            protected void RaisePropertyChanged(string propertyName) {
                System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
                if ((propertyChanged != null)) {
                    propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
                }
            }
        }
       
        [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
        public interface ISyncServiceChannel : Timmons.VectorControl.Mobile.SDFCreator.SyncServiceReference.ISyncService, System.ServiceModel.IClientChannel {
        }
       
        [System.Diagnostics.DebuggerStepThroughAttribute()]
        [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
        public partial class SyncServiceClient : System.ServiceModel.ClientBase<Timmons.VectorControl.Mobile.SDFCreator.SyncServiceReference.ISyncService>, Timmons.VectorControl.Mobile.SDFCreator.SyncServiceReference.ISyncService {
           
            public SyncServiceClient() {
            }
           
            public SyncServiceClient(string endpointConfigurationName) :
                    base(endpointConfigurationName) {
            }
           
            public SyncServiceClient(string endpointConfigurationName, string remoteAddress) :
                    base(endpointConfigurationName, remoteAddress) {
            }
           
            public SyncServiceClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) :
                    base(endpointConfigurationName, remoteAddress) {
            }
           
            public SyncServiceClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) :
                    base(binding, remoteAddress) {
            }
           
            public string GetData(int value) {
                return base.Channel.GetData(value);
            }
           
            public Timmons.VectorControl.Mobile.SDFCreator.SyncServiceReference.CompositeType GetDataUsingDataContract(Timmons.VectorControl.Mobile.SDFCreator.SyncServiceReference.CompositeType composite) {
                return base.Channel.GetDataUsingDataContract(composite);
            }
           
            public SyncServerInfo GetServerInfo(SyncSession syncSession) {
                return base.Channel.GetServerInfo(syncSession);
            }
           
            public SyncContext ApplyChanges(SyncGroupMetadata groupMetadata, System.Data.DataSet dataSet, SyncSession syncSession) {
                return base.Channel.ApplyChanges(groupMetadata, dataSet, syncSession);
            }
           
            public SyncContext GetChanges(SyncGroupMetadata groupMetadata, SyncSession syncSession) {
                return base.Channel.GetChanges(groupMetadata, syncSession);
            }
           
            public SyncSchema GetSchema(object[] tableNames, SyncSession syncSession) {
                return base.Channel.GetSchema(tableNames, syncSession);
            }
        }
    }


    In my client code I am using followings statements :

                    SyncServiceReference.SyncServiceClient svc = new Timmons.VectorControl.Mobile.SDFCreator.SyncServiceReference.SyncServiceClient();
                    ServerSyncProvider serverProvider = new ServerSyncProviderProxy(svc);

     SyncAgent _syncAgent;
                    _syncAgent = new SyncAgent();
                    _syncAgent.RemoteProvider = new ServerSyncProviderProxy(serverProvider);
    SyncStatistics syncStats = _syncAgent.Synchronize();

    But I still get the error.

    Any help is really really appreciated.
    Thanks
    Thursday, September 17, 2009 3:26 PM
  • Sam problem here: WCF Sync on Desktop to create SDF

    The solution:

    Remove this switch when you generate proxy with svcutil.exe: /ct:System.Collections.Generic.List`1
    Then you needn't to change the signature of GetSchema.

    I recommend to added service reference in Visual Studio with Collection type as System.Array. svcutil.exe will genrate the types in SynFx for you.


    [OperationContract]
            SyncSchema GetSchema(string[] tableNames, SyncSession syncSession);

    this signature should be change to:

    [OperationContract()]
            SyncSchema GetSchema(Collection<string> tableNames, SyncSession syncSession);

    Friday, September 18, 2009 3:56 AM
  • Bob,

    That didnt help. I get the same error. Thanks
    Monday, September 21, 2009 5:17 PM