基于C#的ArcEngine二次开发43:GP工具--数据管理工具--Joins

本文涉及的产品
数据管理 DMS,安全协同 3个实例 3个月
推荐场景:
学生管理系统数据库
简介: 基于C#的ArcEngine二次开发43:GP工具--数据管理工具--Joins

使用GP工具实现数据表连接功能

1 数据连接

1.1 在ArcMap图层中的应用

需要FeatureLayer

示例代码:

///IFeatureLayer 基准图层
///ITable 要连接的表
///mFeatureField 基准表中的链接字段
///mTableField 外表链接的字段
///返回链接关系结果类
public  IFeatureClass FeatureJionTableFon(IFeatureLayer mFeatureLayer, ITable mTable, string mFeatureField, string mTableField)
{
       inputFeatureClass = mFeatureLayer.FeatureClass; //得到基准要素类
       FeatureTable = inputFeatureClass as ITable;//基准要素类转化为表
       IRelationshipClass relationshipClass = memoryRelClassFactory.Open("", FeatureTable as IObjectClass, mFeatureField, mTable as IObjectClass, mTableField, "forward", "backward", esriRelCardinality.esriRelCardinalityOneToOne);//建立关系类
       DisplayRelationshipClass = mFeatureLayer as IDisplayRelationshipClass;//显示关系类
       DisplayRelationshipClass.DisplayRelationshipClass(relationshipClass, ESRI.ArcGIS.Geodatabase.esriJoinType.esriLeftInnerJoin); //基于指定的连接类型和关系类建立连接
       displayTable = DisplayRelationshipClass as IDisplayTable;//显示表接口跳转
       outputFeatureClass = displayTable.DisplayTable as IFeatureClass;//输出要素类接口跳转
       return outputFeatureClass;
}

对于上述代码,如果我们没有IFeatureLayer时,我们不能通过as语句,将IFeatureClass跳转为IFeatureLayer,而是应该先定义后赋值;故上述代码可改进为:

///IFeatureLayer 基准图层
///ITable 要连接的表
///mFeatureField 基准表中的链接字段
///mTableField 外表链接的字段
///返回链接关系结果类
public  IFeatureClass FeatureJionTableFon(IFeatureClass baseFeatureClass, IFeatureClass srcFeatureClass, string baseFeatureField, string srcTableField)
{
    // 1 创建一个内存关系类
    Type memRelClassFactoryType = Type.GetTypeFromProgID(
    "esriGeodatabase.MemoryRelationshipClassFactory");
    IMemoryRelationshipClassFactory memRelClassFactory = 
    Activator.CreateInstance(memRelClassFactoryType) as IMemoryRelationshipClassFactory
    ;
    // 2 创建关系类
    IRelationshipClass relationshipClass = memRelClassFactory.Open("数据连接",
    baseFeatureClass, baseFeatureField, srcFeatureClass, srcTableField, 
    "", "", esriRelCardinality.esriRelCardinalityOneToOne);
    // 3 将关系类展示
    IFeatureLayer pFeatureLayer = new FeatureLayerClass();
    pFeatureLayer.FeatureClass = baseFeatureClass;
    IDisplayRelationshipClass  pDisplayRelationshipClass = pFeatureLayer as IDisplayRelationshipClass;//显示关系类
    pDisplayRelationshipClass.DisplayRelationshipClass(relationshipClass, ESRI.ArcGIS.Geodatabase.esriJoinType.esriLeftInnerJoin); //基于指定的连接类型和关系类建立连接
    // 4 展示表转换为要素类
    IDisplayTable displayTable = pDisplayRelationshipClass as IDisplayTable;//显示表接口跳转
    return  displayTable.DisplayTable as IFeatureClass;//输出要素类接口跳转
}

1.2 使用GP工具进行要素类连接--AddJoin

创建临时GDB文件,执行工具AddJoin建立要素连接,使用CopyFeatures工具拷贝链接结果

