GP开发示例:数据库去重

简介: 这个例子专业讲解基于ArcEngine使用GP开发的过程及遇到的问题。更多GP使用方法:GP使用心得 功能需求:现在外业第一次数据(简称调绘.mdb)和第二次数据(简称检查.mdb)有重复。第二次是在第一次的基础上进行的,即如果调绘.mdb中LCA层有365个要素,检查时发现错误,就删除了11个错误,并新增了43个,共408个,检查.mdb相对于调绘.mdb实际上有354个重复,现在要将重复的删除,mdb中包括点、线、面三种类型的要素类。

这个例子专业讲解基于ArcEngine使用GP开发的过程及遇到的问题。更多GP使用方法:GP使用心得

功能需求:现在外业第一次数据(简称调绘.mdb)和第二次数据(简称检查.mdb)有重复。第二次是在第一次的基础上进行的,即如果调绘.mdb中LCA层有365个要素,检查时发现错误,就删除了11个错误,并新增了43个,共408个,检查.mdb相对于调绘.mdb实际上有354个重复,现在要将重复的删除,mdb中包括点、线、面三种类型的要素类。

软件实现:在ArcGIS里利用工具可以实现,使用按空间位置查询,找出重复的,然后删除即可;由于每个mdb中的要素图层比较多,所以可以使用批处理,批处理时填写参数可以利用Excel快速进行。但是,mdb较多,路径各不相同,图层较多,操作起不比较费时。

程序实现

1.首先确定用什么工具来实现(先在ArcGIS里做一次):利用空间位置查询选择重复的要素,开启编辑器,删除!

2.设计界面,我每写一个功能,都要把界面整理一下,因为我不想让它很丑就出去见人。这里使用DotNetBar,节省了相当多的时间。

image

3.因为是直接对数据库进行操作,所以首先就要遍历数据中的要素图层,一般做法是利用GP的ListFeatureClasses方法。

GP.SetEnvironmentValue("workspace", moreDBPath.Trim());
IGpEnumList pGpEnumList = GP.ListFeatureClasses("", "", "");
string strFC = pGpEnumList.Next();
while (strFC != "")
{
    System.Windows.Forms.Application.DoEvents();
    Console.WriteLine(strFC);
    strFC = pGpEnumList.Next();
}

选择遍历数据库没有问题!

4.利用按位置选择

SelectLayerByLocation SLBL = new SelectLayerByLocation();
SLBL.in_layer = moreDB + "\\" + strFC;
SLBL.select_features = referDB + "\\" + strFC;
SLBL.overlap_type = "ARE_IDENTICAL_TO";
GPClass.Execute(SLBL); //这里使用了自定义的GPClass类,可以直接使用GPExecute

报错ERROR 000368,去官网帮助一查,竟然没有368,这是为什么?但从相邻错误信息来看,应该是哪个参数无效!

image

再去官网看了按空间位置查询的帮助文档。它说:输入必须是要素图层;不可以是要素类。要素图层?要素类?以前一直把它们看成是一种意思,于是去查一下了帮助,长知识了。

image

结果Python的示例代码,使用了MakeFeatureLayer来创建要素图层。

image

//创建要素图层
MakeFeatureLayer MFL = new MakeFeatureLayer();
MFL.in_features = moreDB + "\\" + strFC;
MFL.out_layer = strFC + @"_Lyr";
GPClass.Execute(MFL);

//按位置选择
SelectLayerByLocation SLBL = new SelectLayerByLocation();
SLBL.in_layer = strFC + @"_Lyr";
SLBL.select_features = referDB + "\\" + strFC;
SLBL.overlap_type = "ARE_IDENTICAL_TO";
GPClass.Execute(SLBL);

GP执行成功,虽然还看不到效果。因为MakeFeatureLayer是临时图层,程序结束就没有了,需要将它导出来:

//复制要素导出
CopyFeatures CF = new CopyFeatures();
CF.in_features = strFC + @"_Lyr";
CF.out_feature_class = resultDB + "\\" + strFC;
GPClass.Execute(CF);

现在的问题是是选择类型是ARE_IDENTICAL_TO,如果输入图层中的要素与某一选择要素相同(就几何而言),则会选择这些要素。生成的mdb是重复那一部分,而需要的结果是不重复的那一部分。在ArcGIS里可以通过切换选择来操作。于是想,先把它全部选中,然后将重复的移除。代码:

//创建要素图层
MakeFeatureLayer MFL = new MakeFeatureLayer();
MFL.in_features = moreDB + "\\" + strFC;
MFL.out_layer = strFC + @"_Lyr";
GPClass.Execute(MFL);

//选择所有
SelectLayerByAttribute SLBA = new SelectLayerByAttribute();
SLBA.in_layer_or_view = strFC + @"_Lyr";
GPClass.Execute(SLBA);

//按位置选择(移除)
SelectLayerByLocation SLBL = new SelectLayerByLocation();
SLBL.in_layer = strFC + @"_Lyr";
SLBL.select_features = referDB + "\\" + strFC;
SLBL.overlap_type = "ARE_IDENTICAL_TO";
SLBL.selection_type = "REMOVE_FROM_SELECTION";
GPClass.Execute(SLBL);

//复制要素
CopyFeatures CF = new CopyFeatures();
CF.in_features = strFC + @"_Lyr";
CF.out_feature_class = resultDB + "\\" + strFC;
GPClass.Execute(CF);
终于实现了。

5.为了增加用户的体验,重写在了一个类,并把新建一个线程来处理:

string referDB = "";
string moreDB = "";
string resultDB = "";
ProgressBarX progress = null;
public NoRepeatClass(string _referDB, string _moreDB, string _resultDB, ProgressBarX _progress)
{
    referDB = _referDB;
    moreDB = _moreDB;
    resultDB = _resultDB;
    progress = _progress;

    Thread MyThreadOne = new Thread(new ThreadStart(MainFun));
    MyThreadOne.Name = "NoRepeat";
    MyThreadOne.IsBackground = true;
    MyThreadOne.Start();
}

private void MainFun()
{
 //主程序代码
}

6.为了让用户知道处理的进度,于是添加了进度条,并更新内容为当前处理图层的名称。但这里,不能直接在一个线程里设置主线程的控件属性,于是找了一个函数:

#region 设置控件参数
/// <summary>
/// 设置控件参数
/// </summary>
/// <param name="oControl">控件</param>
/// <param name="propName">参数名称</param>
/// <param name="propValue">参数值</param>
delegate void SetControlValueCallback(Control oControl, string propName, object propValue);
public static  void SetControlPropertyValue(Control oControl, string propName, object propValue)
{
    if (oControl.InvokeRequired)
    {
        SetControlValueCallback d = new SetControlValueCallback(SetControlPropertyValue);
        oControl.Invoke(d, new object[] { oControl, propName, propValue });
    }
    else
    {
        Type t = oControl.GetType();
        System.Reflection.PropertyInfo[] props = t.GetProperties();
        foreach (System.Reflection.PropertyInfo p in props)
        {
            if (p.Name.ToUpper() == propName.ToUpper())
            {
                p.SetValue(oControl, propValue, null);
            }
        }
    }
}
#endregion

目前的效果如下:

image

7.为了提高操作效率,增加了路径拖放功能,下面是拖放类:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace GPTools
{
    class DragClass
    {
        private  Control control;
        private string fileType = "";

        public DragClass(Control _control,string _fileType)
        {
            //如果控件为空 
            if (_control == null)
            {
                return;
            }
            control = _control;
            fileType = _fileType;

            //设置是否可以拖放
            control.AllowDrop = true;

            //定义拖放事件
            control.DragEnter += new DragEventHandler(control_DragEnter);
          ontrol.DragDrop += new DragEventHandler(control_DragDrop);

        }

        private void control_DragEnter(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                e.Effect = DragDropEffects.Copy;
            }
        }

        private void control_DragDrop(object sender, DragEventArgs e)
        {
            string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
            foreach (string file in files)
            {
                //判断文件类型
                if (Path.GetExtension(file) == fileType)
                {
                    Console.WriteLine(file);
                    control.Text = file;
                }
            }
        }
    }
}

