Пример #1
0
 protected virtual void OnApplyChangeFailed(object sender, DbApplyChangeFailedEventArgs ev)
 {
     if (ApplyChangeFailed != null)
     {
         ApplyChangeFailed(sender, ev);
     }
 }
 public void SynchronizeServer_ApplyChangeFailed(object sender, DbApplyChangeFailedEventArgs e)
 {
     if (e.Error != null)
     {
         Log.Error("[DistributedDb] Synchronize Server ApplyChangeFailed Error", e.Error, this);
     }
 }
Пример #3
0
        public void ShowFailures(object syncOrchestrator, DbApplyChangeFailedEventArgs args)
        {
            ConflictForm form = new ConflictForm();

            form.HandleConflict(fromPeer, toPeer, args);
            form.ShowDialog();
        }
Пример #4
0
        public void HandleConflict(string fromPeer, string toPeer, DbApplyChangeFailedEventArgs args)
        {
            _conflictArgs = args;

            this.Text = "Conflict Detected on " + toPeer;
            richTextBoxHelp.Text = "Conflict Resolution Guide: \n" +
                "Continue: Ignore the remote change [local change wins] \n " +
                "Force Write: Overwrite existing row [remote change wins]. For this option to work the sync commands need to use @sync_force_write parameter \n" +
                "Retry Next Sync: Record the conflict in the sync metadata and fetch it again in the next sync \n" +
                "Retry: Disabled, only used when custom code is written to make changes to the database to fix the conflict (i.e. constraint conflict) \n";
            buttonRetry.Enabled = false;

            textBoxSyncStage.Text = _conflictArgs.Conflict.Stage.ToString();
            textBoxConflictType.Text = _conflictArgs.Conflict.Type.ToString();
            textBoxError.Text = _conflictArgs.Conflict.ErrorMessage;

            groupBoxRemoteChange.Text = "Remote Change from " + fromPeer;
            groupBoxLocalChange.Text = "Local Change on " + toPeer;

            if (_conflictArgs.Conflict.RemoteChange!= null)
            {
                dataGridServerChange.DataSource = _conflictArgs.Conflict.RemoteChange;
            }

            if (_conflictArgs.Conflict.LocalChange != null)
            {
                dataGridClientChange.DataSource = _conflictArgs.Conflict.LocalChange;
            }

            Application.DoEvents();
        }
Пример #5
0
        static void Program_ApplyChangeFailed(object sender, DbApplyChangeFailedEventArgs e)

        {
            MessageBox.Show(e.Conflict.Type.ToString());

            MessageBox.Show(e.Error.ToString());
        }
Пример #6
0
        void Program_ApplyChangeFailed(object sender, DbApplyChangeFailedEventArgs e)
        {
            string strmsg = "Error Type: " + DateTime.Now.ToShortDateString() + " " + DateTime.Now.ToShortTimeString() + e.Conflict.Type + "\n";

            strmsg += "Error Message: " + DateTime.Now.ToShortDateString() + " " + DateTime.Now.ToShortTimeString() + e.Error + "\n";
            WriteLogFile(strmsg);
        }
Пример #7
0
 private void Provider_ApplyingChanges(object sender, DbApplyChangeFailedEventArgs e)
 {
     if (e.Conflict.Type == DbConflictType.LocalUpdateRemoteUpdate)
     {
         int i = e.Conflict.LocalChange.Rows.Count;
     }
     else if (e.Conflict.Type == DbConflictType.LocalCleanedupDeleteRemoteUpdate)
     {
         e.Action = ApplyAction.Continue;
     }
     else if (e.Conflict.Type == DbConflictType.LocalDeleteRemoteUpdate)
     {
         e.Action = ApplyAction.RetryWithForceWrite;
     }
     else if (e.Conflict.Type == DbConflictType.LocalInsertRemoteInsert)
     {
         e.Action = ApplyAction.Continue;
     }
     else if (e.Conflict.Type == DbConflictType.LocalUpdateRemoteDelete)
     {
         e.Action = ApplyAction.Continue;
     }
     else if (e.Conflict.Type == DbConflictType.ErrorsOccurred)
     {
         Console.WriteLine(e.Error.Message);
     }
     else
     {
         Console.WriteLine(e.Error.Message);
     }
 }
Пример #8
0
        public void HandleConflict(string fromPeer, string toPeer, DbApplyChangeFailedEventArgs args)
        {
            _conflictArgs = args;

            this.Text            = "Conflict Detected on " + toPeer;
            richTextBoxHelp.Text = "Conflict Resolution Guide: \n" +
                                   "Continue: Ignore the remote change [local change wins] \n " +
                                   "Force Write: Overwrite existing row [remote change wins]. For this option to work the sync commands need to use @sync_force_write parameter \n" +
                                   "Retry Next Sync: Record the conflict in the sync metadata and fetch it again in the next sync \n" +
                                   "Retry: Disabled, only used when custom code is written to make changes to the database to fix the conflict (i.e. constraint conflict) \n";
            buttonRetry.Enabled = false;

            textBoxSyncStage.Text    = _conflictArgs.Conflict.Stage.ToString();
            textBoxConflictType.Text = _conflictArgs.Conflict.Type.ToString();
            textBoxError.Text        = _conflictArgs.Conflict.ErrorMessage;

            groupBoxRemoteChange.Text = "Remote Change from " + fromPeer;
            groupBoxLocalChange.Text  = "Local Change on " + toPeer;

            if (_conflictArgs.Conflict.RemoteChange != null)
            {
                dataGridServerChange.DataSource = _conflictArgs.Conflict.RemoteChange;
            }

            if (_conflictArgs.Conflict.LocalChange != null)
            {
                dataGridClientChange.DataSource = _conflictArgs.Conflict.LocalChange;
            }

            Application.DoEvents();
        }
