本来做的事情是将SDE中任意范围内的要素按查询条件导出到文件地理数据库,最初使用的是IFeatureDataConverter接口的ConvertFeatureClass方法,可是后来发现这个方法不支持注记要素类的导出,且会将其变成多边形要素。于是想到按几何查询条件将一个个要素写入到新建的要素类中,实现代码如下:
IFeatureClass targetFeatureClass = (targetWorkspace as IFeatureWorkspace).CreateFeatureClass(fcName,
sourceFeatureClass.Fields, null, null, sourceFeatureClass.FeatureType, "shape", "");
IFeatureCursor pFeatureCursor = sourceFeatureClass.Search(pSpatialFilter, false);
IFeature sFeature = pFeatureCursor.NextFeature();
while (sFeature != null)
{
AddFeatureToFC(targetFeatureClass, sFeature);
sFeature = pFeatureCursor.NextFeature();
}
Marshal.ReleaseComObject(pFeatureCursor);
可是每当运行到
IFeatureCursor pFeatureCursor = sourceFeatureClass.Search(pSpatialFilter, false);
时就会报错 An expected Field was not found or could not be retrieved properly. [SHAPE.AREA] ,有时候会报错Failed sending the dataset deleted notification to a workspace extension. [Survey Database]。代码上的微调会导致出现不同的错误,至今还没搞明白是为什么。不过也发现,只有注记要素类才会发生这种错误,其他点线面要素类是不会发生的。
搜索时,发现竹子也遇到了这个问题,原因应该是在创建数据库时引用了sourceFeatureClass.Fields,创建之后两者共用一套Fields,查询时会有冲突。实际上因为注记要素类和其他要素类不同,他是采用FDO(Feature Data Object)技术处理的,在FDO中有模式(Schema)这一概念,我的理解,是因为上述代码中的过程中,新旧两个要素类引用了相同的模式,至于为什么引用了相同的模式会出错,我就不得而知了。关于FDO的技术,可以参考博客GIS解决之道---深入FDO、AutoCAD Map 3D和MapGuide
知道了原因,那就容易找到解决方案了,核心是在创建新要素类时不要引用原来的Fields,方法有两种:
一种方法是用IClone克隆一个,代码如下
IClone clone = sourceFeatureClass.Fields as IClone;
IFields pFields = clone.Clone() as IFields;
另一种方法是如竹子,自己新建Fields