在初始化主程序后实例化拖放类,一旦拖放就会触发DragEnter事件和DragDrop事件:

DragClass dg = new DragClass(this.txbReferDB, ".mdb");
DragClass dg2 = new DragClass(this.txbMoreDB, ".mdb");

8.因为我们只遍历了检查.mdb中的图层,万一调绘.mdb中没有对应图层怎么,所以,我们得检查,如果没有则跳过。

//创建要素图层
//……

//检查数据
object dt = "";
if (GPClass.GP.Exists(referDB + "\\" + strFC, ref dt))
{
    //3.选择所有
    //4.按位置选择(移除)
}
//复制要素
//……
9.为了更准确的统计操作时间,添加了计时功能。效果图如下:

 

image

10.为了让用户快速进行执行任务,可以在执行按钮上添加Enter事件。

private void btnExcute_Enter(object sender, EventArgs e)
{
    Excute();
}

private void Excute()
{
    referDBPath = txbReferDB.Text.Trim();
    moreDBPath = txbMoreDB.Text.Trim();
    resultDBPath = txbResultDB.Text.Trim();

    if (referDBPath.Trim() != "" && moreDBPath.Trim() != "" && resultDBPath.Trim() != "")
    {
        NoRepeatClass nr = new NoRepeatClass(referDBPath, moreDBPath, resultDBPath, progressBar);
    }
    else
    {
        MessageBoxEx.EnableGlass = false;
        MessageBoxEx.Show("警告:数据库路径选择有误!\n    请检查数据路径是否正确。", "提示");
    }
}

 

参考:http://bbs.esrichina-bj.cn/esri/viewthread.php?tid=50540

 