Пример #9
0
        private void to_ApplyChangeFailed(object sender, DbApplyChangeFailedEventArgs e)
        {
            var toProvider = sender as RelationalSyncProvider;

#if DEBUG
            if (toProvider.ScopeName == Scope.Icd.ToScopeString())
            {
                return;
            }
#endif
            if (e.Conflict.Type == DbConflictType.ErrorsOccurred)
            {
                Poster.PostMessage("ApplyChangeFailed. Error: {0}", e.Error);
            }
            else if (SyncTracer.IsVerboseEnabled() == false)
            {
                SyncTracer.Warning(1, "CONFLICT DETECTED FOR CLIENT {0}", toProvider.Connection);
                SyncTracer.Warning(2, "** Local change **");
                SyncTracer.Warning(2, TableToStr(e.Conflict.LocalChange));
                SyncTracer.Warning(2, "** Remote change **");
                SyncTracer.Warning(2, TableToStr(e.Conflict.RemoteChange));
            }

            if (!ConflictsCounter.Keys.Contains(e.Conflict.Type))
            {
                ConflictsCounter[e.Conflict.Type] = 0;
            }

            ConflictsCounter[e.Conflict.Type]++;

            if (e.Conflict.Type != DbConflictType.ErrorsOccurred)
            {
                e.Action = ApplyAction.RetryWithForceWrite;
            }
        }
Пример #10
0
        private void karPaypal_ApplyChangeFailed(object sender, DbApplyChangeFailedEventArgs e)
        {
            // display conflict type
            Console.WriteLine(e.Conflict.Type);

            // display error message
            Console.WriteLine(e.Error);
        }
Пример #11
0
        static void Program_ApplyChangeFailed(object sender, DbApplyChangeFailedEventArgs e)
        {
            // display conflict type
            Console.WriteLine(e.Conflict.Type);

            // display error message 
            Console.WriteLine(e.Error);
        }
        private void PrintChangeFailedEventArgs(object sender, DbApplyChangeFailedEventArgs e)
        {
            // display conflict type
            Console.WriteLine(e.Conflict.Type);

            // display error message
            Console.WriteLine(e.Error);
        }
Пример #13
0
        static void Program_ApplyChangeFailed(object sender, DbApplyChangeFailedEventArgs e)
        {
            // display conflict type
            Console.WriteLine(e.Conflict.Type);

            // display error message
            Console.WriteLine(e.Error);
        }
Пример #14
0
 private void ApplyChangeFailed(object sender, DbApplyChangeFailedEventArgs e)
 {
     if (e.Conflict != null)
     {
         Log(e.Conflict.Type.ToString());
     }
     if (e.Error != null)
     {
         Log(e.Error.ToString());
     }
 }
        public void SynchronizeClient_ApplyChangeFailed(object sender, DbApplyChangeFailedEventArgs e)
        {
            if (e.Conflict != null)
            {
                Log.Error("[DistributedDb] Synchronize Client ApplyChangeFailed [" + e.Conflict.RemoteChange.TableName + "] Conflict", new Exception(e.Conflict.Type.ToString()), this);
            }

            if (e.Error != null)
            {
                Log.Error("[DistributedDb] Synchronize Client ApplyChangeFailed [" + e.Conflict.RemoteChange.TableName + "] Error", e.Error, this);
            }
        }
Пример #16
0
 static void Program_ApplyChangeFailed(object sender, DbApplyChangeFailedEventArgs e)
 {
     if (e.Conflict.Type == DbConflictType.LocalInsertRemoteInsert)
     {
         //e.Action = ApplyAction.RetryWithForceWrite;
         e.Action = ApplyAction.Continue;
     }
     else
     {
         throw e.Error;
     }
 }
Пример #17
0
 private static void sync_error_event_handler_local(object sender, DbApplyChangeFailedEventArgs e)
 {
     try
     {
         Debug.WriteLine("=========SYNC ERROR==========");
         // display conflict type
         Debug.WriteLine(e.Conflict.Type);
         // display error message
         Debug.WriteLine(e.Error);
         Debug.WriteLine("=========END SYNC ERROR==========");
     }
     catch (Exception ex)
     {
         Debug.WriteLine(ex);
     }
 }
Пример #18
0
        protected void proveedor_ApplyChangeFailed(object sender, DbApplyChangeFailedEventArgs e)
        {
            String mensaje =
                string.Format(
                    "{0}:{1}\n\r{2}:{3}\n\r{4}:{5}\n\r{6}:{7}\n\r{8}:{9}\n\r{10}:{11}\n\r",
                    "\tSource Database  :", e.Connection.Database,
                    "\tContexto         :", e.Context,
                    "\tAction           :", e.Action.ToString(),
                    "\tSession Id       :", e.Session.SessionId,
                    "\tTransaccion      :", e.Transaction.ToString(),
                    "\tTipo de conflicto: ", e.Conflict.Type
                    );

            e.Action = ApplyAction.RetryWithForceWrite; //Aplicar cambios del lado del local

            this.loguear("proveedor_ApplyChangeFailed", mensaje);
        }
 private void ServerApplyChangeFailed(object sender, DbApplyChangeFailedEventArgs e)
 {
     PrintChangeFailedEventArgs(sender, e);
 }
