Xamarin中的Azure移动服务412故障
本文关键字:故障 服务 移动 中的 Azure Xamarin | 更新日期: 2023-09-27 18:27:00
每当试图通过MobileServices更新项目时,我总是会收到412个错误(PreconditionFailed)。我相信这是最近开始的,但不幸的是,这个错误给我的信息很少。
我已经设置了一个冲突解决程序,其想法是在发生任何冲突时,将客户端版本作为赢家,根据https://azure.microsoft.com/en-us/documentation/articles/mobile-services-windows-store-dotnet-handling-conflicts-offline-data/.为了做到这一点,我重复了推动的呼吁。然而,我在两次推送中都失败了412次,而不仅仅是第一次。
这是我的处理程序代码。
public class AzureConflictHandler : IMobileServiceSyncHandler
{
readonly ILogger _logger;
public AzureConflictHandler(ILogger logger){
_logger = logger;
}
#region IMobileServiceSyncHandler implementation
public Task OnPushCompleteAsync (MobileServicePushCompletionResult result)
{
return Task.FromResult (false);
}
public async Task<JObject> ExecuteTableOperationAsync (IMobileServiceTableOperation operation)
{
try{
await operation.ExecuteAsync ();
return null;
}
catch (MobileServiceConflictException ex)
{
_logger.HandleException (ex);
}
catch (MobileServicePreconditionFailedException ex)
{
_logger.HandleException (ex);
//https://codemilltech.com/why-cant-we-be-friends-conflict-resolution-in-azure-mobile-services/
}
catch(Exception e){
_logger.HandleException (e);
throw;
}
try
{
//retry so we'll take the client value
await operation.ExecuteAsync();
return null;
}
catch (MobileServicePreconditionFailedException e)
{
_logger.HandleException(e, LogLevel.Fatal);
return e.Value;
}
}
#endregion
}
其他人看到这个错误了吗?我的数据对象中有一个Version字段,如下所示。
public string id { get; set; }
public string EntityType { get; set; }
public Guid EntityID { get; set; }
public string EntityJSON { get; set; }
public DateTimeOffset LastUpdatedDate { get; set; }
[Microsoft.WindowsAzure.MobileServices.Version]
public string Version { set; get; }
我不知道教程为什么这么说,但目前是不正确的。
第二次调用execute,不会更改结果,本地项永远不会自动修改。(从技术上讲,如果你只想赢得最后一次写入(客户端),你可以从你的数据模型中删除版本,你永远不会得到412。)
假设从长远来看,您需要一个更复杂的策略,那么您需要使用服务器的版本副本更新本地项的版本。
catch (MobileServicePreconditionFailedException ex) {
var serverValue = ex.Value;
// Resolve in favor of our client by just using the server's version
var item = operation.Item;
item[MobileServiceSystemColumns.Version] = serverValue[MobileServiceSystemColumns.Version];
// this will save the item changes to the local store so next Push()
// will resolve this
operation.UpdateOperationAsync(item)
throw ex;
}
在上面的代码中,尽管您立即重试,但要注意它应该处于循环中,因为另一个客户端也可能在更新它,等等。
在这种情况下,你可以做一些更像的事情
while (some condition) {
try {
return await operation.ExecuteAsync();
} catch (obileServicePreconditionFailedException ex) {
var serverItem = ex.Value;
operation.item[MobileServiceSystemColumns.Version] = serverValue[MobileServiceSystemColumns.Version];
} catch ...
}
https://github.com/Azure/mobile-services-samples/blob/master/TodoOffline/WindowsUniversal/TodoOffline/TodoOffline.Shared/SyncHandler.cs#L27