(一)
GIS系统数据是基础,想必大家在做ArcEngine二次开发的过程中都会遇到向MDB和SDE写入数据的工作,我们将会通过几个篇幅,从大数据量导入过程中的问题和解决方式入手带给大家一些实用的经验。
1.数据的写入和删除要使用IWorkspaceEdit.StartEditing来开启一个编辑流程,千万别草率的写入和删除。使用该接口,如果数据在处理过程中出现任何异常,可以不对操作结果进行保存编辑和结束编辑IWorkspaceEdit.StopEditing,这样能够保证你处理的数据不被破坏。
2.读取数据要释放游标和要素类,循环IFeatureCursor过程中要释放Feature,循环结束时释放IFeatureCursor。
while ((feature = featureCursor.NextFeature()) != null) { Marshal.ReleaseComObject(feature);//释放要素 } Marshal.ReleaseComObject(featureCursor);//释放游标
3.有时会在导入过程中需要对原始数据进行加工和处理,那么可以考虑将SDE中大数据量的图层分批导入到MDB(Personal Geodatabase)中,在对MDB中的数据进行加工和处理后导入到新的图层中。数据导入一批就进行保存编辑然后再开始编辑,这样会更好的保证数据的导入成功率,如数据量在200万条执行一次导入成功率会比每次导入50万条的成功率低很多,如果为每个要素类导入时开启一个专用的gsrvr进程那么成功率将是最高的。分批处理和导入也会大幅提升速度。
4.在保持编辑后要手动调用垃圾回收机制,这样能够在数据保存后释放掉gsrvr进程,可以有效的避免gsrvr进程死锁。
GC.Collect(); //发起一轮全面的回收
(二)
上一篇中提到在导入过程中需要对大数据量的原始数据进行加工和处理后导入到新的图层中,可以考虑采用分批处理和导入,这里就通过一个事例来说明具体的实现方式。
先来看看图形数据结构:
1.原始数据DataSet中有三个图层分别是:StationEquipment(站内设备层、线层)、StationLine(站内连接线层、线层)、StationFrame(站房边框层、面层),站内设备层和站内连接线层中的要素在空间关系上它们都分布在站房边框层要素内。其中站内设备层和站内连接线层的数据量在100万条以上,站房边框层有2800条数据。
2.新数据DataSet中对应有三个图层分别是:NewStationEquipment(站内设备层、点层)、NewStationLine(站内连接线层、线层)、NewStationFrame(站房边框层、面层)。
数据处理要求:
1.要将原始数据中的站内设备层中的线要素转换为点要素导入到新的站内设备层中(把线要素的中心点存储到新的站内设备层中)。
2.要将原始数据中的站内连接线层的线要素延长到新的设备点要素上,形成连接关系。
介绍完数据情况和处理要求后,我们来看看具体的实现方式:
1.建立一个Personal Geodatabase文件命名为Staion.mdb,按照原始数据图层的结构在MDB中创建3个图层。
2.分批将原始数据中的100站房边框层要素和通过空间查询得到站内设备层要素和站内连接线层要素导入到通过Staion.mdb作为模板复制的一个MDB文件中。
(1)分批将原始数据导入到每个MDB中
public void SDEDataMigrate() { int start = 1; string[] SDELayerNames = { "SDE.StationEquipment", "SDE.StationLine", "SDE.StationFrame" }; string[] MDBLayerNames = { "StationEquipment", "StationLine", "StationFrame" }; //加载SDE图层 OpenSDE(SDELayerNames); //循环分批导入MDB,每次复制100个站房数据到一个拷贝的MDB中 while (start > 0) { start = CopyGDB(start, start.ToString(), MDBLayerNames); } }
(2)拷贝MDB,导入原始数据到MDB中
private int CopyGDB(int start, string directoryName, string[] layerNames) { IWorkspaceFactory workspaceFactory; IFeatureWorkspace featureWorkspace; IWorkspaceName workName; IWorkspaceName workNameCopy; string resourceDirectory = @"D:\Personal GDB"; IFileNames fileNames; IFeatureClass featureClass; IFeatureLayer featureLayer; int stop; //目的地目录是否存在 if (!Directory.Exists(directoryName)) { Directory.CreateDirectory(directoryName); } fileNames = new FileNamesClass(); fileNames.Add(@"D:\Personal GDB\Staion.mdb"); workspaceFactory = new AccessWorkspaceFactoryClass(); workName = workspaceFactory.GetWorkspaceName(resourceDirectory, fileNames); workspaceFactory.Copy(workName, directoryName, out workNameCopy); featureWorkspace = workspaceFactory.OpenFromFile(directoryName + @"\Staion.mdb", 0) as IFeatureWorkspace; foreach (string layerName in layerNames) { featureClass = featureWorkspace.OpenFeatureClass(layerName); featureLayer = new FeatureLayer(); featureLayer.FeatureClass = featureClass; featureLayer.Name = featureClass.AliasName; _MDBLayerList.Add(featureLayer); } //开始编辑 WorkSpaceStartEdit(featureWorkspace as IWorkspace); //导入数据 stop = SDEDataCopy(start, 10); _MDBLayerList.Clear(); //结束编辑 WorkSpaceStopEdit(featureWorkspace as IWorkspace); Marshal.ReleaseComObject(workspaceFactory); return stop; }