Пример #20
0
 static void Program_ApplyChangeFailed(object sender, DbApplyChangeFailedEventArgs e)
 {
     Console.WriteLine(e.Conflict.Type);
     Console.WriteLine(e.Error);
 }
        private void dbProvider_ApplyChangeFailed(object sender, DbApplyChangeFailedEventArgs e)
        {
            //For conflict detection, the "local" database is the one at which the
            //ApplyChangeFailed event occurs. We determine at which database the event
            //fired and then compare the name of that database to the names of
            //the databases specified as the LocalProvider and RemoteProvider.
            string DbConflictDetected = e.Connection.Database.ToString();
            string DbOther;

            DbOther = DbConflictDetected == _localProviderDatabase ? _remoteProviderDatabase : _localProviderDatabase;

            Console.WriteLine(String.Empty);
            Console.WriteLine("Conflict of type " + e.Conflict.Type + " was detected at " + DbConflictDetected + ".");

            //<snippetOCSv2_CS_Peer_Conflicts_LocalUpdateRemoteUpdate>
            if (e.Conflict.Type == DbConflictType.LocalUpdateRemoteUpdate)
            {
                //Get the conflicting changes from the Conflict object
                //and display them. The Conflict object holds a copy
                //of the changes; updates to this object will not be
                //applied. To make changes, use the Context object.
                DataTable conflictingRemoteChange = e.Conflict.RemoteChange;
                DataTable conflictingLocalChange  = e.Conflict.LocalChange;
                int       remoteColumnCount       = conflictingRemoteChange.Columns.Count;
                int       localColumnCount        = conflictingLocalChange.Columns.Count;

                Console.WriteLine(String.Empty);
                Console.WriteLine(String.Empty);
                Console.WriteLine("Row from database " + DbConflictDetected);
                Console.Write(" | ");

                //Display the local row. As mentioned above, this is the row
                //from the database at which the conflict was detected.
                for (int i = 0; i < localColumnCount; i++)
                {
                    Console.Write(conflictingLocalChange.Rows[0][i] + " | ");
                }

                Console.WriteLine(String.Empty);
                Console.WriteLine(String.Empty);
                Console.WriteLine(String.Empty);
                Console.WriteLine("Row from database " + DbOther);
                Console.Write(" | ");

                //Display the remote row.
                for (int i = 0; i < remoteColumnCount; i++)
                {
                    Console.Write(conflictingRemoteChange.Rows[0][i] + " | ");
                }

                //Ask for a conflict resolution option.
                Console.WriteLine(String.Empty);
                Console.WriteLine(String.Empty);
                Console.WriteLine("Enter a resolution option for this conflict:");
                Console.WriteLine("A = change from " + DbConflictDetected + " wins.");
                Console.WriteLine("B = change from " + DbOther + " wins.");

                string conflictResolution = Console.ReadLine();
                conflictResolution.ToUpper();

                if (conflictResolution == "A")
                {
                    e.Action = ApplyAction.Continue;
                }

                else if (conflictResolution == "B")
                {
                    e.Action = ApplyAction.RetryWithForceWrite;
                }

                else
                {
                    Console.WriteLine(String.Empty);
                    Console.WriteLine("Not a valid resolution option.");
                }
            }
            //</snippetOCSv2_CS_Peer_Conflicts_LocalUpdateRemoteUpdate>

            //Write any errors to a log file.
            //<snippetOCSv2_CS_Peer_Conflicts_ErrorsOccurred>
            else if (e.Conflict.Type == DbConflictType.ErrorsOccurred)
            {
                string logFile = @"C:\SyncErrorLog.txt";

                Console.WriteLine(String.Empty);
                Console.WriteLine("An error occurred during synchronization.");
                Console.WriteLine("This error has been logged to " + logFile + ".");

                StreamWriter  streamWriter = File.AppendText(logFile);
                StringBuilder outputText   = new StringBuilder();

                outputText.AppendLine("** APPLY CHANGE FAILURE AT " + DbConflictDetected.ToUpper() + " **");
                outputText.AppendLine("Error source: " + e.Error.Source);
                outputText.AppendLine("Error message: " + e.Error.Message);

                streamWriter.WriteLine(DateTime.Now.ToShortTimeString() + " | " + outputText.ToString());
                streamWriter.Flush();
                streamWriter.Dispose();
            }
            //</snippetOCSv2_CS_Peer_Conflicts_ErrorsOccurred>
        }
        protected void proveedor_ApplyChangeFailed(object sender, DbApplyChangeFailedEventArgs e)
        {
            String mensaje =
               string.Format(
                "{0}:{1}\n\r{2}:{3}\n\r{4}:{5}\n\r{6}:{7}\n\r{8}:{9}\n\r{10}:{11}\n\r",
                "\tSource Database  :", e.Connection.Database,
                "\tContexto         :", e.Context,
                "\tAction           :", e.Action.ToString(),
                "\tSession Id       :", e.Session.SessionId,
                "\tTransaccion      :", e.Transaction.ToString(),
                "\tTipo de conflicto: ", e.Conflict.Type
                );
            e.Action = ApplyAction.RetryWithForceWrite; //Aplicar cambios del lado del local

            this.loguear("proveedor_ApplyChangeFailed", mensaje);
        }
