带OfflineStore的DatasyncClient调用PushTablesAsync触发PushFailedException
解决Azure Data Sync Push时的PreconditionFailed(ETag不匹配)问题
问题根源
PushFailedException触发PreconditionFailed状态,核心是乐观并发冲突:本地缓存的实体ETag与服务器端最新ETag不一致。即便数据已同步至服务器,本地离线存储的ETag未正确更新,导致后续同步无法自动恢复。
客户端侧修复方案
1. 捕获异常并手动更新本地ETag
调用PushTablesAsync()时捕获异常,遍历失败操作,从服务器响应提取最新ETag更新本地实体后重新推送:
try { await _dataSyncClient.PushTablesAsync(); } catch (PushFailedException ex) { foreach (var failure in ex.PushResult.Failures) { // 获取服务器返回的最新ETag var serverETag = failure.ServerItem.ETag; // 更新本地实体ETag failure.LocalItem.ETag = serverETag; // 持久化更新后的实体到离线存储 await _offlineTable.UpdateAsync(failure.LocalItem); } // 重新执行推送 await _dataSyncClient.PushTablesAsync(); }
2. 配置冲突解决策略(谨慎使用)
若业务允许服务器版本优先,可在推送时设置ConflictResolutionPolicy为ServerWins,让服务器数据覆盖本地冲突项:
var pushOptions = new PushOptions { ConflictResolutionPolicy = ConflictResolutionPolicy.ServerWins }; await _dataSyncClient.PushTablesAsync(pushOptions);
注意:此方式会直接覆盖本地冲突数据,仅适用于服务器版本为权威数据源的场景。
3. 规范本地ETag管理
- 禁止手动修改实体的ETag字段,交由Data Sync客户端自动维护。
- 确保离线存储的新增/更新操作后,ETag被正确持久化到本地SQLite数据库。
服务器侧排查点
- 确认Azure Web App的Data Sync服务端,实体的ETag字段已配置
[Timestamp]属性(对应SQL Server的rowversion类型),且服务端未手动修改ETag值。 - 检查是否有其他进程/服务直接修改SQL Server数据,导致ETag异常更新,客户端未同步到最新版本。
自动恢复优化封装
封装同步逻辑,加入针对PreconditionFailed的自动重试机制,避免手动删除本地数据库或执行Purge:
public async Task SafePushAsync(int maxRetries = 3) { int retryCount = 0; while (retryCount < maxRetries) { try { await _dataSyncClient.PushTablesAsync(); break; } catch (PushFailedException ex) when (ex.PushResult.Failures.Any(f => f.Status == HttpStatusCode.PreconditionFailed)) { retryCount++; foreach (var failure in ex.PushResult.Failures.Where(f => f.Status == HttpStatusCode.PreconditionFailed)) { failure.LocalItem.ETag = failure.ServerItem.ETag; await _offlineTable.UpdateAsync(failure.LocalItem); } } } }
内容的提问来源于stack exchange,提问作者Dave
相关产品推荐
相关产品推荐

