I was looking at the ExportDeltaAsync method to use in a custom sync workflow we have. What is unclear to me is how you could trim the results of this to be only the edits since a certain time.
If I were to use ExportDeltaAsync at 12:00 and then send those to the server and sync that delta file to the server. If I run the ExportDeltaAsync at 1:00, it would seem I will still get all the edits from before 12:00. Is there a way to reset the HasEdits on the Geodatabase or some other other way that one only Exports the Deltas since the last time that ExportDeltaAsync was called?
Hi Joe,
The ExportDeltaAsync is based on the last sync time on the geodatabase. I just tested the following code, if there's a syncGeodatabase happened in between, no delta is created. Code snippet against sample server is shared below.
HasEdits only reset after edits are applied/sync'd or undone/rolled back. Edits in a mobile geodatabase can be wrapped in explicit transaction by gdb.Begin/Commit/RollbackTransaction().
If you're uploading client delta a different way, the API will not have information about the last acknowledged update to compare with the edit and gdb tracking fields. Geodatabase.hasLocalEdits(), ArcGISFeatureTable.hasLocalEdits() and ArcGISFeatureTable.getLocalEditsAsync() are all based on this time. There's a GeodatabaseFeatureTable.getHasLocalEditsSince() with DateTimeOffset parameter that you could use but it only returns boolean.
Is there something in the current sync workflow that can be improved to support your custom sync processes?
private const string FeatureServiceUrl = "https://sampleserver6.arcgisonline.com/arcgis/rest/services/Sync/SaveTheBaySync/FeatureServer";
private async Task TestExportDeltaAsync(bool syncBeforeExport = false)
{
try
{
var task = await GeodatabaseSyncTask.CreateAsync(new Uri(FeatureServiceUrl));
var areaOfInterest = task.ServiceInfo?.FullExtent;
ArgumentNullException.ThrowIfNull(areaOfInterest);
var parameters = await task.CreateDefaultGenerateGeodatabaseParametersAsync(areaOfInterest);
var pathToGeodatabase = $@"C:\dev\gdb\{Guid.NewGuid()}.geodatabase";
Debug.WriteLine(pathToGeodatabase);
var job = task.GenerateGeodatabase(parameters, pathToGeodatabase);
var gdb = await job.GetResultAsync();
// introduce an edit
areaOfInterest = gdb.GenerateGeodatabaseGeometry?.Extent;
ArgumentNullException.ThrowIfNull(areaOfInterest);
if (gdb.GetGeodatabaseFeatureTable(0) is GeodatabaseFeatureTable table)
{
await table.LoadAsync();
if (table.GeometryType == GeometryType.Point
&& table.FeatureTypes.Count > 0
&& !string.IsNullOrEmpty(table.LayerInfo?.DisplayFieldName))
{
var random = new Random();
var index = random.Next(0, table.FeatureTypes.Count - 1);
var featureType = table.FeatureTypes[index];
double x = areaOfInterest.XMin + random.NextDouble() * areaOfInterest.Width;
double y = areaOfInterest.YMin + random.NextDouble() * areaOfInterest.Height;
var point = new MapPoint(x, y, areaOfInterest.SpatialReference);
var feature = table.CreateFeature(featureType, point);
feature.SetAttributeValue(table.LayerInfo.DisplayFieldName, $"Added on {DateTimeOffset.UtcNow}");
await table.AddFeatureAsync(feature);
}
}
if (syncBeforeExport)
{
var syncParameters = await task.CreateDefaultSyncGeodatabaseParametersAsync(gdb);
var syncJob = task.SyncGeodatabase(syncParameters, gdb);
await syncJob.GetResultAsync();
}
var deltaPath = $@"{gdb.Path.Replace(".geodatabase", "")}-delta.geodatabase";
var hasDeltaExported = await GeodatabaseSyncTask.ExportDeltaAsync(gdb, deltaPath);
Debug.WriteLine($"Exported? {hasDeltaExported}");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
private async void OnExportDelta(object sender, RoutedEventArgs e)
{
await TestExportDeltaAsync(true);
await TestExportDeltaAsync(false);
}
Thanks.
Jennifer