Пример #23
0
 private void Program_ApplyChangeFailed(object sender, DbApplyChangeFailedEventArgs e)
 {
     File.WriteAllText("Errors.txt",
                       DateTime.Now.ToString() + '\n' +
                       e.Conflict.Type.ToString() + ": " + e.Error.ToString());
 }
        private static void Program_ApplyChangeFailed(object sender, DbApplyChangeFailedEventArgs e)
        {
            // Both the server and the client have the same update on the same row, by default client (remote) wins
            if ((e.Conflict.Type == DbConflictType.LocalUpdateRemoteUpdate) &&
                (e.Conflict.Stage == DbSyncStage.ApplyingUpdates))
            {
                // If we use "ApplyAction.RetryWithForceWrite" the server will win the conflict...
                e.Action = ApplyAction.RetryWithForceWrite;


                // Otherwise (default behaviour), the client change will be written unto server (client wins)
            }
            else if ((e.Conflict.Type == DbConflictType.LocalInsertRemoteInsert) &&
                     (e.Conflict.Stage == DbSyncStage.ApplyingInserts))
            {
                // If we use "ApplyAction.RetryWithForceWrite" the server will win the conflict...
                e.Action = ApplyAction.RetryWithForceWrite;


                // Otherwise (default behaviour), the client change will be written unto server (client wins)
            }
            else if ((e.Conflict.Type == DbConflictType.LocalDeleteRemoteDelete) &&
                     (e.Conflict.Stage == DbSyncStage.ApplyingDeletes))
            {
                // If we use "ApplyAction.RetryWithForceWrite" the server will win the conflict...
                e.Action = ApplyAction.RetryWithForceWrite;


                // Otherwise (default behaviour), the client change will be written unto server (client wins)
            }
            else if ((e.Conflict.Type == DbConflictType.ErrorsOccurred) &&
                     (e.Conflict.Stage == DbSyncStage.ApplyingInserts))
            {
                #region Custom logic for proof of concept

                // Custom logic proof of concept (unique constraint)
                // Cannot insert duplicate key row in object 'dbo.Region' with unique index 'IX_RegionDescription'. The duplicate key value is (UniqueConstraintRegionDescription).
                // The statement has been terminated.
                if (e.Conflict.ErrorMessage.Contains("Cannot insert duplicate key row in object") &&
                    (e.Conflict.ErrorMessage.Contains("with unique index")))
                {
                    // For table named "Region" we want [server] to always win when the type of conflict is: unique name constraint...
                    // Additionally, all child relations from the [server] need to be written to the [client] database as well
                    // Additionally, client side conflicting row needs to be deleted BUT its child relations need to be updated to the
                    // [server] value
                    if (e.Conflict.RemoteChange.TableName.Equals("Region"))
                    {
                        try
                        {
                            var conflictingUniqueConstraint = string.Empty;
                            var serverRegionId = Guid.Empty;

                            if (e.Connection.State == ConnectionState.Open)
                            {
                                // 1. get the conflicting unique constraint from the [server]
                                if (e.Context.DataSet.Tables.Contains("Region"))
                                {
                                    var dataTable = e.Context.DataSet.Tables["Region"];
                                    for (var j = 0; j < dataTable.Rows.Count; j++)
                                    {
                                        var row = dataTable.Rows[j];


                                        // check if the status is Completed
                                        if (!string.IsNullOrEmpty(row["RegionDescription"].ToString()))
                                        {
                                            conflictingUniqueConstraint = row["RegionDescription"].ToString();
                                        }

                                        // get the unique Id of the conflicting row [server]
                                        serverRegionId = new Guid(row["RegionID"].ToString());
                                    }
                                }


                                // 2. Get the [client] entity id (Guid) for the conflicting row (which will be different from the [server]s)
                                var clientRegionId = string.Empty;

                                var sqlTextSel   = "select * from dbo.Region where RegionDescription=@description ";
                                var myCommandSel = new SqlCommand(sqlTextSel, (SqlConnection)e.Connection,
                                                                  (SqlTransaction)e.Transaction);
                                myCommandSel.Parameters.AddWithValue("@description",
                                                                     conflictingUniqueConstraint.TrimEnd());

                                var dr = myCommandSel.ExecuteReader();
                                while (dr.Read())
                                {
                                    clientRegionId = dr["RegionID"].ToString();
                                }


                                // This should allow the [server] to insert its region data into the [client] database
                                var sqlTextDeleteReg =
                                    "update dbo.Region set RegionDescription=@regionDescriptionConflicting where RegionID=@clientRegionId ";
                                var myCommandDeleteReg = new SqlCommand(sqlTextDeleteReg, (SqlConnection)e.Connection,
                                                                        (SqlTransaction)e.Transaction);
                                myCommandDeleteReg.Parameters.AddWithValue("@clientRegionId", clientRegionId);
                                myCommandDeleteReg.Parameters.AddWithValue("@regionDescriptionConflicting", conflictingUniqueConstraint.TrimEnd() + "-Conflict-" + DateTime.Now);
                                myCommandDeleteReg.ExecuteNonQuery();

                                //var sqlTextDeleteTer =
                                //  "update dbo.Territories set TerritoryDescription=territoryDescriptionConflicting where RegionID=@clientRegionId ";
                                //var myCommandDeleteTer = new SqlCommand(sqlTextDeleteTer, (SqlConnection)e.Connection,
                                //   (SqlTransaction)e.Transaction);
                                //myCommandDeleteTer.Parameters.AddWithValue("@clientRegionId", clientRegionId);
                                //myCommandDeleteTer.Parameters.AddWithValue("@territoryDescriptionConflicting", conflictingClientTerritory.TrimEnd() + "-Conflict-" + DateTime.Now);
                                //myCommandDeleteTer.ExecuteNonQuery();

                                //// var tempDataTable = new DataTable();
                                ////// create data adapter
                                //// var da = new SqlDataAdapter(myCommandSel);
                                ////// this will query your database and return the result to your datatable
                                //// var res = da.Fill(tempDataTable);
                                ////// var drc = tempDataTable.ParentRelations;
                                //// var x = tempDataTable.Rows[0].GetChildRows("RegionID");


                                //// 3. Every [client] side child entity related via the said guid, needs to be **updated** to [server] side guid...
                                //// need to start from the "childmost" and work our way up, in this extremely elaborate case, we only have the
                                //// table named [Territory] that has a one to many relation to the [Region] table...no further tables are related
                                //// making this a simple sample...
                                // var sqlTextDeleteTer =
                                //    "update dbo.Territory set RegionID=@serverRegionID where RegionID=@clientRegionId ";
                                // var myCommandDeleteTer = new SqlCommand(sqlTextDeleteTer, (SqlConnection) e.Connection,
                                //    (SqlTransaction) e.Transaction);
                                // myCommandDeleteTer.Parameters.AddWithValue("@clientRegionId", clientRegionId);
                                // myCommandDeleteTer.Parameters.AddWithValue("@serverRegionID", serverRegionId);
                                // myCommandDeleteTer.ExecuteNonQuery();


                                //// 4. delete the row that has the conflicting unique constraint - from the [local] database
                                //var sqlText = "delete from Region where RegionDescription=@description ";
                                //var myCommand = new SqlCommand(sqlText, (SqlConnection) e.Connection,
                                //    (SqlTransaction) e.Transaction);
                                //myCommand.Parameters.AddWithValue("@description", conflictingUniqueConstraint);

                                //myCommand.ExecuteNonQuery();
                            }


                            // 3. Let it sync (overwrite the client row with the server row
                            // If we use "ApplyAction.RetryWithForceWrite" the server will win the conflict...
                            e.Action = ApplyAction.RetryWithForceWrite;
                            // However the server is powerless against unique key constraint validation scenario...

                            e.Transaction.Commit();


                            // Problem: will client side entities that were just updated to feature server side guid be synced to the server?
                        }
                        catch (Exception regionExc)
                        {
                            e.Transaction.Rollback();
                        }
                    }
                }

                #endregion

                // Otherwise (default behaviour), the client change will be written unto server (client wins)

                if (e.Conflict.ErrorMessage.Contains("The INSERT statement conflicted with the FOREIGN KEY constraint"))
                {
                }
            }
        }
