当前位置:   article > 正文

基于C#的ArcEngine二次开发29:GDB文件操作及异常处理_domain.vct.filegdb

domain.vct.filegdb

目录

1. ArcCatalog创建GDB、MDB、SHP

2. 代码创建gdb工作空间

2.1 CreateFileGDB Class创建

2.2 Acrivator.CreateInstance创建

2.2.1 实现代码

2.2.2 空间索引格网大小无效异常及解决方案

2.2.3 完善代码

3 GDB目录删除与资源释放

3.1 删除gdb文件

3.2 资源解除占用

3.2.1 杀死文件:

3.2.2 解除资源锁定:

3.2.3 资源释放问题

4 从gdb中拷贝图层到mdb中

4.1 从gdb中获取感兴趣图层

4.2 获取gdb感兴趣图层的图层名

4.3 打开mdb文件

4.4 判断要拷贝到mdb的文件是否存在

4.5 输出mdb图层名设置

4.6 字段赋值

4.7 设置几何定义

 4.8 满足条件的数据查询

4.9 数据转换



1. ArcCatalog创建GDB、MDB、SHP

  • 打开arccatalog

ARCGIS数据建库:GDB数据、MDB数据、SHP数据库

  • 选择要建库的位置——右键——新建

ARCGIS数据建库:GDB数据、MDB数据、SHP数据库

  • 文件地理数据库就是格式为gdb的数据

ARCGIS数据建库:GDB数据、MDB数据、SHP数据库

  • 个人地理数据库就是格式为mdb的数据

ARCGIS数据建库:GDB数据、MDB数据、SHP数据库

  • shapefile就是格式为shp的数据

ARCGIS数据建库:GDB数据、MDB数据、SHP数据库

2. 代码创建gdb工作空间

2.1 CreateFileGDB Class创建

Creates a file geodatabase in a folder. [在给定目录下创建一个地理数据库]

  1. //创建GDB文件对象
  2. CreateFileGDB process1 = new CreateFileGDB {out_folder_path = @"D:\新建文件夹", out_name = "temp.gdb"}

注意上述代码中为out_folder_path设定的目录必须是已存在的目录,否则在使用GP工具执行时,会报错:对COM组件的调用返回了错误 HRESULT E_FAIL

GP.Execute(processor1, null);//将创建的GDB文件加入到GP工具中

2.2 Acrivator.CreateInstance创建

2.2.1 实现代码

  1. /// <summary>
  2. /// 在指定目录下创建gdb文件
  3. /// </summary>
  4. /// <param name="path">创建目录</param>
  5. /// <returns>返回工作空间</returns>
  6. public static IWorkspace CreateFileGdbWorkspace(string gdbFileName)
  7. {
  8. Type factoryType = Type.GetTypeFromProgID(
  9. "esriDataSourcesGDB.FileGDBWorkspaceFactory");
  10. IWorkspaceFactory workspaceFactory = (IWorkspaceFactory)Activator.CreateInstance
  11. (factoryType);
  12. string path = System.IO.Path.GetDirectoryName(gdbFileName);
  13. string fileName = System.IO.Path.GetFileName(gdbFileName);
  14. IWorkspaceName workspaceName = workspaceFactory.Create(path, fileName, null, 0);
  15. IName name = (IName)workspaceName;
  16. IWorkspace workspace = (IWorkspace)name.Open();
  17. return workspace;
  18. }

2.2.2 空间索引格网大小无效异常及解决方案

  • 错误:空间索引格网大小无效
  • 当通过 CreateFeature 和 Store 方法或使用 InsertCursor 创建新要素时,可能发生以下错误而导致创建失败:“FDO_E_INVALID_GRID_SIZE -2147216894 空间索引格网大小无效。”
  • 原因: 在创建要素的要素类的格网过小而无法处理要素,所以将出现 FDO_E_INVALID_GRID_SIZE 错误。 仅在使用文件地理数据库或 ArcSDE 地理数据库时会发生此错误。

根据错误消息出现方式的不同,可采用两种不同的方式来处理此错误。

  • 如果在 ArcMap 中进行编辑时出现此错误,可重新计算或修改要素类的格网大小以容纳新要素。 必须在 ArcCatalog 的“要素类”属性对话框中重新计算格网大小。 此操作需要使用“停止编辑”功能,保存一切更改并关闭包含要素类的地图文档。 有关如何重新计算或修改要素类格网大小的步骤,请参阅以下 Web 帮助文档:设置空间索引。
  • 如果在 ArcObjects API 中以编程方式遇到此错误,则通知用户手动修改空间索引不是理想的解决方案。 相反,可以在插入要素之前将要素类置于 LoadOnly 模式,以避免发生此错误。 当要素类退出 LoadOnly 模式时,地理数据库将自动重新计算适合的格网大小。 以下代码示例演示了如何将 LoadOnly 模式与要素类配合使用:

