基于C#的ArcEngine二次开发50:MDB创建新要素类及“无当前记录”异常处理

简介: 基于C#的ArcEngine二次开发50:MDB创建新要素类及“无当前记录”异常处理

最近做数据处理,需要想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个参数:

image.png

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

 //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);    
    }
相关实践学习
阿里云图数据库GDB入门与应用
图数据库(Graph Database,简称GDB)是一种支持Property Graph图模型、用于处理高度连接数据查询与存储的实时、可靠的在线数据库服务。它支持Apache TinkerPop Gremlin查询语言,可以帮您快速构建基于高度连接的数据集的应用程序。GDB非常适合社交网络、欺诈检测、推荐引擎、实时图谱、网络/IT运营这类高度互连数据集的场景。 GDB由阿里云自主研发,具备如下优势: 标准图查询语言:支持属性图,高度兼容Gremlin图查询语言。 高度优化的自研引擎:高度优化的自研图计算层和存储层,云盘多副本保障数据超高可靠,支持ACID事务。 服务高可用:支持高可用实例,节点故障迅速转移,保障业务连续性。 易运维:提供备份恢复、自动升级、监控告警、故障切换等丰富的运维功能,大幅降低运维成本。 产品主页:https://www.aliyun.com/product/gdb
相关文章
|
1月前
|
C#
C#学习相关系列之数据类型类的三大特性(二)
C#学习相关系列之数据类型类的三大特性(二)
|
1月前
|
C#
58.c#:directory类
58.c#:directory类
12 0
|
1月前
|
C#
57.c#:directorylnfo类
57.c#:directorylnfo类
13 0
|
1月前
|
C#
深入C#中的String类
深入C#中的String类
11 0
|
1月前
|
C#
C#学习系列相关之多线程(二)----Thread类介绍
C#学习系列相关之多线程(二)----Thread类介绍
|
1月前
|
C#
C#学习相关系列之数据类型类----嵌套类和嵌套方法(三)
C#学习相关系列之数据类型类----嵌套类和嵌套方法(三)
|
1月前
|
存储 C# 索引
C#学习相关系列之数据类型类的定义(一)
C#学习相关系列之数据类型类的定义(一)
|
1月前
|
存储 API C#
60.c#:steamreader类
60.c#:steamreader类
12 0
|
1月前
|
API C# vr&ar
59.c#:steamWriter类
59.c#:steamWriter类
16 0
|
1月前
|
C# 数据安全/隐私保护
56.c#:filelnfo类
56.c#:filelnfo类
13 2