public AddJoin tableJoin(IFeatureClass editFeatureClass, IFeatureClass srcFeatureClass)
{
    //1 创建gp工具
    ESRI.ArcGIS.Geoprocessor.Geoprocessor pGeoprocessor =     ESRI.ArcGIS.Geoprocessor.Geoprocessor{};
    pGeoprocessor.OverwriteOutput = true;
    pGeoprocessor.AddOutputToMap = false;
    //2 创建GDB文件
    CreateFileGDB processor = new CreateFileGDB {};
    processor.out_folder_path = @"d:\临时目录";
    processor.out_name = "temp.gdb";
    pGeoprocessor.Execute(processor, null);
    //3 图层连接
    AddJoin pAddJoin = new AddJoin { };
    pAddJoin.in_layer_or_view = editFeatureClass;
    pAddJoin.in_field = "FEAID";
    pAddJoin.join_table = srcFeatureClass as ITable;
    pAddJoin.join_field = "FEAID";
    pAddJoin.join_type = "KEEP_ALL";
    pGeoprocessor.Execute(pAddJoin, null);
    //4 图层拷贝
    CopyFeatures pCopy = new CopyFeatures{};
    pCopy.in_features = editFeatureClass;
    pCopy.out_feature_class = "d:\临时目录\temp.gdb\连接图层";
    pGeoprocessor.Execute(pCopy , null);
}

1.3 删除连接

        /// <summary>
        /// 删除图层所有表连接(一次移除所有连接)
        /// </summary>
        /// <param name="pFeatureLayers"></param>
        public static void DeleteRelationships(IFeatureLayer pFeatureLayers)
        {
            ESRI.ArcGIS.DataManagementTools.RemoveJoin removeJoin = new ESRI.ArcGIS.DataManagementTools.RemoveJoin(pFeatureLayers);           
            ESRI.ArcGIS.Geoprocessor.Geoprocessor gp = new ESRI.ArcGIS.Geoprocessor.Geoprocessor();
            IGeoProcessorResult gpResult =  gp.Execute(removeJoin,null) as IGeoProcessorResult;           
        }

X 帮助文档翻译

连接数据会将字段从一个或多个表追加到另一表。 ArcGIS提供了几种连接数据的方法。适当的方法取决于数据源和数据的基数。本主题描述了可用的选项以及如何确定最适合应用程序的选项。

X.1 查询表

查询表是虚拟表,代表涉及来自同一地理数据库或对象链接和嵌入数据库(OLE DB)数据源的一个或多个表的查询。 建立查询表时,可以基于主键制造一个ObjectID列。这允许表中具有ObjectID列的一对多联接;因此,支持选择。 创建查询表时,将根据是否涉及形状列来确定只读表或要素类返回。然后可以将其作为图层添加到ArcMap或用作任何其他只读表或要素类。该查询可以保存在图层文件或地图文档中。如果对查询中涉及的表进行了更改,则它们将反映在查询表中,因为它是虚拟表。 要获取查询表,请创建一个QueryDef对象,该对象定义了联接。然后可以调用IQueryDef.Evaluate方法来获取联接结果的游标。 请注意,QueryDef(以及随后的查询表)将仅返回已保存到数据库的行。如果应用程序处于编辑会话中,则该编辑会话中所做的更改将不会反映在QueryDef的结果中。 以下代码示例显示如何联接街道要素类(使用OBJECTID字段作为主键)和保存街道替代名称的表(替代名)(使用JOINID字段作为外键)

// Create the query definition.
IQueryDef queryDef = featureWorkspace.CreateQueryDef();
// Provide a list of tables to join.
queryDef.Tables = "streets, altname";
// Set the subfields and the WhereClause (in this case, the join condition).
queryDef.SubFields = "streets.NAME, streets.TYPE, altname.ST_NAME, altname.ST_TYPE";
queryDef.WhereClause = "streets.OBJECTID = altname.JOINID";
// Get a cursor of the results and find the indexes of the fields to display.
using(ComReleaser comReleaser = new ComReleaser())
{
    ICursor cursor = queryDef.Evaluate();
    comReleaser.ManageLifetime(cursor);
    int streetsNameIndex = cursor.FindField("streets.NAME");
    int streetsTypeIndex = cursor.FindField("streets.TYPE");
    int altnameNameIndex = cursor.FindField("altname.ST_NAME");
    int altnameTypeIndex = cursor.FindField("altname.ST_TYPE");
    // Use the cursor to step through the results, displaying the names and altnames of each 
    // street.
    IRow row = null;
    while ((row = cursor.NextRow()) != null)
    {
        Console.WriteLine("Street name: {0} {1}. - Alt. name: {2} {3}.",
            row.get_Value(streetsNameIndex), row.get_Value(streetsTypeIndex),
            row.get_Value(altnameNameIndex), row.get_Value(altnameTypeIndex));
    }
}