目录
相关文章
|
9天前
|
存储 Java 关系型数据库
在Java开发中,数据库连接是应用与数据交互的关键环节。本文通过案例分析,深入探讨Java连接池的原理与最佳实践
在Java开发中,数据库连接是应用与数据交互的关键环节。本文通过案例分析,深入探讨Java连接池的原理与最佳实践,包括连接创建、分配、复用和释放等操作,并通过电商应用实例展示了如何选择合适的连接池库(如HikariCP)和配置参数,实现高效、稳定的数据库连接管理。
24 2
|
9天前
|
监控 Java 数据库连接
在Java开发中,数据库连接管理是关键问题之一
在Java开发中,数据库连接管理是关键问题之一。本文介绍了连接池技术如何通过预创建和管理数据库连接,提高数据库操作的性能和稳定性,减少资源消耗,并简化连接管理。通过示例代码展示了HikariCP连接池的实际应用。
13 1
|
18天前
|
SQL JavaScript 关系型数据库
node博客小项目:接口开发、连接mysql数据库
【10月更文挑战第14天】node博客小项目:接口开发、连接mysql数据库
|
29天前
|
Rust 前端开发 关系型数据库
Tauri 开发实践 — Tauri 集成本地数据库
本文介绍了在 Tauri 框架中集成本地数据库的几种方案,包括直接绑定 SQLite、使用第三方数据库库和使用 tauri-plugin-sql-api 插件。最终选择了 tauri-plugin-sql-api,因为它集成简单、支持多种数据库类型,并且与 Tauri 框架深度整合,提升了开发效率和安全性。文章详细介绍了如何安装和使用该插件,以及如何编写核心代码实现数据库操作。
126 2
|
1月前
|
前端开发 Java 数据库连接
表白墙/留言墙 —— 中级SpringBoot项目,MyBatis技术栈MySQL数据库开发,练手项目前后端开发(带完整源码) 全方位全步骤手把手教学
本文是一份全面的表白墙/留言墙项目教程,使用SpringBoot + MyBatis技术栈和MySQL数据库开发,涵盖了项目前后端开发、数据库配置、代码实现和运行的详细步骤。
36 0
表白墙/留言墙 —— 中级SpringBoot项目,MyBatis技术栈MySQL数据库开发,练手项目前后端开发(带完整源码) 全方位全步骤手把手教学
|
16天前
|
NoSQL 前端开发 MongoDB
前端的全栈之路Meteor篇(三):运行在浏览器端的NoSQL数据库副本-MiniMongo介绍及其前后端数据实时同步示例
MiniMongo 是 Meteor 框架中的客户端数据库组件,模拟了 MongoDB 的核心功能,允许前端开发者使用类似 MongoDB 的 API 进行数据操作。通过 Meteor 的数据同步机制,MiniMongo 与服务器端的 MongoDB 实现实时数据同步,确保数据一致性,支持发布/订阅模型和响应式数据源,适用于实时聊天、项目管理和协作工具等应用场景。
|
2月前
|
关系型数据库 数据库 网络虚拟化
Docker环境下重启PostgreSQL数据库服务的全面指南与代码示例
由于时间和空间限制,我将在后续的回答中分别涉及到“Python中采用lasso、SCAD、LARS技术分析棒球运动员薪资的案例集锦”以及“Docker环境下重启PostgreSQL数据库服务的全面指南与代码示例”。如果你有任何一个问题的优先顺序或需要立即回答的,请告知。
68 0
|
3月前
|
Java Spring 开发者
Java Web开发新潮流:Vaadin与Spring Boot强强联手,打造高效便捷的应用体验!
【8月更文挑战第31天】《Vaadin与Spring Boot集成:最佳实践指南》介绍了如何结合Vaadin和Spring Boot的优势进行高效Java Web开发。文章首先概述了集成的基本步骤,包括引入依赖和配置自动功能,然后通过示例展示了如何创建和使用Vaadin组件。相较于传统框架,这种集成方式简化了配置、提升了开发效率并便于部署。尽管可能存在性能和学习曲线方面的挑战,但合理的框架组合能显著提升应用开发的质量和速度。
59 0
|
3月前
|
数据库 Java 数据库连接
玩转Play Framework的秘密武器:Ebean ORM带你解锁高效数据库操作新姿势,让你的代码从此飞起来!
【8月更文挑战第31天】Play Framework 以其简洁的 API 和高效开发体验著称,Ebean ORM 则是其推荐的对象关系映射(ORM)工具之一。Ebean 可将 Java 对象轻松映射到数据库表,简化数据库交互。本文将指导你在 Play Framework 中使用 Ebean ORM 进行数据库操作,涵盖项目创建、依赖引入、数据库配置、模型定义及 CRUD 操作,并通过示例代码展示实现过程。通过这些步骤,你将学会如何利用 Ebean 的丰富功能,如事务管理、查询构建等,提升 Web 应用的数据库交互能力。
55 0
|
3月前
|
数据库 测试技术 开发者
Play Framework的测试魔法:让代码在舞台上翩翩起舞,确保应用质量的幕后英雄!
【8月更文挑战第31天】Play Framework不仅以其高效开发与部署流程著称,还内置了强大的测试工具,提供全面的测试支持,确保应用高质量和稳定性。本文将详细介绍如何在Play Framework中进行单元测试和集成测试,涵盖`WithApplication`、`WithServer`及`WithDatabase`等类的使用方法,并通过示例代码手把手教你如何利用Play的测试框架。无论是单元测试、集成测试还是数据库操作测试,Play Framework均能轻松应对,助你提升应用质量和开发效率。
44 0