2.2.3 完善代码

  1. IQueryFilter filter = new QueryFilterClass();
  2. filter.WhereClause = "";
  3. IFeatureCursor pFeaturnCuesor = srcFeatureClass.Search(filter, false);
  4. IFeature pFeature = pFeaturnCuesor.NextFeature();
  5. IFeatureClassLoad dstFeaLoad = dstFeatureClass as IFeatureClassLoad;
  6. dstFeaLoad.LoadOnlyMode = true;
  7. while (pFeature != null)
  8. {
  9. IFeature dstFea = dstFeatureClass.CreateFeature();
  10. dstFea.Shape = pFeature.Shape;
  11. dstFea.Store();
  12. pFeature = pFeaturnCuesor.NextFeature();
  13. }

3 GDB目录删除与资源释放

3.1 删除gdb文件

gdb实际上是一个文件夹,所以要使用文件夹删除的方式删除

  1. ///dir为要删除的文件夹
  2. public void deleteDir(string dir)
  3. {
  4. try
  5.     {
  6.         Directory.Delete(dir, true);
  7.     }
  8.     catch
  9.     {
  10.         foreach (string file in Directory.GetFiles(dir))
  11.         {
  12.             FileInfo info = new FileInfo(file);
  13.             info.Attributes = FileAttributes.Normal;
  14.             File.Delete(file);
  15.         }
  16.         Directory.Delete(dir);
  17.      }
  18. }

代码二:

将IWorkspace转为IDataset,然后使用IDataset.Delete();进行删除。最好不要使用System.IO.File.Delete(path); 根据mdb或FileGDB的路径删除,这种方法可能删除不掉或者删不干净。

  1. IDataset dataset = pWorkspace as IDataset; 
  2. dataset.Delete();

注意:删除该workspace之前需要将使用到的FeatureClass,Feature,FeatureCursor,Field等AO对象先释放掉,可以使用System.Runtime.InteropServices.Marshal.FinalReleaseComObject();释放。

  1. IWorkspaceFactory pWF = new FileGDBWorkspaceFactoryClass();
  2. IWorkspace pW = pWF.OpenFromFile(gdbPath);
  3. IFeatureWorkspace pWorkspace = pW as IFeatureWorkspace;
  4. .....
  5. IDataset dataset = pWorkspace as IDataset;
  6. dataset.Delete();

3.2 资源解除占用

3.2.1 杀死文件:

  1. Process[] pcs = Process.GetProcesses();
  2. foreach (Process p in pcs)
  3. {
  4. if (p.MainModule.FileName == "你的文件路径")
  5. {
  6. p.Kill();
  7. }
  8. }

3.2.2 解除资源锁定:

  1. ArcEngine /AO创建IWorkSpaceFactory的两种方式:
  2. //第一种使用ae的工厂方法:
  3.  IWorkspaceFactory pWsFactory = new ShapefileWorkspaceFactoryClass();
  4.  IFeatureWorkspace  pWorkSpace = pWsFactory.OpenFromFile(path, 0) as IFeatureWorkspace;
  5. //第二种使用C#的动态创建类型的方法:
  6. Type typeObj=Type .GetTypeFromProgID("esriWorkspaceType.ShapefileWorkspaceFactoryClass" );
  7. IWorkspaceFactory pWsFactory = (IWorkspaceFactory)Activator.CreateInstance(typeObj,null);
  8. IFeatureWorkspace  pWorkSpace = pWsFactory.OpenFromFile(path, 0) as IFeatureWorkspace;
  9. //关闭资源锁定  
  10. IWorkspaceFactoryLockControl ipWsFactoryLock = IWorkspaceFactoryLockControl)pWsFactory; //pWsFactory可以是GDB/SHP/MDB
  11. if(ipWsFactoryLock.SchemaLockingEnabled)
  12. {
  13. ipWsFactoryLock.DisableSchemaLocking();
  14. }

3.2.3 资源释放问题

