I am creating a custom geoprocessing tool for ArcGIS Desktop/Server. During the tool execution, I create a dbf file and access its contents using a cursor. The lock on this file remains after the tool has finished executing and can only be removed by restarting ArcMap/ArcCatalog. Is there a programmatic method to remove the schema lock?
I have stepped into the code below, line by line. Creation of the ITable ArcObject creates a lock file ending in ".sr.lock" and creating the ICursor object creates a lock file ending in ".rd.lock" in the same directory as the dbf file. Without using either ReleaseComObject method at the bottom, both files persist. I can get the second lock file from the cursor removed but not the one associated with the table. Even if I delete the dbf file, the lock files persist, and the parent directory cannot be deleted until ArcMap/ArcCatalog is closed.
There is code here that hints at a solution, but there are elements of that code that are missing.
public Dictionary<Int32, Dictionary<Int32,Double>> GetTabulatedAreaDict()
{
IGPUtilities3 gpUtil = new GPUtilitiesClass();
Geoprocessor gp = new Geoprocessor();
//Tabulate Area
string tableName = "lcAreaByRru.dbf";
string tablePath = this.tempDirPath + "\\" + tableName;
TabulateArea tabulateArea = new TabulateArea();
tabulateArea.in_zone_data = this.rruPath;
tabulateArea.zone_field = "VALUE";
tabulateArea.in_class_data = this.rasterValue.GetAsText();
tabulateArea.class_field = "VALUE";
tabulateArea.out_table = tablePath;
gp.Execute(tabulateArea, null);
// Extract information from table
IWorkspaceFactory wsf = new ShapefileWorkspaceFactoryClass();
IWorkspace ws = wsf.OpenFromFile(this.tempDirPath, 0);
IFeatureWorkspace fws = (IFeatureWorkspace)ws;
ITable taTable = fws.OpenTable(tableName);// Creates .sr.lock file
//ITable taTable = gpUtil.OpenTableFromString(tablePath); // Creates .sr.lock file
ICursor tableRows = taTable.Search(null, false); // Creates .rd.lock file
IRow tableRow = tableRows.NextRow();
this.tabulatedAreaDict = new Dictionary<Int32, Dictionary<Int32, Double>>();
while (tableRow != null)
{
Int32 id = (Int32)tableRow.get_Value(1); // Feature ID
Dictionary<Int32, Double> valueAreaDict = new Dictionary<Int32, Double>();
for (int i = 2; i < tableRow.Fields.FieldCount; i++)
{
int key = int.Parse(tableRow.Fields.get_Field(i).Name.Split('_')[1]);
double value = (double)tableRow.get_Value(i);
valueAreaDict.Add(key, value);
}
this.tabulatedAreaDict.Add(id, valueAreaDict);
tableRow = tableRows.NextRow();
}
System.Runtime.InteropServices.Marshal.ReleaseComObject(tableRows); //Removes .rd.lock file
System.Runtime.InteropServices.Marshal.ReleaseComObject(taTable); // Does not remove .sr.lock file
return this.tabulatedAreaDict;
}
Update:
I found that the dbf was not locked, but there were stray lock files associated with the dbf. While ArcCatalog was still running, I was able to delete the table, but I was not able to delete the folder containing the dbf. Deletion of the parent directory failed when using the ArcCatalog GUI or Windows Explorer. I was able to delete the folder using the Delete_management geoprocessing tool.
I had considered accessing the dbf using a non-ArcObjects method, but I realized I would probably run into this problem later with feature classes and geodatabases, so it was best to continue using ArcObjects.
To better manage this issue, I intend to create the table in the scratch workspace (system temp if unspecified) then move the file to the correct destination when I'm finished accessing it.