每当尝试通过MobileServices更新项目时,我都会遇到412错误(PreconditionFailed).我相信这已经开始了,但不幸的是错误给了我很少的信息.
我设置了一个冲突解决方案,根据https://azure.microsoft.com/en-us/documentation/articles/mobile-services-windows,将客户端版本作为赢家的想法发生冲突.-store-dotnet-handling-conflicts-offline-data /.为此我正在重复推动呼叫.但是我在BOTH推送时失败了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 TaskExecuteTableOperationAsync (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; }
phillipv.. 7
我不确定为什么该教程说明了这一点,但它目前是不正确的.
第二次调用执行不会更改结果,永远不会自动修改本地项.(从技术上讲,如果你只想要最后一次写入胜利(客户端),你可以从数据模型中删除版本,而你永远不会得到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
我不确定为什么该教程说明了这一点,但它目前是不正确的.
第二次调用执行不会更改结果,永远不会自动修改本地项.(从技术上讲,如果你只想要最后一次写入胜利(客户端),你可以从数据模型中删除版本,而你永远不会得到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