AE中对MDB,SDE等数据库操作时,打开后却往往不能及时释放资源,导致别人操作提示对象被锁定。很多帖子说了很多原理,看的也烦且不实用,比如一句话概括的用System.Runtime.InteropServices.Marshal.ReleaseComObject(object o) 释放,说的很不清楚,很多人试过觉的释放不掉。事实上,的确是用该方法,但释放的技巧在于,新建几个AE对象就要逐步释放几个,例如:

  1. IWorkspaceFactory Fact = new AccessWorkspaceFactoryClass ();
  2. IFeatureWorkspace Workspace = Fact.Open(Propset,0) as IFeatureWorkspace;
  3. IFeatureClass Fcls = Workspace.OpenFeatureClass ("District");
  4. IFeatureLayer Fly = new FeatureLayerClass();
  5. ……
  6. IFeature pf
  7. IField pfield
  8. ……

再对象运行结束时释放,如:

  1. System.Runtime.InteropServices.Marshal.ReleaseComObject(Fact)
  2. System.Runtime.InteropServices.Marshal.ReleaseComObject(Workspace);
  3. System.Runtime.InteropServices.Marshal.ReleaseComObject(Fcls);
  4. System.Runtime.InteropServices.Marshal.ReleaseComObject(Fly);
  5. System.Runtime.InteropServices.Marshal.ReleaseComObject(pf);
  6. System.Runtime.InteropServices.Marshal.ReleaseComObject(pfield);

看到吧,千万不要以为你释放了等级最高的 IWorkspaceFactory, IWorkspace就算完事了。没办法,AE有时就这么难以理解的麻烦。

4 从gdb中拷贝图层到mdb中

主要是为了调用 IFeatureDataConverter.ConvertFeatureClass 方法:

  1. public IEnumInvalidObject ConvertFeatureClass (
  2.     IFeatureClassNameInputDatasetName,
  3.     IQueryFilterInputQueryFilter,
  4.     IFeatureDatasetNameoutputFDatasetName,
  5.     IFeatureClassNameoutputFClassName,
  6.     IGeometryDefOutputGeometryDef,
  7.     IFieldsOutputFields,
  8.     stringconfigKey,
  9.     intFlushInterval,
  10.     intparentHWND);

为了给该函数提供参数,进行如下步骤拆解:

  • 从gdb中获取感兴趣图层
  • 从gdb中获取感兴趣图层的名称
  • 打开mdb文件
  • 判断要拷贝文件是否存在,存在删除
  • 将gdb待拷贝图层字段赋值到mdb目标图层
  • 设置集合定义
  • 设置查询条件
  • 调用转换函数

4.1 从gdb中获取感兴趣图层

  • 打开工作空间工厂
  • 从文件中打开工作空间,将工作空间跳转为要素工作空间
  • 从要素工作空间中打开要素类
  1. IWorkspaceFactory workspaceFactory = new ESRI.ArcGIS.DataSourcesGDB.FileGDBWorkspaceFactoryClass();
  2. IWorkspace iworkspace = iworkspaceFactory.OpenFromFile(inPath, 0);
  3. IFeatureWorkspace ifeatureWorkspace = (IFeatureWorkspace)iworkspace;
  4. IFeatureClass ipFeaterClass = ifeatureWorkspace.OpenFeatureClass(checkLayerName);

4.2 获取gdb感兴趣图层的图层名

  1. IWorkspaceName inWorkspaceName = (inWorkspace as IDataset).FullName as IWorkspaceName ;
  2. IFeatureClassName inFeatureClassName = new FeatureClassNameClass();
  3. IDatasetName inDatasetName = (IDatasetName)inFeatureClassName;
  4. inDatasetName.WorkspaceName = inWorkspaceName;
  5. inDatasetName.Name = gdbLayerName;

4.3 打开mdb文件

  1. IWorkspaceFactory oworkspaceFactory = new AccessWorkspaceFactory();
  2. IWorkspace oworkspace = oworkspaceFactory.OpenFromFile(inPath, 0);
  3. IFeatureWorkspace ofeatureWorkspace = (IFeatureWorkspace)workspace;
  4. IFeatureClass poFeaterClass = ofeatureWorkspace.OpenFeatureClass(mdbLayerName);

