Edit operation failed - data is currently locked?

6525
18
03-07-2016 07:41 AM
Highlighted
by Anonymous User
Not applicable

I'm trying to use an edit operation to populate attributes of a newly added field in a feature class. But the edit operation fails with the following message:  "Edit operation failed. The data is currently locked by another user and cannot be saved"

My workflow is as follows:

  1. Create new feature class using existing feature class as template (using GP) - success
  2. Copy selected features in template feature class to the new feature class (using GP) - success
  3. Create a new field in feature class (using GP) - success
  4. Try to populate the new field (using this example) - error

What's locking the data? It's certainly not another user. I'm the only user. The gdb workspace is a temp folder in my user appdata dir.

The data isn't on the map or open anywhere else.

18 Replies
Highlighted
Esri Regular Contributor

Hi Luke,

The following code works for me in Pro 1.3. I haven't tried release 1.2 yet. What version are you on?

   protected override async void OnClick()
    {
      //create feature class from template
      var mva = Geoprocessing.MakeValueArray(@"C:\arcgis\ArcTutor\Editing\Zion.gdb", "test", "POINT",@"C:\arcgis\ArcTutor\Editing\Zion.gdb\Ranger_stations");
      var cts = new System.Threading.CancellationTokenSource();
      var result = await Geoprocessing.ExecuteToolAsync("CreateFeatureclass_management", mva, null, cts.Token,null,GPExecuteToolFlags.RefreshProjectItems);

      //copy selected features from a layer in the map to feature class
      mva = Geoprocessing.MakeValueArray("Ranger stations", @"C:\arcgis\ArcTutor\Editing\Zion.gdb\test");
      result = await Geoprocessing.ExecuteToolAsync("CopyFeatures_management", mva,null,cts.Token,null,GPExecuteToolFlags.None);

      //add field to test feature class
      mva = Geoprocessing.MakeValueArray(@"C:\arcgis\ArcTutor\Editing\Zion.gdb\test", "someID", "LONG");
      result = await Geoprocessing.ExecuteToolAsync("AddField_management", mva, null, cts.Token, null, GPExecuteToolFlags.None);

      //calculate field value with editor callback.
      await QueuedTask.Run(() =>
      {
        using (Geodatabase geodatabase = new Geodatabase(@"C:\arcgis\ArcTutor\Editing\Zion.gdb"))
        using (FeatureClass featureClass = geodatabase.OpenDataset<FeatureClass>("test"))
        using (FeatureClassDefinition featureClassDefinition = featureClass.GetDefinition())
        {
          int someIndex = featureClassDefinition.FindField("someID");

          EditOperation editOperation = new EditOperation();
          editOperation.Callback(context =>
          {
            using (RowCursor rowCursor = featureClass.Search(null, false))
            {
              while (rowCursor.MoveNext())
              {
                using (Feature feature = (Feature)rowCursor.Current)
                {
                  feature[someIndex] = 42;
                  feature.Store();
                }
              }
            }
          }, featureClass);
          editOperation.ExecuteAsync();
        }
      });

      //delete the feature class to cleanup
    }

Just as a side note because the target feature class ("test") is not in the map, you can use the editor callback method to update values with the rowcursor as shown in the example. If the layer was in the map however, I would use the editor inspector class and editoperation modify combo to calc the field. Its just easier.

Reply
0 Kudos
Highlighted
by Anonymous User
Not applicable

Hi Sean,

I tried that exact code in 1.2 (with added step to create GDB) and the editOperation returns true (I assume success), but the new field will not populate. It just remains <null>.

I want to edit datastore data, not map data, so went for the callback approach.

See code below:

protected override async void OnClick()

        {

            //create geodatabase

            var cts = new System.Threading.CancellationTokenSource();

            var mva = Geoprocessing.MakeValueArray(@"D:\Temp", "Test.gdb");

            var result = await Geoprocessing.ExecuteToolAsync("CreateFileGDB_management", mva, null, cts.Token, null, GPExecuteToolFlags.RefreshProjectItems);

            //create feature class from template

            mva = Geoprocessing.MakeValueArray(@"D:\Temp\Test.gdb", "Test", "POLYGON", templateTablePath);

            result = await Geoprocessing.ExecuteToolAsync("CreateFeatureclass_management", mva, null, cts.Token, null, GPExecuteToolFlags.RefreshProjectItems);

            //copy selected features from a layer in the map to feature class

            mva = Geoprocessing.MakeValueArray(templateTablePath, @"D:\Temp\Test.gdb\Test");

            result = await Geoprocessing.ExecuteToolAsync("CopyFeatures_management", mva, null, cts.Token, null, GPExecuteToolFlags.None);

            //add field to test feature class

            mva = Geoprocessing.MakeValueArray(@"D:\Temp\Test.gdb\Test", "someID", "LONG");

            result = await Geoprocessing.ExecuteToolAsync("AddField_management", mva, null, cts.Token, null, GPExecuteToolFlags.None);

            //calculate field value with editor callback.

            await QueuedTask.Run(() =>

            {

                using (Geodatabase geodatabase = new Geodatabase(@"D:\Temp\Test.gdb"))

                using (FeatureClass featureClass = geodatabase.OpenDataset<FeatureClass>("Test"))

                using (FeatureClassDefinition featureClassDefinition = featureClass.GetDefinition())

                {

                    int someIndex = featureClassDefinition.FindField("someID");

                    EditOperation editOperation = new EditOperation();

                    editOperation.Callback(context =>

                    {

                        using (RowCursor rowCursor = featureClass.Search(null, false))

                        {

                            while (rowCursor.MoveNext())

                            {

                                using (Feature feature = (Feature)rowCursor.Current)

                                {

                                  

                                    feature[someIndex] = 42;

                                    feature.Store();

                                }

                            }

                        }

                    }, featureClass);

                    editOperation.ExecuteAsync();

                }

            });

            MessageBox.Show("Complete");

        }