定义了QueryDef后,可以使用TableQueryName类创建查询表。以下代码示例显示了一个函数,该函数采用QueryDef,包含表的地理数据库工作区以及新查询表的名称。它还使用一个用于以逗号分隔的关键字段列表的参数来制造ObjectID。如果这不是一个选项,请将makeCopy参数(或CopyLocally属性)设置为true,并为关键字段提供一个空字符串。

// Make the new TableQueryName.
IQueryName2 queryName2 = (IQueryName2)new TableQueryNameClass();
queryName2.QueryDef = queryDef;
queryName2.PrimaryKey = "streets.StreetID";
queryName2.CopyLocally = true;
// Set the workspace and name of the new QueryTable.
IDatasetName datasetName = (IDatasetName)queryName2;
datasetName.WorkspaceName = workspaceName;
datasetName.Name = "StreetsJoin";
// Open the virtual table.
IName name = (IName)queryName2;
ITable table = (ITable)name.Open();

在ArcGIS 10及更高版本中,从同一ArcSDE或OLE DB数据源连接两个或多个数据集的开发人员可能要考虑使用查询类或查询游标。有关更多信息,请参见查询类和游标

X.2 RelQueryTables

RelQueryTables用于连接来自不同数据源的表。例如,可以使用RelQueryTable将dBASE表连接到文件地理数据库要素类。

创建RelQueryTable需要两个表(或要素类)和一个关系类。关系类可以保留在地理数据库中,也可以创建为临时内存关系类。RelQueryTables不支持一对多联接。请参见下图:

20200526103255860.png

RelQueryTables与查询表一样,都是只读的并且是虚拟的,因为对基本表的更改反映在RelQueryTable中。

与工作空间工厂一样,MemoryRelationshipClassFactory和RelQueryTableFactory类都是单例组件对象模型(COM)类,不应在.NET中使用new关键字实例化;而是应使用Activator.CreateInstance方法实例化它们,并使用Type.GetTypeFromProgID创建Type实例。有关更多信息,请参见与单例对象交互。

以下代码示例显示如何将宗地要素类和所有者表结合在一起以创建RelQueryTable:

// Build a memory relationship class.
Type memRelClassFactoryType = Type.GetTypeFromProgID(
    "esriGeodatabase.MemoryRelationshipClassFactory");
IMemoryRelationshipClassFactory memRelClassFactory = 
    (IMemoryRelationshipClassFactory)Activator.CreateInstance(memRelClassFactoryType)
    ;
IRelationshipClass relationshipClass = memRelClassFactory.Open("ParcelsOwners",
    parcelsFeatureClass, "PARCEL_ID", (IObjectClass)ownersTable, "PARCEL_ID", 
    "Is Owned By", "Owns", esriRelCardinality.esriRelCardinalityOneToOne);
// Open the RelQueryTable as a feature class.
Type rqtFactoryType = Type.GetTypeFromProgID("esriGeodatabase.RelQueryTableFactory");
IRelQueryTableFactory rqtFactory = (IRelQueryTableFactory)Activator.CreateInstance
    (rqtFactoryType);
ITable relQueryTable = (ITable)rqtFactory.Open(relationshipClass, false, null, null,
    String.Empty, false, false);

删除满足where语句的要素的所有关系

This C# example deletes all the relationships for features satisfying the where clause parameter.
public void DelRelationships(IRelationshipClass relationshipClass, IFeatureClass featureClass, string whereClause)
{
    // Get the features whose relationships you want to delete
    IQueryFilter queryFilter = new QueryFilterClass();
    queryFilter.WhereClause = whereClause;
    IFeatureCursor featureCursor = featureClass.Search(queryFilter, false);
    IFeature feature = null;
    ISet featureSet = new ESRI.ArcGIS.esriSystem.SetClass();
    while ((feature = featureCursor.NextFeature()) != null) {
      featureSet.Add(feature);
    }
    // Delete the relationships
    featureSet.Reset();
    Console.WriteLine("Count {0}", featureSet.Count);
    relationshipClass.DeleteRelationshipsForObjectSet(featureSet);
}

外表关联:

ITable dispTable=((IDisplayTable)feaLayer).DisplayTable ;//图层
ITable attTable;//外表
IMemoryRelationshipClassFactory fac=new MemoryRelationshipClassFactoryClass ();
IRelationshipClass relClass=fac.Open("JZMJ",(IObjectClass)dispTable,"ZDDJH",
  IObjectClass)attTable,"G03",
  "Forward","Backward",
  esriRelCardinality.esriRelCardinalityOneToOne);