Пример #25
0
 private static void dbProvider_SyncProcessFailed(object sender, DbApplyChangeFailedEventArgs e)
 {
     //Write your code here
 }
Пример #26
0
        /// <summary>
        ///     On the client (remote)
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static void Program_ChangeApplyFail(object sender, DbApplyChangeFailedEventArgs e)
        {
            // Summary:
            //     The peer database threw an exception while applying a change.
            // ErrorsOccurred = 0,
            //
            // Summary:
            //     The local and remote peers both updated the same row.
            // LocalUpdateRemoteUpdate = 1,
            //
            // Summary:
            //     The local peer updated a row that the remote peer deleted.
            // LocalUpdateRemoteDelete = 2,
            //
            // Summary:
            //     The local peer deleted a row that the remote peer updated.
            // LocalDeleteRemoteUpdate = 3,
            //
            // Summary:
            //     The local and remote peers both inserted a row that has the same primary
            //     key value. This caused a primary key violation.
            // LocalInsertRemoteInsert = 4,
            //
            // Summary:
            //     The local and remote peers both deleted the same row.
            // LocalDeleteRemoteDelete = 5,
            //
            // Summary:
            //     The local peer deleted a row that the remote peer updated, and the metadata
            //     for that row was cleaned up.
            // LocalCleanedupDeleteRemoteUpdate = 6,

            switch (e.Conflict.Type)
            {
            case DbConflictType.ErrorsOccurred:
                var serverConflict = true;
                var stage          = e.Conflict.Stage;

                if (e.Conflict.LocalChange != null)
                {
                    serverConflict = true;
                }
                else if (e.Conflict.RemoteChange != null)
                {
                    serverConflict = false;
                }

                // If we encounter an conflict while inserting server data into client database...
                if (!serverConflict && stage == DbSyncStage.ApplyingInserts)
                {
                    // since we want server to win insert conflicts...
                    if (e.Conflict.ErrorMessage.Contains("Violation of UNIQUE KEY constraint"))
                    {
                        // e.Action = ApplyAction.RetryWithForceWrite; // This wont work, constraint is a constraint
                    }

                    // In this case we need to forego changing/updating the root entity, BUT we want to be able to insert/update its children!!!
                    // Root Entity on Master remains the same, but the children taken from the client must be inserted and related to the root entity...
                }


                break;

            case DbConflictType.LocalCleanedupDeleteRemoteUpdate:

                break;

            case DbConflictType.LocalDeleteRemoteDelete:

                break;

            case DbConflictType.LocalDeleteRemoteUpdate:

                break;

            case DbConflictType.LocalInsertRemoteInsert:
                e.Action = ApplyAction.Continue;
                break;

            case DbConflictType.LocalUpdateRemoteDelete:

                break;

            case DbConflictType.LocalUpdateRemoteUpdate:

                break;
            }

            // display conflict type
            Console.WriteLine(e.Conflict.ErrorMessage);
        }
Пример #27
0
 protected abstract void SyncProviderOnApplyChangeFailed(object sender, DbApplyChangeFailedEventArgs dbApplyChangeFailedEventArgs);