4.4 判断要拷贝到mdb的文件是否存在

  1. IWorkspace2 oworkspace2 = (IWorkspace2)oworkspace;
  2. if (oworkspace2.get_NameExists(esriDatasetType.esriDTFeatureClass, checkLayerName + "_超出图层检查结果"))
  3. {
  4. IFeatureClass pFC = ofeatureWorkspace.OpenFeatureClass(checkLayerName + "_超出图层检查结果");
  5. IDataset pDS = pFC as IDataset;
  6. pDS.Delete();
  7. }

4.5 输出mdb图层名设置

  1. IWorkspaceName ouWorkspaceName = (ouWorkspace as IDataset).FullName as IWorkspaceName ;
  2. IFeatureClassName ouFeatureClassName = new FeatureClassNameClass();
  3. IDatasetName ouDatasetName = (IDatasetName)ouFeatureClassName;
  4. ouDatasetName.WorkspaceName = ouWorkspaceName;
  5. ouDatasetName.Name = mdbLayerName;

4.6 字段赋值

  1. IFieldChecker fieldChecker = new FieldCheckerClass();
  2. fieldChecker.InputWorkspace = iworkspace;//输入数据集工作空间
  3. fieldChecker.ValidateWorkspace = ouWorkpace;//输出工作空间
  4. IFields outFeatureClassFields;
  5. IEnumFieldError enumFieldError;
  6. fieldChecker.Validate(inFeatureClassFields, out enumFieldError, out outFeatureClassFields);

4.7 设置几何定义

  1. IField geometryField = outFeatureClassFields.get_Field(outFeatureClassFields.FindField(inFeatureClass.ShapeFieldName));
  2. IGeometryDef geometryDef = geometryField.GeometryDef;

 4.8 满足条件的数据查询

  1. //Set up the IQueryFilter to convert all the features by leaving a blank WhereClause
  2. QueryFilter qf = new QueryFilterClass();
  3. qf.WhereClause = "";

4.9 数据转换

  1. IFeatureDataConverter fctofc = new FeatureDataConverterClass();
  2. IEnumInvalidObject enumErrors = fctofc.ConvertFeatureClass(inFeatureClassName, qf, null, outFeatureClassName, geometryDef, outFeatureClassFields, "", 1000, 0);

参考资料:从FileGDB导出shp

5 其他代码积累

5.1 添加或删除字段

  1. /// <summary>
  2. /// 删除属性表字段
  3. /// </summary>
  4. /// <param name="layer">需要添加字段的IFeatureLayer</param>
  5. /// <param name="fieldName">添加的字段的名称</param>
  6. /// <returns></returns>
  7. static public bool DeleteField(IFeatureLayer layer, string fieldName)
  8. {
  9. try
  10. {
  11. ITable pTable = (ITable)layer;
  12. IFields pfields;
  13. IField pfield;
  14. pfields = pTable.Fields;
  15. int fieldIndex = pfields.FindField(fieldName);
  16. pfield = pfields.get_Field(fieldIndex);
  17. pTable.DeleteField(pfield);
  18. return true;
  19. }
  20. catch (Exception ex)
  21. {
  22. return false;
  23. }
  24. }
  25. /// <summary>
  26. /// 添加字段
  27. /// </summary>
  28. /// <param name="layer"></param>
  29. /// <param name="fieldName"></param>
  30. /// <param name="filedType"></param>
  31. /// <param name="fieldLength"></param>
  32. /// <returns></returns>
  33. static public bool AddField(IFeatureLayer layer, string fieldName, esriFieldType filedType, int fieldLength)
  34. {
  35. try
  36. {
  37. IFields pFields = layer.FeatureClass.Fields;
  38. // IFieldsEdit pFieldsEdit = pFields as IFieldsEdit;
  39. IFieldEdit pFieldEdit;
  40. pFieldEdit = new FieldClass();
  41. if (fieldName.Length > 5)
  42. pFieldEdit.Name_2 = fieldName.Substring(0, 5);
  43. else
  44. pFieldEdit.Name_2 = fieldName;
  45. pFieldEdit.Type_2 = filedType;
  46. pFieldEdit.Editable_2 = true;
  47. pFieldEdit.AliasName_2 = fieldName;
  48. pFieldEdit.Length_2 = fieldLength;
  49. ITable pTable = (ITable)layer;
  50. pTable.AddField(pFieldEdit);
  51. return true;
  52. // pFieldsEdit.AddField((IField)pFieldEdit);
  53. }
  54. catch (Exception ex)
  55. {
  56. return false;
  57. }
  58. }

 

 

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/341093
推荐阅读
相关标签
  

闽ICP备14008679号