IDisplayRelationshipClass dispRelClass=feaLayer as IDisplayRelationshipClass ;
dispRelClass.DisplayRelationshipClass(relClass,esriJoinType.esriLeftInnerJoin);
相关实践学习
MySQL基础-学生管理系统数据库设计
本场景介绍如何使用DMS工具连接RDS,并使用DMS图形化工具创建数据库表。
相关文章
|
6月前
|
IDE C# 开发工具
一个开源轻量级的C#代码格式化工具(支持VS和VS Code)
一个开源轻量级的C#代码格式化工具(支持VS和VS Code)
195 6
|
1月前
|
XML 存储 安全
C#开发的程序如何良好的防止反编译被破解?ConfuserEx .NET混淆工具使用介绍
C#开发的程序如何良好的防止反编译被破解?ConfuserEx .NET混淆工具使用介绍
55 0
|
1月前
|
SQL JSON BI
最好的 C# .NET 报告工具
最好的 C# .NET 报告工具
40 0
|
3月前
|
SQL 数据管理 关系型数据库
《SQL转换秘籍:Vanna+Qwen双剑合璧,轻松实现私有模型转换》——揭秘如何利用Vanna和Qwen这两款神级工具,让你的SQL数据管理和转换如虎添翼!
【8月更文挑战第17天】Vanna与Qwen是两款优秀的开源数据库管理工具,助力用户高效管理及转换SQL数据。先安装Vanna和Qwen,随后在Vanna中创建并编辑私有模型,定义表结构等。完成模型构建后,导出为SQL文件。接着,在Qwen中导入此文件,并根据目标数据库类型(如MySQL)转换SQL语句。例如,生成创建`users`表的SQL代码。这两款工具显著提升了数据库管理工作流程的便捷性与效率。
155 1
|
5月前
|
算法 C#
C#开源实用的工具类库,集成超过1000多种扩展方法
C#开源实用的工具类库,集成超过1000多种扩展方法
|
6月前
|
安全 数据管理 测试技术
网络安全与信息安全:防范漏洞、加强加密与提升安全意识深入探索自动化测试框架的设计原则与实践应用化测试解决方案。文章不仅涵盖了框架选择的标准,还详细阐述了如何根据项目需求定制测试流程,以及如何利用持续集成工具实现测试的自动触发和结果反馈。最后,文中还将讨论测试数据管理、测试用例优化及团队协作等关键问题,为读者提供全面的自动化测试框架设计与实施指南。
【5月更文挑战第27天】 在数字化时代,网络安全与信息安全已成为维护国家安全、企业利益和个人隐私的重要环节。本文旨在分享关于网络安全漏洞的识别与防范、加密技术的应用以及提升安全意识的重要性。通过对这些方面的深入探讨,我们希望能为读者提供一些实用的建议和策略,以应对日益严峻的网络安全挑战。 【5月更文挑战第27天】 在软件开发周期中,自动化测试作为保障软件质量的关键步骤,其重要性日益凸显。本文旨在剖析自动化测试框架设计的核心原则,并结合具体案例探讨其在实际应用中的执行策略。通过对比分析不同测试框架的优缺点,我们提出一套高效、可扩展且易于维护的自动
|
13天前
|
C# 开发者
C# 一分钟浅谈:Code Contracts 与契约编程
【10月更文挑战第26天】本文介绍了 C# 中的 Code Contracts,这是一个强大的工具,用于通过契约编程增强代码的健壮性和可维护性。文章从基本概念入手,详细讲解了前置条件、后置条件和对象不变量的使用方法,并通过具体代码示例进行了说明。同时,文章还探讨了常见的问题和易错点,如忘记启用静态检查、过度依赖契约和性能影响,并提供了相应的解决建议。希望读者能通过本文更好地理解和应用 Code Contracts。
28 3
|
1月前
|
安全 C# 数据安全/隐私保护
实现C#编程文件夹加锁保护
【10月更文挑战第16天】本文介绍了两种用 C# 实现文件夹保护的方法:一是通过设置文件系统权限,阻止普通用户访问;二是使用加密技术,对文件夹中的文件进行加密,防止未授权访问。提供了示例代码和使用方法,适用于不同安全需求的场景。
101 0

热门文章

最新文章