Пример #28
0
 public void ShowFailures(object syncOrchestrator, DbApplyChangeFailedEventArgs args)
 {
     ConflictForm form = new ConflictForm();
     form.HandleConflict(fromPeer, toPeer, args);
     form.ShowDialog();
 }
Пример #29
0
 protected override void SyncProviderOnApplyChangeFailed(object sender, DbApplyChangeFailedEventArgs dbApplyChangeFailedEventArgs)
 {
     ShowMessage("Local");
 }
        /// <summary>
        /// Handler for the ApplyChangedFailed event of the SqlSyncProvider class. This is used to record
        /// conflict information and apply the service conflict resolution policy.
        /// </summary>
        /// <param name="sender">Sender object</param>
        /// <param name="e">Event args</param>
        private void SqlSyncProviderApplyChangeFailed(object sender, DbApplyChangeFailedEventArgs e)
        {
            ApplyAction applyAction = ApplyAction.Continue;

            // Note: LocalChange table name may be null if the record does not exist on the server. So use the remote table name.
            string tableName = e.Conflict.RemoteChange.TableName;

            Type entityType = _configuration.TableGlobalNameToTypeMapping[tableName];

            ConstructorInfo constructorInfo = entityType.GetConstructor(Type.EmptyTypes);
            
            // Handle Errors first
            if (null != e.Error)
            {
                var syncError = new SyncError
                                    {
                                        LiveEntity = (IOfflineEntity)constructorInfo.Invoke(null),
                                        ErrorEntity = (IOfflineEntity)constructorInfo.Invoke(null)
                                    };

                //Note: When Error is not null, the conflict type should be ErrorsOccurred. Assert, just to make sure this is always correct.
                Debug.Assert(e.Conflict.Type == DbConflictType.ErrorsOccurred, "Conflict.Type is not ErrorsOccurred.");

                syncError.Description = e.Error.Message;

                // Fill in the error entity. This is the value of the client entity.
                _converter.GetEntityFromDataRow(e.Conflict.RemoteChange.Columns, e.Conflict.RemoteChange.Rows[0], syncError.ErrorEntity);

                // Mark the error entity as a tombstone, if the client sent a delete.
                // Note: The DataRow.RowState property is not marked as deleted, so we cannot use that
                // to determine if the client change was a delete.
                if (e.Conflict.Stage == DbSyncStage.ApplyingDeletes)
                {
                    syncError.ErrorEntity.ServiceMetadata.IsTombstone = true;
                }

                // Get the current version from the server.
                IOfflineEntity serverVersion = GetCurrentServerVersionForEntities(
                                                                new List<IOfflineEntity> { syncError.ErrorEntity },
                                                                (SqlConnection)e.Connection,
                                                                (SqlTransaction)e.Transaction)
                                                                .FirstOrDefault();

                // There is no item corresponding to the item sent from the client.
                // Example is an INSERT which caused an RI error and server does not have the record.
                if (null == serverVersion)
                {
                    // If there is no server record and the client changes is not a tombstone, then 
                    // set the LiveEntity as a compensating action which is a tombstone.
                    // This means that the client has to apply the delete locally
                    // for data convergence.

                    // If there is no server record and the client is a tombstone, then we ideally should
                    // just ackowledge the action and don't send any response but
                    // for now we will keep the sync error as is. 

                    _converter.GetEntityFromDataRow(e.Conflict.RemoteChange.Columns, e.Conflict.RemoteChange.Rows[0], syncError.LiveEntity);
                    syncError.LiveEntity.ServiceMetadata.IsTombstone = true;
                }
                else
                {
                    syncError.LiveEntity = serverVersion;
                }

                if (this.ApplyClientChangeFailed != null)
                {
                    this.ApplyClientChangeFailed(syncError.ErrorEntity);
                }

                // This will add the item as an exception to the server knowledge and will also send the exception to the client.
                // However the exception will be cleared the next time the client uploads changes, since we increment tickcounts always.

                applyAction = ApplyAction.Continue;

                // The ApplyChangesFailed event is fired when a conflict is detected. During resolution,
                // if change application fails due to some errors (such as RI, connectivity issues etc), 
                // the provider fires the ApplyChangesFailed event again 
                // to report an error. If we save the error entity as is, then both the original conflict and this new error
                // will be sent back to the client in the response. Since this is not desirable, we first need to remove the
                // corresponding conflict entity from the _conflicts collection before recording the error.

                // Note: item versions are not bumped since the conflict has not yet been resolved.

                RemoveEntityFromConflictCollection(tableName, syncError.LiveEntity);

                _syncErrors.Add(syncError);

                e.Action = applyAction;

                return;
            }

            // Create instances of OfflineCapableEntities and initialize the WinningChange and LosingChange properties.
            var c = new SyncConflict
                        {
                            LiveEntity = (IOfflineEntity)constructorInfo.Invoke(null),
                            LosingEntity = (IOfflineEntity)constructorInfo.Invoke(null)
                        };

            ConflictResolutionPolicy policyToUse = _conflictResolutionPolicy;

            SyncConflictResolution? userResolution = null;
            // Check and fire any Conflict interceptors            
            if (_configuration.HasConflictInterceptors(this._scopeName) ||
                _configuration.HasTypedConflictInterceptor(this._scopeName, entityType))
            {
                userResolution = GetUserConflictResolution(e, constructorInfo, entityType);

                if (userResolution != null && userResolution == SyncConflictResolution.ServerWins)
                {
                    policyToUse = ConflictResolutionPolicy.ServerWins;
                }
                else if (userResolution != null &&
                    (userResolution == SyncConflictResolution.ClientWins || userResolution == SyncConflictResolution.Merge))
                {
                    // If resolution is Merge or ClientWins, set the resolution to ClientWins so the runtime will 
                    // retry with force write and save the merged values back
                    policyToUse = ConflictResolutionPolicy.ClientWins;
                }
            }

            // If there were no Errors, then act based on the service conflict resolution policy.
            switch (policyToUse)
            {
                // ServerWins policy...
                case ConflictResolutionPolicy.ServerWins:

                    // For OCS, ApplyAction.Continue means ServerWins (local change will be maintained).
                    applyAction = ApplyAction.Continue;

                    // If the local change exists, then save it in the WinningChange property
                    if (null != e.Conflict.LocalChange && 1 == e.Conflict.LocalChange.Rows.Count)
                    {
                        _converter.GetEntityFromDataRow(e.Conflict.LocalChange.Columns, e.Conflict.LocalChange.Rows[0], c.LiveEntity);
                    }
                    // If local change does not exist
                    else
                    {
                        _converter.GetEntityFromDataRow(e.Conflict.RemoteChange.Columns, e.Conflict.RemoteChange.Rows[0], c.LiveEntity);
                        c.LiveEntity.ServiceMetadata.IsTombstone = true;
                    }

                    // Save the remote change in the LosingChange property.
                    if (1 == e.Conflict.RemoteChange.Rows.Count)
                    {
                        _converter.GetEntityFromDataRow(e.Conflict.RemoteChange.Columns, e.Conflict.RemoteChange.Rows[0], c.LosingEntity);
                    }

                    // Save the conflict resolution policy. 
                    c.Resolution = WebUtil.GetSyncConflictResolution(ConflictResolutionPolicy.ServerWins);

                    // Set the tombstone flag based on the type of the conflict.
                    switch (e.Conflict.Type)
                    {
                        case DbConflictType.LocalDeleteRemoteDelete:
                            c.LosingEntity.ServiceMetadata.IsTombstone = true;
                            c.LiveEntity.ServiceMetadata.IsTombstone = true;
                            break;
                        case DbConflictType.LocalDeleteRemoteUpdate:
                            c.LiveEntity.ServiceMetadata.IsTombstone = true;
                            break;
                        case DbConflictType.LocalUpdateRemoteDelete:
                            c.LosingEntity.ServiceMetadata.IsTombstone = true;
                            break;
                        // No changes to the tombstone flag for other cases.
                        default:
                            break;
                    }

                    if (this.ApplyClientChangeFailed != null)
                    {
                        this.ApplyClientChangeFailed(c.LosingEntity);
                    }

                    break;

                // ClientWins policy...
                case ConflictResolutionPolicy.ClientWins:

                    // For OCS, client change can be kept by using ApplyAction.RetryWithForceWrite.
                    applyAction = ApplyAction.RetryWithForceWrite;

                    if (1 == e.Conflict.RemoteChange.Rows.Count)
                    {
                        _converter.GetEntityFromDataRow(e.Conflict.RemoteChange.Columns, e.Conflict.RemoteChange.Rows[0], c.LiveEntity);
                    }

                    // If the local change exists, then save it in the WinningChange property
                    if (1 == e.Conflict.LocalChange.Rows.Count)
                    {
                        _converter.GetEntityFromDataRow(e.Conflict.RemoteChange.Columns, e.Conflict.LocalChange.Rows[0], c.LosingEntity);
                    }

                    // Save the conflict resolution policy. 
                    c.Resolution = userResolution ?? WebUtil.GetSyncConflictResolution(ConflictResolutionPolicy.ClientWins);

                    // Set the tombstone flag based on the type of the conflict.
                    switch (e.Conflict.Type)
                    {
                        case DbConflictType.LocalDeleteRemoteDelete:
                            c.LosingEntity.ServiceMetadata.IsTombstone = true;
                            c.LiveEntity.ServiceMetadata.IsTombstone = true;
                            break;
                        case DbConflictType.LocalDeleteRemoteUpdate:
                            c.LosingEntity.ServiceMetadata.IsTombstone = true;
                            break;
                        case DbConflictType.LocalUpdateRemoteDelete:
                            c.LiveEntity.ServiceMetadata.IsTombstone = true;
                            break;
                        // No changes to the tombstone flag for other cases.
                        default:
                            break;
                    }

                    if (this.ApplyClientChangeFailed != null)
                    {
                        this.ApplyClientChangeFailed(c.LiveEntity);
                    }

                    break;
            }

            // After deciding on the Live and the Losing entities for the conflict, we need to generate and save the SyncId 
            // of the LiveEntity. This value is used later after all changes are applied to project on the latest 
            // server knowledge and add positive exceptions to the updated client knowledge that is sent in the response.

            SyncId rowId = GenerateSyncIdForConflictingEntity(tableName, c.LiveEntity);

            if (!_conflictToSyncEntityIdMapping.ContainsKey(c))
            {
                _conflictToSyncEntityIdMapping.Add(c, rowId);

                // Note: SyncId's are unique for each entity.
                Debug.Assert(!_syncEntityIdToConflictMapping.ContainsKey(rowId), "!_syncEntityIdToConflictMapping.ContainsKey(rowId)");

                // Also fill the reverse mapping of syncId to the conflict entity.
                _syncEntityIdToConflictMapping.Add(rowId, c);
            }
            
            _conflicts.Add(c);

            e.Action = applyAction;
        }