Cheers,

Luke

Reply
0 Kudos
Highlighted
Esri Contributor

Luke,

please do take a look at the sample code again. I believe you are missing the context.invalidate call.

However for just changing a single attribute using the callback approach is overkill. A single edit operation with multiple Modify calls should suffice.

Thomas

Highlighted
by Anonymous User
Not applicable

Hi Thomas,

I had included the invalidate call originally but it make no difference unfortunately. Plus from what I'm reading on the editing concepts page, it would seem it's only necessary when I want to refresh the map (which I don't need).

Refreshing the map (or the attributes table) is only needed when the Callback method is used to edit datasets from datastores.

To refresh the map to reflect changes made in the data, call the IEditContext.Invalidate method on the IEditContext parameter on the Action delegate passed into the callback.

Note: If it is known that the edits being made are not going to affect the rendering of any layers, you could avoid calling it at all; or if you knew it would only affect color and not location, you could call it at the end of store.

As I'm not editing data that's on the map - do I have a choice to not use the callback approach? I thought the inspector was only for map data.

Luke

Reply
0 Kudos
Highlighted
Esri Contributor

Luke,

you were stating earlier that the field remains <null>. Depending on when and where you are checking the changed attribute value the invalidate is required as Pro might be showing you a cached state of the data and unless you invalidate the cached state is considered the current state.

Please do take a look at ArcGIS Pro 1.2 API Reference Guide for the overloaded Create method. We have method signatures that accept a table as an argument. A feature class is inheriting from table so you can have multiple feature classes participate in a single edit operation regardless if they are shown in the map or not. Please keep in mind that you will still need to save the edits done by the edit operation in order to be persisted in the geodatabase.

The alternative is ArcGIS Pro 1.2 API Reference Guide which is new at 1.2 and is happening as a single source on the geodatabase.

Thomas

Reply
0 Kudos
Highlighted
by Anonymous User
Not applicable

I'm also unable to edit the field using the inspector class. I've added the feature class in question to the map as a new featurelayer, and used the code below to update the custom field, but values are still null.

When I open the inspector object in debug I can even see that the field attribute is being correctly populated for each feature ("current value" attribute is correct) - but the edits don't ever get applied, despite op.Execute() returning true.

await QueuedTask.Run(() =>

{

    //add the output layer to the map

    var lyr = LayerFactory.CreateFeatureLayer(new Uri(outputFcPath), MapView.Active.Map, LayerPosition.AddToTop);

    var cur = lyr.Search();

    //populate the TEST field

    if (lyr.CanEditData())

    {

      

        while (cur.MoveNext())

        {

            var insp = new Inspector();

            var feature = cur.Current;

            insp.Load(lyr, feature.GetObjectID());

            insp["TEST"] = "testvalue";

            var op = new EditOperation();

            op.Name = "Populate test field";

            op.Modify(insp);

            op.Execute();

        }

    }

});

Reply
0 Kudos
Highlighted
Esri Regular Contributor

Luke,

Sorry about the delay, its dev summit week. I tried to reproduce this at 1.2 and it works ok for me with that code and the arc tutorial data. Something is blocking your layers or workspace but I cant think of anything obvious at this point. If nobody else chimes in here I would contact tech support and be prepared to supply the code and data for the reproducible case you have.

Reply
0 Kudos
Highlighted
by Anonymous User
Not applicable

Hi Sean,

Hope the summit was good this year! Thanks for testing that - i'll revisit my code this week and perhaps try some other data. Must be something on my side...

Cheers,

Luke

Reply
0 Kudos
Highlighted
Occasional Contributor II

Luke Coursey‌ I have the same problem. Did you find a solution?

I made simple test: I executed Add Field tool on shapefile and found 3 (!!!) locks near shp file after tool has finished. Seems like a bug on the ESRI side. I sure that Add Field shouldn't lock dataset. Sean Jones‌ Did you reproduce the issue?

Reply
0 Kudos