ArcObjects ExcelWorkspaceFactory 不会发布 Excel 文件
ArcObjects ExcelWorkspaceFactory Won't Release Excel File
我正在使用 ArcObjects 设置从 xls 和 csv 文件到地理数据库的批量导入。那部分工作正常,但导入后,我想删除文件。但是,这不起作用,因为该文件仍处于打开状态。 None 个正在使用的接口派生自 IDisposable 或公开 Close 方法。我也尝试过使用 ComReleaser 强制关闭我打开的所有 COM 对象,但这也不起作用。我所看到的与关闭连接有关的唯一事情是我需要删除对这些类型的所有引用并强制进行垃圾收集,这违反了标准(有充分的理由)。
这是我用于 excel 导入的方法:
private ServiceResult<IEnumerable<int>> InsertControlsFromXls(FileInfo xlsFile) {
ServiceResult<IEnumerable<int>> result = new ServiceResult<IEnumerable<int>>();
using(ComReleaser comReleaser = new ComReleaser()) {
//read in the spreadsheet as a workspace
Type factoryType = Type.GetTypeFromProgID("esriDataSourcesOleDB.ExcelWorkspaceFactory");
IWorkspaceFactory workspaceFactory = (IWorkspaceFactory)Activator.CreateInstance(factoryType);
IWorkspace workspace = workspaceFactory.OpenFromFile(xlsFile.FullName, 0);
IFeatureWorkspace remoteWorkspace = (IFeatureWorkspace)OpenWorkspace();
IFeatureWorkspace featureWorkspace = (IFeatureWorkspace)workspace;
IWorkspaceEdit2 session = (IWorkspaceEdit2)remoteWorkspace;
IMultiuserWorkspaceEdit multiuserWorkspace = (IMultiuserWorkspaceEdit)remoteWorkspace;
comReleaser.ManageLifetime(workspaceFactory);
comReleaser.ManageLifetime(workspace);
comReleaser.ManageLifetime(remoteWorkspace);
comReleaser.ManageLifetime(featureWorkspace);
comReleaser.ManageLifetime(session);
comReleaser.ManageLifetime(multiuserWorkspace);
try {
//session.StartEditing(false);
multiuserWorkspace.StartMultiuserEditing(esriMultiuserEditSessionMode.esriMESMVersioned);
session.StartEditOperation();
Match tableMatch = _tableRecReg.Match(xlsFile.Name);
string tableName = tableMatch.Success ? tableMatch.Groups[1].Value + "$" : "Sheet1$";
ITable table = featureWorkspace.OpenTable(tableName);
result.Value = CopyAllFeatures(table, remoteWorkspace.OpenFeatureClass(AppSettings.DefaultSchema + "." + ControlMap.TableName));
session.StopEditOperation();
session.StopEditing(true);
} catch {
session.AbortEditOperation();
session.StopEditing(false);
throw;
}
}
return result;
}
好的,我通过疯狂地使用 ComReleaser 对象让它工作。基本上,我扫描了我的代码,每当我发现任何来自 ArcObjects 的东西时,我都会附加一个 ComReleaser 来管理它。基本上,我只是在进行手动内存管理。无论如何,它似乎确实释放了文件,只要 EVERYTHING 被释放(即使它看起来不相关)。如上面的评论所述,ComReleaser class 应该在底层使用 ReleaseComObject,因此该路径也应该有效。
我猜在您的示例中是 ITable 导致的。 table 对象将锁定 sheet。至少,它在其他地理数据库中这样做。
不确定 CopyAllFeatures 的作用,但也要留意 ICursor。
我正在使用 ArcObjects 设置从 xls 和 csv 文件到地理数据库的批量导入。那部分工作正常,但导入后,我想删除文件。但是,这不起作用,因为该文件仍处于打开状态。 None 个正在使用的接口派生自 IDisposable 或公开 Close 方法。我也尝试过使用 ComReleaser 强制关闭我打开的所有 COM 对象,但这也不起作用。我所看到的与关闭连接有关的唯一事情是我需要删除对这些类型的所有引用并强制进行垃圾收集,这违反了标准(有充分的理由)。
这是我用于 excel 导入的方法:
private ServiceResult<IEnumerable<int>> InsertControlsFromXls(FileInfo xlsFile) {
ServiceResult<IEnumerable<int>> result = new ServiceResult<IEnumerable<int>>();
using(ComReleaser comReleaser = new ComReleaser()) {
//read in the spreadsheet as a workspace
Type factoryType = Type.GetTypeFromProgID("esriDataSourcesOleDB.ExcelWorkspaceFactory");
IWorkspaceFactory workspaceFactory = (IWorkspaceFactory)Activator.CreateInstance(factoryType);
IWorkspace workspace = workspaceFactory.OpenFromFile(xlsFile.FullName, 0);
IFeatureWorkspace remoteWorkspace = (IFeatureWorkspace)OpenWorkspace();
IFeatureWorkspace featureWorkspace = (IFeatureWorkspace)workspace;
IWorkspaceEdit2 session = (IWorkspaceEdit2)remoteWorkspace;
IMultiuserWorkspaceEdit multiuserWorkspace = (IMultiuserWorkspaceEdit)remoteWorkspace;
comReleaser.ManageLifetime(workspaceFactory);
comReleaser.ManageLifetime(workspace);
comReleaser.ManageLifetime(remoteWorkspace);
comReleaser.ManageLifetime(featureWorkspace);
comReleaser.ManageLifetime(session);
comReleaser.ManageLifetime(multiuserWorkspace);
try {
//session.StartEditing(false);
multiuserWorkspace.StartMultiuserEditing(esriMultiuserEditSessionMode.esriMESMVersioned);
session.StartEditOperation();
Match tableMatch = _tableRecReg.Match(xlsFile.Name);
string tableName = tableMatch.Success ? tableMatch.Groups[1].Value + "$" : "Sheet1$";
ITable table = featureWorkspace.OpenTable(tableName);
result.Value = CopyAllFeatures(table, remoteWorkspace.OpenFeatureClass(AppSettings.DefaultSchema + "." + ControlMap.TableName));
session.StopEditOperation();
session.StopEditing(true);
} catch {
session.AbortEditOperation();
session.StopEditing(false);
throw;
}
}
return result;
}
好的,我通过疯狂地使用 ComReleaser 对象让它工作。基本上,我扫描了我的代码,每当我发现任何来自 ArcObjects 的东西时,我都会附加一个 ComReleaser 来管理它。基本上,我只是在进行手动内存管理。无论如何,它似乎确实释放了文件,只要 EVERYTHING 被释放(即使它看起来不相关)。如上面的评论所述,ComReleaser class 应该在底层使用 ReleaseComObject,因此该路径也应该有效。
我猜在您的示例中是 ITable 导致的。 table 对象将锁定 sheet。至少,它在其他地理数据库中这样做。
不确定 CopyAllFeatures 的作用,但也要留意 ICursor。