Select to view content in your preferred language

Geodatabase.ApplyEdits() and non-SDE Versioned data

1349
2
10-17-2018 09:14 AM
daleward
Occasional Contributor

We're seeing Geodatabase.ApplyEdits() leaving what appear to be unnecessary records in the SDE.STATES and SDE.STATE_LINEAGES tables when we edit non-SDE Versioned data, and are wondering what the cause is.

This from within a "headless" console application, which is why we are using Geodatabase.ApplyEdits(). We do not see this issue when using EditOperation.ExecuteAsync, from within an ArcGIS Pro add-in.

If we point the code below at a non-SDE Versioned Feature Class, we end up with additional records in the SDE.STATES and SDE.STATE_LINEAGES tables.

For example - if we have only one row in both SDE.STATES and SDE.STATE_LINEAGES, and we run the code below that inserts a row into a non-versioned feature class, at the end of the run we'll have two records in SDE.STATES and three records in SDE.STATE_LINEAGES.

If there are lots of updates to a non-versioned feature class in a day, that means our STATES and STATE_LINEAGES tables grow by quite a bit. Which means the user has to compress the database more frequently and/or takes a performance hit on querying versioned layers in the database.

Here's the code we are executing (it's based on the ProConcepts Geodatabase ApplyEdits sample😞

DatabaseConnectionProperties connectionProperties = new DatabaseConnectionProperties(EnterpriseDatabaseType.Oracle)
{
   AuthenticationMode = AuthenticationMode.DBMS,
   Instance = @"OUR_SERVER",
   User = "xxx",
   Password = "xxx",
   Version = "SDE.DEFAULT"  // We've also tried setting this to NULL and not setting it at all.
};

 using (Geodatabase gdb = new Geodatabase(DatabaseConnectionProperties))

{

 using (FeatureClass featureClass = gdb.OpenDataset<FeatureClass>("TEST_NONVERSION_FC"))
{

FeatureClassDefinition fcDefinition = fc.GetDefinition();

gdb.ApplyEdits(() => {
using (RowBuffer rowbuffer = featureClass.CreateRowBuffer())
{

   // set an attribute value
    rowbuffer[1] = 12;

   // create a geometry

   List<MapPoint> points = new List<MapPoint>();
   points.Add(MapPointBuilder.CreateMapPoint(-85.003, 47.012800, 100, 0,    fcDefinition.GetSpatialReference()));
   points.Add(MapPointBuilder.CreateMapPoint(-105.994, 26.368, 1000, 1000,    fcDefinition.GetSpatialReference()));
   using (PolylineBuilder pb = new PolylineBuilder(points))
   {
      pb.SpatialReference = fcDefinition.GetSpatialReference();
      pb.HasM = true;
      pb.HasZ = true;
      rowbuffer[fcDefinition.GetShapeField()] = pb.ToGeometry();
   }

   // insert the data into the feature class
   using (Feature f = featureClass.CreateRow(rowbuffer))
   { }
}
});

}

}

Is the above code's workflow more or less correct?

Is there an additional cleanup we need to perform?

0 Kudos
2 Replies
RichRuh
Esri Regular Contributor

Hi Dale,

I spent some time looking into this.

It turns out that using Geodatabase.ApplyEdits() will create an editing transaction, which will add rows to the SDE_states and SDE_state_lineages tables. This will occur even if the call to ApplyEdits() is completely empty.

gdb.ApplyEdits( ()=>
{
 // nothing here
});‍‍‍‍

What you should be able to do is take your editing code and remove it out of ApplyEdits() entirely. This will result in writing directly to the database without any transaction management. I was able to try this (I used an add-in, but it should work in a CoreHost application as well), and it worked without adding rows to the states tables.

You really do give up all transaction management though.

edit1();
edit2();
edit3();‍‍‍

If edit3 fails, edit1 and edit2 have already been written to the database. If you did

gdb.ApplyEdits( ()=>
{
 edit1();
 edit2();
 edit3();
});

then an error in edit3 would cause edit1 and edit2 to rollback.

I hope this helps,

--Rich

daleward
Occasional Contributor

Thank you, Rich. That makes sense.

0 Kudos