Пример #31
0
        private void ApplyLocalChangesFailedFn(object sender, DbApplyChangeFailedEventArgs e)
        {
            Console.WriteLine(e.Conflict.Type);

            Console.WriteLine(e.Error);
        }
Пример #32
0
 private static void sync_error_event_handler_remote(object sender, DbApplyChangeFailedEventArgs e)
 {
     try
     {
         Debug.WriteLine("=========SYNC ERROR==========");
         // display conflict type
         Debug.WriteLine(e.Conflict.Type);
         // display error message
         Debug.WriteLine(e.Error);
         Debug.WriteLine("=========END SYNC ERROR==========");
     }
     catch (Exception ex)
     {
         Debug.WriteLine(ex);
     }
 }
        static void Program_ApplyChangeFailed(object sender, DbApplyChangeFailedEventArgs e)
        {
            // display conflict type
            Console.WriteLine(e.Conflict.Type);

            if (e.Conflict.Type == DbConflictType.LocalUpdateRemoteUpdate)
            {
                Console.WriteLine("diadeem");
            }

                // display error message
                Console.WriteLine(e.Error);
        }
Пример #34
0
 public static void Program_ApplyChangeFailed(object sender, DbApplyChangeFailedEventArgs e)
 {
     WriteErrorLog(string.Format("SCP Conflict.Type Error : {0}", e.Conflict.Type));
     WriteErrorLog(string.Format("SCP Error : {0}", e.Error));
 }
        /// <summary>
        /// Invokes the users Conflict Interceptor and returns back with a resolution.
        /// </summary>
        /// <param name="e">Actual event args</param>
        /// <param name="constructorInfo">ConstructorInfo object</param>
        /// <param name="entityType">Entity type of the conflict</param>
        private SyncConflictResolution? GetUserConflictResolution(DbApplyChangeFailedEventArgs e, ConstructorInfo constructorInfo, Type entityType)
        {
            // Create the Client and Server entities
            IOfflineEntity clientVersion = (IOfflineEntity)constructorInfo.Invoke(null);
            IOfflineEntity serverVersion = null;

            // Read RemoteChange as client version
            _converter.GetEntityFromDataRow(e.Conflict.RemoteChange.Columns, e.Conflict.RemoteChange.Rows[0], clientVersion);

            // Set tombstone based on DbSyncConflict as the DataRow is always marked unchanged
            clientVersion.ServiceMetadata.IsTombstone =
                e.Conflict.Type == DbConflictType.LocalDeleteRemoteDelete ||
                e.Conflict.Type == DbConflictType.LocalUpdateRemoteDelete;

            if (e.Conflict.LocalChange != null && e.Conflict.LocalChange.Rows.Count > 0)
            {
                // Server row exists. Create memory for row.
                serverVersion = (IOfflineEntity)constructorInfo.Invoke(null);
                _converter.GetEntityFromDataRow(e.Conflict.LocalChange.Columns, e.Conflict.LocalChange.Rows[0], serverVersion);

                // Set tombstone based on DbSyncConflict as the DataRow is always marked unchanged
                serverVersion.ServiceMetadata.IsTombstone =
                    e.Conflict.Type == DbConflictType.LocalDeleteRemoteDelete ||
                    e.Conflict.Type == DbConflictType.LocalDeleteRemoteUpdate;
            }

            IOfflineEntity mergedVersion = null;
            this._conflictContext.ClientChange = clientVersion;
            this._conflictContext.ServerChange = serverVersion;

            SyncConflictResolution? userResolution = this._configuration.InvokeConflictInterceptor(
                this._conflictContext,
                entityType,
                out mergedVersion);

            // Check to see the resolution.
            if (userResolution != null && userResolution == SyncConflictResolution.Merge)
            {
                // Check that mergedVersion is not null and is of the expected type
                if (mergedVersion == null)
                {
                    throw new InvalidOperationException("User SyncConflictInterceptor returned a conflict resolution of 'Merge' but did not specify a merged version.");
                }
                if (mergedVersion.GetType() != clientVersion.GetType())
                {
                    throw new InvalidOperationException(
                        string.Format(CultureInfo.InvariantCulture,
                                      "User SyncConflictInterceptor returned merged version entity type '{0} does not match required type '{1}'.",
                                      mergedVersion.GetType().Name, clientVersion.GetType().Name));
                }

                // Merge is required
                // If merge is requested then the server version is always the losing version as changes are overwritten. In this case
                // set the policy to clientWins and copy the mergedVersion values in to the Args.Conflict.RemoteChange
                object[] rowValues = _converter.CopyEntityToDataRow(mergedVersion, e.Conflict.RemoteChange);

                // Now add this row back to the DataSet to we can retry applying this.
                _converter.MergeChangeInToDataSet(e.Context.DataSet.Tables[e.Conflict.RemoteChange.TableName], e.Conflict.RemoteChange.Rows[0], rowValues, mergedVersion.GetType());
            }

            return userResolution;
        }
Пример #36
0
 public void ShowFailures(object syncOrchestrator, DbApplyChangeFailedEventArgs args)
 {
     args.Action = ApplyAction.Continue;
 }
Пример #37
0
 public void ShowFailures(object syncOrchestrator, DbApplyChangeFailedEventArgs args)
 {
     args.Action = ApplyAction.Continue;
 }
 private static void dbProvider_SyncProcessFailed
     (object sender, DbApplyChangeFailedEventArgs e)
 {
     //Common.WriteLog(System.DateTime.Now.ToString() + e.Context.ToString());
 }