最近做数据处理,需要想MDB中写入一个错误导出图层,没有注意到MDB和GDB的区别,直接使用了GDB 的套路,结果报了“无当前记录”的错误,瞬间懵逼。在网上溜达了一圈,找到都是下面这个答案:
问题:使用 IFeatureWorkspace.CreateFeatureClass() 方法,出现异常:无当前记录百度/谷歌没有找到合适的解决之道.而是用IFeatureWorkspace.CreateTable()方法却正常.要素工作空间为AccessWorkspaceClass(),
原因:不明
解决方法:此段代码直接在Personal Geodatabase中新建要素类,后来改为FileGeoDatabase中新建,出现的异常提示 与空间参考相关.
后来新建FeatureDataset,在FeatureDataset设置空间参考.之后,再在FeatureDataset中新建FeatureClass.成功
看了半天不明所以,问题并没有解决;我理解它的思路是用GDB解决了问题;但是我的需求是导出MDB,所以自己就摸索了一番,把摸索的结果在这里记录一下。
问题原因:CreateFeatureClass的Fields字段出错
我的方案是:先创建只包含SHAPE的要素类,然后再添加字段
1 MDB与GDB的区别与联系分析
这一部分参考源为:https://www.cnblogs.com/xiongyunqi/p/5517118.html
一、平台支援:
1、Personal Geodatabase:仅可在Windows 上运行;
2、File Geodatabase:跨平台支援,可在Windows 及UNIX、linux上运行。
评价:这是个非常大的亮点,使得数据可以更好的移植。
二、存储方式:
1、Personal Geodatabase 是一个MS-Access 的mdb 数据库文档;
2、File Geodatabase 以一个文件夹方式储存。
评价:Personal Geodatabase有依托微软的access数据库的限制,File Geodatabase,可以慢慢摆脱依靠access的限制,不用受制与微软的技术。
三、存储限制:
1、Personal Geodatabase:相同于MS Accesss 限制,数据库最大容量为2GB。
2、File Geodatabase:数据库无限制,每个表限制为1TB(1000GB)。
评价:File Geodatabase支持对海量数据的处理。
四、储存空间:
同样的资料,在File Geodatabase 中比Personal Geodatabase 和Shapefile占用的硬盘空间更少,通常可以减少50%~70%,最多可减少到1/5。
五、效能:
File Geodatabase 相较于Personal Geodatabase 处理数据的速度可快20%到10倍,这部分随着资料量的增加,效能差异越大。
六、是否支持数据压缩:
1、Personal Geodatabase:不支持数据压缩。
2、File Geodatabase:支持一种新的数据压缩格式,在查询与显示方面均与未压缩格式相同,压缩比率可从2:1 到25:1。
2 ArcEngine处理GDB、MDB和shape
2.1 获取三类数据
E中,GDB和MDB的获取方式是不同的,对于GDB的工作空间工厂为:
IWorkspaceFactory pWF = new FileGDBWorkspaceFactoryClass(); IWorkspace pWS = pWF.OpenFromFile(gdbPath, 0);
而打开MDB的代码为:
IWorkspaceFactory pWF = new AccessWorkspaceFactoryClass(); IWorkspace pWS = pWF.OpenFromFile(gdbPath, 0);
获取Shape文件的代码为:
IWorkspaceFactory pWF = new ShapefileWorkspaceFactoryClass(); IWorkspace pWS = pWF.OpenFromFile(shapeDir, 0);
显然在AE中,采用了三种不同的方式来处理三类数据,其中MDB和shape表现的是文件的形式,而GDB则是以文件夹的形式表示;但是有一点是相同的,在使用OpenFromFile打开时,GDB和mdb传的是完整路径,而shape文件则传的是其上级目录。
2.2 打开要素类
所谓殊途同归,在这里最合适不过了,打开要素类,三种数据源不约而同的使用OpenFeatureClass函数:
IFeatureWorkspace pFWs = pWS as IFeatureWorkspace; IFeatureClass pFeaCls = pWS.OpenFeatureClass("LRDL");
但是还是要注意以下几点:
GDB使用该方法只能打开直接存放在GDB下的要素类,要打开存放在要素集中要素类,需要先打开要素集FeatureDataset
shape文件传递的参数是shape的文件名称,因为shape的文件名即要素类名称
3 新建要素类
本文要解决的主要问题是MDB中新建要素类,之前的权当铺垫。
3.1 CreateFeatureClass函数解析
该方法包含以上7个参数:
3.2 Fields
其中报的无当前记录异常,就是出在Fields字段上
一次性创造了好几个字段,然后一把整进去,结果就报了错;实际上AE内部是不让咱这么干的,在你创建的时候只有几个关键字段,如OBJECTID、Shape等,这些默认字段;其余的字段,你要想加,只能是要素类创建完成了,再一个一个往里边添加。这么分析未知对错,但是解决了我遇到的这个问题。
3.2.1 方案1-使用IFeatureClassDescription
IFeatureClassDescription fcDescription = new FeatureClassDescriptionClass(); IObjectClassDescription ocDescription = (IObjectClassDescription)fcDescription; IFields fields = ocDescription.RequiredFields;
使用这个代码倒是解决了异常,投影没办法设置,想做实验的参考这篇文章:AE新建工作空间要素类示例
3.2.2 方案2-先创建再添加
- 首先定义几何图形的类型、参考系统、字段名称、几何类型
//设置几何图形类型 IGeometryDef geometryDef = shpfield.GeometryDef; IGeometryDefEdit geometryDefEdit = (IGeometryDefEdit)geometryDef; geometryDefEdit.GeometryType_2 = esriGeometryType.esriGeometryPoint; //设置参考系统 ISpatialReferenceFactory3 spatialReferenceFactory = new SpatialReferenceEnvironmentClass(); ISpatialReference spatialReference = spatialReferenceFactory.CreateSpatialReference((int)esriSRGeoCSType.esriSRGeoCS_WGS1984); geometryDefEdit.SpatialReference_2 = spatialReference; //创建字段并赋值 IField field = new FieldClass(); IFieldEdit fieldEdit = (IFieldEdit)field; fieldEdit.Name_2 = "Shape"; fieldEdit.Type_2 = esriFieldType.esriGeometryType; fieldEdit.GeometryDef_2 = geometryDef; fieldsEdit.AddField(field);
3.3 CLSID
- 设置要素类型UID,也即CLSID,下面借用arcengine创建要素类、图层的方法的总结
//pUidClsID字段为空时 if (pUidClsId == null) { pUidClsId = new UIDClass(); switch (pFeatureType) { case (esriFeatureType.esriFTSimple): if (pGeometryType == esriGeometryType.esriGeometryLine) pGeometryType = esriGeometryType.esriGeometryPolyline; pUidClsId.Value = "{52353152-891A-11D0-BEC6-00805F7C4268}"; break; case (esriFeatureType.esriFTSimpleJunction): pGeometryType = esriGeometryType.esriGeometryPoint; pUidClsId.Value = "{CEE8D6B8-55FE-11D1-AE55-0000F80372B4}"; break; case (esriFeatureType.esriFTComplexJunction): pUidClsId.Value = "{DF9D71F4-DA32-11D1-AEBA-0000F80372B4}"; break; case (esriFeatureType.esriFTSimpleEdge): pGeometryType = esriGeometryType.esriGeometryPolyline; pUidClsId.Value = "{E7031C90-55FE-11D1-AE55-0000F80372B4}"; break; case (esriFeatureType.esriFTComplexEdge): pGeometryType = esriGeometryType.esriGeometryPolyline; pUidClsId.Value = "{A30E8A2A-C50B-11D1-AEA9-0000F80372B4}"; break; case (esriFeatureType.esriFTAnnotation): pGeometryType = esriGeometryType.esriGeometryPolygon; pUidClsId.Value = "{E3676993-C682-11D2-8A2A-006097AFF44E}"; break; case (esriFeatureType.esriFTDimension): pGeometryType = esriGeometryType.esriGeometryPolygon; pUidClsId.Value = "{496764FC-E0C9-11D3-80CE-00C04F601565}"; break; } }
3.4 EXTCLSID
//pUidClsExt字段为空时 if (pUidClsExt == null) { switch (pFeatureType) { case esriFeatureType.esriFTAnnotation: pUidClsExt = new UIDClass(); pUidClsExt.Value = "{24429589-D711-11D2-9F41-00C04F6BC6A5}"; break; case esriFeatureType.esriFTDimension: pUidClsExt = new UIDClass(); pUidClsExt.Value = "{48F935E2-DA66-11D3-80CE-00C04F601565}"; break; } }
3.5 创建代码
tFeatureClass = tFeatureWorkspace.CreateFeatureClass(pName, pFields, pUidClsId, pUidClsExt, pFeatureType, strShapeFieldName, pConfigWord);
3.6 添加字段
int checkFieldIndex = poFeaterClass.FindField("检查结果记录"); if(checkFieldIndex == -1) { IFields pFields = new FieldClass(); IFieldEdit pFieldEdit = pFields as IFieldEdit; pFieldEdit.Name_2 = "检查结果记录"; pFieldEdit.Type_2 = filedType; pFieldEdit.Length_2 = fieldLength; poFeaterClass.AddField(pFieldEdit); }