Hello,
I'm having an issue deleting rows from a table using the EditOperation class. My code is as follows:
QueuedTask.Run(() =>
{
Table dnoXrefTable = Utilities.GetPrdTable("SPATIAL.DNO_XREF");
QueryFilter qf = new QueryFilter { WhereClause = $"FACILITYID='{facilityId}' AND FEATURECLASS='{featureClassName}'" };
var deleteOperation = new EditOperation();
deleteOperation.Name = "Delete features";
using (var rowCursor = dnoXrefTable.Search(qf, false))
{
while (rowCursor.MoveNext())
{
using (var row = rowCursor.Current)
{
deleteOperation.Delete(row);
}
}
}
deleteOperation.Execute();
});
No errors but data isn't removed from the table after it runs. I can delete the features manually so I don't think it's a permissions issue.
Thanks in advance for any help!
Solved! Go to Solution.
Actually, after i tried your use case with my code snippet again i realized that my dataset didn't really represent the one-to-many (related records) use case property, instead with my data i always only had one related record that was correctly deleted. After changing my query logic, i was able to duplicate the same problem that you are seeing. I think that this is actually a bug. I will pass this on to the Editor team.
However, there is a workaround for this issue. You can use the EditOperation Delete method on the table instead of deleting each row. The following code snippet worked for me:
// collect all object ids that need to be deleted
List<long> ids = new List<long>();
using (var tableCursor = _countyTable.Search(qf))
{
while (tableCursor.MoveNext())
{
using (var tableRow = tableCursor.Current)
{
//not working as expected: deleteEditOp.Delete(tableRow);
ids.Add(tableRow.GetObjectID());
}
}
}
// delete all records with objects ids
deleteEditOp.Delete(_countyTable, ids);
Can you check if this works for you?
Instead of using EditOperation you can also use this:
dnoXrefTable.DeleteRows(qf);
Thanks Wolf. Unfortunately I get an error saying it cannot be edited outside of an edit session (I assume because it's an enterprise table).
Well it was worth a try. I will use an Enterprise table to try this. I didn't see anything wrong with your code.
I tried your code snippet with a SQL Server Enterprise GDB and it works as expected. Here are my modifications:
protected override void OnClick()
{
if (MapView.Active == null)
{
MessageBox.Show("No active map");
return;
}
QueuedTask.Run(() =>
{
var featureLayer = MapView.Active.Map.GetLayersAsFlattenedList().OfType<FeatureLayer>().FirstOrDefault();
if (featureLayer == null)
{
MessageBox.Show("No Counties feature layer found");
return;
}
Table dnoXrefTable = featureLayer.GetTable();
QueryFilter qf = new QueryFilter { WhereClause = $"STATE_NAME like ('New%')" };
var deleteOperation = new EditOperation
{
Name = "Delete features"
};
using (var rowCursor = dnoXrefTable.Search(qf, false))
{
while (rowCursor.MoveNext())
{
using (var row = rowCursor.Current)
{
deleteOperation.Delete(row);
}
}
}
var delResult = deleteOperation.Execute();
if (delResult != true)
MessageBox.Show($@"Not successful: {deleteOperation.ErrorMessage}");
MessageBox.Show("Edit operation complete");
});
}
I am using a copy of the Counties dataset (from the c:\data\admin folder using Community Samples data). I coded my queryfilter to delete all counties where the state name contains 'New...'.
Here are my screen shots:
1. Before i click my delete button:
2. the delete function has completed:
3. After the OnClick exits (New York and New Hampshire are gone):
If i run the same delete function again i get this message:
So you get no message at all?
Thanks again Wolf, I may have a clue in the ErrorMessage property, but it only tells me, "Not successful: Edit operation failed." and nothing else.
What kind of Enterprise GDB are you using and is the table (or feature class) in the content of your map?
It's an oracle gdb, and yes I have the table in my Table of Contents to verify the feature is removed/not removed.
Sorry I should also mention that this is following a RowDeletedEvent. So I delete another feature in the enterprise GDB, and then as part of this process it should delete the corresponding table links in the XREF table.
This code worked for me. To test I have a feature class (County) and a table with related records (CountyTable).
After i subscribe to the featureclass's row delete event, the related record is deleted after the feature is deleted. This screen shot is after i deleted the 'Larimer' county:
I used the following code to accomplish this. I think the issue is that you have to attach your delete (of the related row) to the 'parent edit operation'.
internal class ActivateRelatedDeletes : Button
{
private SubscriptionToken _rowDeletedToken;
private StandaloneTable _countyTable = null;
protected override void OnClick()
{
if (MapView.Active == null)
{
MessageBox.Show("No active map");
return;
}
QueuedTask.Run(() =>
{
_countyTable = MapView.Active.Map.GetStandaloneTablesAsFlattenedList().OfType<StandaloneTable>().Where(fl => fl.Name.Contains("CountyTable")).FirstOrDefault();
if (_countyTable == null)
{
MessageBox.Show("Cannot find County Table");
return;
}
var featureLayer = MapView.Active.Map.GetLayersAsFlattenedList().OfType<FeatureLayer>().Where(fl => fl.Name.Contains("County")).FirstOrDefault();
if (featureLayer == null)
{
MessageBox.Show("No County feature layer found");
return;
}
var addLinkedOperation = new EditOperation
{
Name = "Add linked rows"
};
_rowDeletedToken = RowDeletedEvent.Subscribe(OnRowEvent, featureLayer.GetTable());
});
}
private void OnRowEvent(RowChangedEventArgs delEventArgs)
{
// get the parent Edit operation
var deleteEditOp = delEventArgs.Operation;
// delete all related records using the FIPS relationship
System.Diagnostics.Trace.WriteLine($@"Deleted related: {delEventArgs.Row["NAME"]}");
var atts = new Dictionary<string, object>();
QueryFilter qf = new QueryFilter { WhereClause = $"FIPS = '{delEventArgs.Row["FIPS"]}'" };
using (var tableCursor = _countyTable.Search(qf))
{
while (tableCursor.MoveNext())
{
using (var tableRow = tableCursor.Current)
{
deleteEditOp.Delete(tableRow);
}
}
}
}
}
Thanks Wolf for all your help thus far. I found swapping my getPrdTable() function for finding it in the table of contents works, so I'll have to diagnose that function, but it still only deletes one row. It iterates through all the rows but after finishing only the last one is deleted. Any idea why? My code for the RowDeletedEvent is as follows:
protected static void OnRowDeletedEvent(RowChangedEventArgs args)
{
//Table dnoTable = Utilities.GetPrdTable("SPATIAL.DNO_XREF");
StandaloneTable dnoTable = MapView.Active.Map.GetStandaloneTablesAsFlattenedList().OfType<StandaloneTable>().FirstOrDefault(); // (only one standalone table in ToC)
var deleteOperation = args.Operation;
QueryFilter qf = new QueryFilter { WhereClause = $"FACILITYID='{args.Row["FACILITYID"]}' AND FEATURECLASS='{args.Row.GetTable().GetDefinition().GetModelName()}'" }; // multiple feautres
using (var rc = dnoTable.Search(qf))
{
while (rc.MoveNext())
{
using (var deleteRow = rc.Current)
{
string oid = deleteRow["OBJECTID"].ToString();
deleteOperation.Delete(deleteRow);
}
}
}
}