代码之家  ›  专栏  ›  技术社区  ›  StezPet

Microsoft.Azure.Mobile使用自定义IMobileServiceSyncHandler-Xamarin表单处理客户端服务器错误

  •  0
  • StezPet  · 技术社区  · 6 年前

    Sample 在我的Xamarin表格申请中。

    在提供的示例/文档中,他们使用的是默认的服务处理程序。

    //简单的错误/冲突处理。真正的应用程序将通过imobileservicesynchhandler处理各种错误,如网络状况、服务器冲突等。

    因为我需要实施 重试逻辑3次 拉/推失败。 根据文档,我创建了一个定制服务处理程序( ).

    请在这里找到我的代码逻辑。

    public class CustomSyncHandler : IMobileServiceSyncHandler
    {
        public async Task<JObject> ExecuteTableOperationAsync(IMobileServiceTableOperation operation)
        {
            MobileServiceInvalidOperationException error = null;
            Func<Task<JObject>> tryExecuteAsync = operation.ExecuteAsync;
    
            int retryCount = 3;
            for (int i = 0; i < retryCount; i++)
            {
                try
                {
                    error = null;
                    var result = await tryExecuteAsync();
                    return result;
                }
                catch (MobileServiceConflictException e)
                {
                    error = e;
                }
                catch (MobileServicePreconditionFailedException e)
                {
                    error = e;
                }
                catch (MobileServiceInvalidOperationException e)
                {
                    error = e;
                }
                catch (Exception e)
                {
                    throw e;
                }
    
                if (error != null)
                {
                    if(retryCount <=3) continue;
                    else
                    {
                         //Need to implement
                         //Update failed, reverting to server's copy.
                    }
                }
            }
            return null;
        }
    
        public Task OnPushCompleteAsync(MobileServicePushCompletionResult result)
        {
            return Task.FromResult(0);
        }
    }
    

    但我不知道如何处理/恢复 服务器副本,以防所有3次重试都失败。

    在待办事项样本中,他们在哪里 还原 它基于 MobileServicePushFailedException异常 . 但是当我们实施 IMobileServiceSyncHandler . PushAsync/PullAsync . 即使是试一试也不会有例外。

            try
            {
                await this.client.SyncContext.PushAsync();
    
                await this.todoTable.PullAsync(
                    //The first parameter is a query name that is used internally by the client SDK to implement incremental sync.
                    //Use a different query name for each unique query in your program
                    "allTodoItems",
                    this.todoTable.CreateQuery());
            }
            catch (MobileServicePushFailedException exc)
            {
                if (exc.PushResult != null)
                {
                    syncErrors = exc.PushResult.Errors;
                }
            }
    
            // Simple error/conflict handling. A real application would handle the various errors like network conditions,
            // server conflicts and others via the IMobileServiceSyncHandler.
            if (syncErrors != null)
            {
                foreach (var error in syncErrors)
                {
                    if (error.OperationKind == MobileServiceTableOperationKind.Update && error.Result != null)
                    {
                        //Update failed, reverting to server's copy.
                        await error.CancelAndUpdateItemAsync(error.Result);
                    }
                    else
                    {
                        // Discard local change.
                        await error.CancelAndDiscardItemAsync();
                    }
    
                    Debug.WriteLine(@"Error executing sync operation. Item: {0} ({1}). Operation discarded.", error.TableName, error.Item["id"]);
                }
            }
        }
    

    在我的应用程序中,我只尝试实现重试3次,以防任何服务器错误。我不是在寻找解决冲突的方法。Thant是我没有添加相同代码的原因。

    如果有人遇到类似的问题,并解决了它,请帮助。

    斯泰兹。

    2 回复  |  直到 6 年前
        1
  •  1
  •   Eric Hedstrom    6 年前

    您说您不想解决冲突,但是您需要通过接受对象的服务器版本或更新客户机操作来以某种方式解决冲突(可能不告诉用户发生了什么)。否则,每次重试操作时,它都会不断地告诉您相同的冲突。

    你需要有一个Microsoft.WindowsAzure.MobileServices.Sync.MobileServiceSyncHandler类,它重写OnPushCompleteAsync(),以便处理冲突和其他错误。让我们调用类SyncHandler:

    public class SyncHandler : MobileServiceSyncHandler
    {
        public override async Task OnPushCompleteAsync(MobileServicePushCompletionResult result)
        {
            foreach (var error in result.Errors)
            {
                await ResolveConflictAsync(error);
            }
            await base.OnPushCompleteAsync(result);
        }
    
        private static async Task ResolveConflictAsync(MobileServiceTableOperationError error)
        {
            Debug.WriteLine($"Resolve Conflict for Item: {error.Item} vs serverItem: {error.Result}");
    
            var serverItem = error.Result;
            var localItem = error.Item;
    
            if (Equals(serverItem, localItem))
            {
                // Items are the same, so ignore the conflict
                await error.CancelAndUpdateItemAsync(serverItem);
            }
            else // check server item and local item or the error for criteria you care about
            {
                // Cancels the table operation and discards the local instance of the item.
                await error.CancelAndDiscardItemAsync();
            }
        }
    }
    

    初始化MobileServiceClient时包含此SyncHandler()的实例:

    await MobileServiceClient.SyncContext.InitializeAsync(store, new SyncHandler()).ConfigureAwait(false);
    

    仔细阅读 MobileServiceTableOperationError 要查看其他冲突,您可以处理它以及允许解决它们的方法。

        2
  •  0
  •   MrBlueSky    6 年前

    异常附带服务器版本的副本。在我执行 IMobileServiceSyncHandler error.Value 这似乎奏效了。

    这种逻辑的一个更广泛的例子可以在 this MSDN blog

    同一位作者还有另一个例子,他向您展示了如何解决有利于服务器副本或客户端副本的冲突, here .