基于C#的ArcEngine二次开发36: 在地理数据库中创建要素类的接口及方法分析(下)

简介: 基于C#的ArcEngine二次开发36: 在地理数据库中创建要素类的接口及方法分析(下)

2.2.1 创建和存储的方法

CreateFeature方法被用来在地理数据库中创建单个要素,它的作用是分配一个系统ObjectID (OID),即OIDField字段的值

Store 方法将这个新特征存储到数据库中

创建要素的基本过程为:要么是在点线面要素类,要么是在参与几何网络或拓扑构建的要素类中,创建一个独立的要素

【The CreateFeature method is used to create individual features in the geodatabase. It has the effect of assigning a system-generated ObjectID (OID), which is the value of the OIDField. Use the IFeature.Store method to store this new feature in the database.This basic process to create a feature is used independently of whether the feature is created in a point, line, polygon feature class, or in a feature class participating in a geometric network or topology.】


Creating the feature:在一个要素类中调用CreateFeature 方法,其效果等同于在ITable 接口中调用CreateRow 方法,一旦方法被调用,其OID就是可用的;例外的情形是IFeatureClass 方法返回的是表示行对象的IFeature接口的引用【Calling the CreateFeature method on a feature class has the same effect as calling the CreateRow method on the ITable interface, except that the IFeatureClass method returns a reference to the IFeature interface representing the returned row object. The OID of the feature is available once the CreateFeature method is called.】

Create the geometry for the feature:一个行对象与要素的基本差异之一就是要素和几何图形的关系,创建集合图形有很多不同的方式【One of the fundamental differences between a feature and a row object is the association between a feature and a geometry. There are many different ways to create the geometry for the feature. For more information on creating geometries, see How to create a polyline and How to create a polygon.】

Store the geometry in the feature:使用IFeature.Shape 方法存储几何图形到要素中【Use the IFeature.Shape property to store the geometry with the feature.】

Set the subtype, initialize any default values, and set other field values:调用CreateFeature方法后,默认的子类型和字段值不会被自动初始化【After calling CreateFeature, the default subtype value is not automatically set nor are default values initialized. For features without a subtype that have defined default values, calling IRowSubtypes.InitDefaultValues initializes the default values. For features created within a feature class containing subtypes, use IRowSubtypes.SubtypeCode to set the subtype value for features before calling IRowSubtypes.InitDefaultValues to ensure the default values are set for the particular subtype. After initializing the default values, the remaining field values can be set through the IFeature.Value property. If the field values are not correct for the type of field, an error is raised. However, if the field is too small to accept the defined value, an error is raised after the call to the Store method.】

Store the feature:IFeature.Store 方法调用要素才会被存储到数据库中,一旦存储方法被调用,在统一编辑会话中的后续查询都将反映到要素中。【The feature is not written to the database until the IFeature.Store method has been called. Once Store has been called, all subsequent queries in the same edit session, using the geodatabase application programming interface (API), reflects the modified state of the feature.】

一旦IFeature.Store 方法调用,将会触发以下行为:


任何与特征相关的复杂行为都会发生。例如,网络要素创建相应的网络元素,拓扑在编辑的功能上创建dirty 区域,并且在覆盖IRowEvents接口的自定义功能上调用OnNew方法。【Any complex behavior inherent to the feature occurs. For example, network features create corresponding network elements, topologies create dirty areas over edited features, and the OnNew method is called on custom features that override the IRowEvents interface.】

如果要素属于实现IObjectClassEvents接口的拓展类,他的IObjectClassEvents.OnCreate也会被调用,这通常用于将对象的字段值设置为应用程序定义的变量【If the class the feature belongs to has a class extension that implements the IObjectClassEvents interface, its IObjectClassEvents.OnCreate method is called. This is often used to set an object's field values to application-defined variables.】

要素类的IObjectClassEvents接口公开事件。如果OnCreate事件有侦听器,则引发该事件,触发所有事件处理程序。【The IObjectClassEvents interface of a feature class exposes events. If the OnCreate event has listeners, the event is raised, triggering all event handlers.】

如果要素类参与具有通知的关系类,并且相关类具有实现IRelatedObjectClassEvents接口的类扩展,则会在扩展上触发RelatedObjectCreated方法。【If the feature's class participates in a relationship class with notification and the related class has a class extension that implements the IRelatedObjectClassEvents interface, the RelatedObjectCreated method is triggered on the extension.】

public static void CreateFeature(IFeatureClass featureClass, IPolyline polyline)
{
    // Build the feature.
    IFeature feature = featureClass.CreateFeature();
    feature.Shape = polyline;
    // Apply the appropriate subtype to the feature.
    ISubtypes subtypes = (ISubtypes)featureClass;
    IRowSubtypes rowSubtypes = (IRowSubtypes)feature;
    if (subtypes.HasSubtype)
    {
        // In this example, the value of 3 represents the polymer vinyl chloride (PVC) subtype.
        rowSubtypes.SubtypeCode = 3;
    }
    // Initialize any default values the feature has.
    rowSubtypes.InitDefaultValues();
    // Update the value on a string field that indicates who installed the feature.
    int contractorFieldIndex = featureClass.FindField("CONTRACTOR");
    feature.set_Value(contractorFieldIndex, "K Johnston");
    // Commit the new feature to the geodatabase.
    feature.Store();
}

2.2.2 使用插入光标创建

插入光标用于将行插入表中,并支持InsertRow方法。插入游标用于大容量行插入。与在表上多次调用CreateRow,然后在新行上调用Store方法相比,使用insert游标在将数据加载到简单表和要素类中时提供了更快的性能。


在通过参与拓扑、几何网络、自定义特性实现自定义行为的表上插入游标,一些类扩展将在内部使用CreateRow和Store方法来实现多态性(在这些情况下性能没有差异)。


InsertRow方法将行缓冲区作为参数。应用程序在插入行的表对象上使用CreateRowBuffer方法获取行缓冲区。每次调用光标上的InsertRow都会在数据库中创建一行,该行的初始值设置为输入行缓冲区中的值。一个单行缓冲区可用于多个InsertRow调用。所创建行的ObjectID由InsertRow方法返回。


请记住,如果要插入的几何图形位于与要插入的要素类不同的空间参照中,则必须投影这些几何图形,这可能会导致性能下降。为了避免这种情况,请确保要插入的几何图形与要插入的要素类使用相同的空间参照。


将真值传递给ITable.Insert方法的UseBuffering参数时,返回一个Insert游标,该游标缓冲客户端的行,并将它们成批发送到服务器以提高性能。始终启用缓冲,除非在编辑会话外部插入行(缓冲只能在编辑会话期间使用)。


应用程序负责在插入所有行之后调用insert游标上的Flush方法。如果未调用Flush方法,则游标在销毁时(当应用程序释放游标上的所有引用时)刷新其缓冲区。但是,依赖析构函数刷新插入游标并不能使应用程序有机会检测调用flush方法时可能出现的错误,例如,如果基础数据库中表的存储空间已满。下一个代码示例提供了一个基本模板来检查刷新是否成功。


如果使用空间缓存,则应在使用插入光标大容量加载要素之前禁用空间缓存。有关更多信息,请参阅ispatialchemanager。


下面的代码示例使用要素缓冲区将一组新要素插入到道路要素类中。特征的数量由geometryList参数的大小决定,特征从列表中按顺序获取其形状属性。所有功能的“TYPE”值都设置为“Primary Highway”。这些插入文件存储在缓冲区中,只有在调用Flush时才会刷新。


代码同2.1.3

2.2.3 使用仅加载模式插入行

IFeatureClassLoad接口是ArcSDE中的要素类以及文件Geodatabase中的要素类和表支持的可选接口。它可以用于启用“仅加载模式”,这可以提高数据加载的性能。仅在插入新行或要素时使用“仅加载”模式。编辑现有要素时不要使用“仅加载”模式。


使用ArcSDE,将要素类置于仅加载模式将禁用插入要素时更新空间索引。在文件geodatabase中,将要素类或表置于“仅加载”模式将禁用在插入行或要素时更新空间索引和属性索引。将要素类或表从仅加载模式中取出可重建索引。


当要素类或表处于仅加载模式时,其他应用程序无法处理数据。只有在通过ISchemaLock接口获取要素类上的独占架构锁之后,才能将要素类或表置于仅加载模式。


当启用或禁用仅加载模式时,应用程序负责确保类上没有未完成的游标。在启用仅加载模式之前实例化的任何游标都应在启用仅加载模式之前使用Marshal.releasecommobject或管理comleaser刷新(如果需要)并销毁,在禁用仅加载模式之前,应使用Marshal.ReleaseComObject或管理ComReleaser刷新和销毁以仅加载模式实例化的所有游标。否则可能导致意外错误。


下面的代码示例是前一个插入光标示例的修改版本,在插入发生之前启用了仅加载模式

//仅插入模式加载
public static void LoadOnlyModeInsert(IFeatureClass featureClass, List < IGeometry >
    geometryList)
{
    // 将FeatureClass转化为IFeatureClassLoad接口
    IFeatureClassLoad featureClassLoad = (IFeatureClassLoad)featureClass;
    //要素解锁,独占此数据库
    ISchemaLock schemaLock = (ISchemaLock)featureClass;
    try
    {
        schemaLock.ChangeSchemaLock(esriSchemaLock.esriExclusiveSchemaLock);
        // 设置要素类为仅加载模式
        featureClassLoad.LoadOnlyMode = true;
        using(ComReleaser comReleaser = new ComReleaser())
        {
            //创建要素缓冲
            IFeatureBuffer featureBuffer = featureClass.CreateFeatureBuffer();
            comReleaser.ManageLifetime(featureBuffer);
            // 创建插入光标
            IFeatureCursor insertCursor = featureClass.Insert(true);
            comReleaser.ManageLifetime(insertCursor);
            // 获取TYPE字段索引,并将其赋值为Primary Highway
            int typeFieldIndex = featureClass.FindField("TYPE");
            featureBuffer.set_Value(typeFieldIndex, "Primary Highway");
            //遍历几何要素列表
            foreach (IGeometry geometry in geometryList)
            {
                //设置几何图形,并将要素缓冲插入
                featureBuffer.Shape = geometry;
                insertCursor.InsertFeature(featureBuffer);
            }
            //缓冲区刷新
            insertCursor.Flush();
        }
    }
    catch (Exception)
    {
        // 异常处理失败的情形
    }
    finally
    {
        // 解除要素类的仅加载模式
        featureClassLoad.LoadOnlyMode = false;
        //解除独占锁,设置为共享锁
        schemaLock.ChangeSchemaLock(esriSchemaLock.esriSharedSchemaLock);
    }
}

2.2.4 使用缓冲和刷新


当对插入光标使用缓冲时,对insert row的调用不会向数据库管理系统(DBMS)写入新行,而是向客户端缓冲区写入新行。当调用ICursor.Flush或当缓冲区达到其最大大小时,缓冲区中包含的行作为批处理操作写入DBMS。由于DBMS写入可以发生在Flush调用或InsertRow调用上(如果缓冲区已达到其最大大小),这两个调用都应该具有适当的错误处理。


缓冲只能在编辑会话期间使用。


还有其他一些事件可以触发刷新,比如游标的销毁(如前所述)。在编辑会话中,停止编辑操作将刷新已版本化的数据,而停止编辑会话将刷新未版本化的数据。此外,在编辑操作中创建搜索或更新光标将刷新已缓存的所有行。


下图显示了缓冲在企业地理数据库中的工作方式


20200426181640456.png

X 重要参考

与本文相关的帮助文档中的示例:

Updating existing features

Updating attributes of existing features

Updating geometry of existing features

Adjusting feature locations with spatial adjustment

Editing with the geodatabase API

Creating features

Updating features

Obtaining changes made in the current edit session

Validating features

Listening to object class events

How to listen to workspace edit events


相关文章
|
4月前
|
关系型数据库 MySQL 分布式数据库
PolarDB 与传统数据库的性能对比分析
【8月更文第27天】随着云计算技术的发展,越来越多的企业开始将数据管理和存储迁移到云端。阿里云的 PolarDB 作为一款兼容 MySQL 和 PostgreSQL 的关系型数据库服务,提供了高性能、高可用和弹性伸缩的能力。本文将从不同角度对比 PolarDB 与本地部署的传统数据库(如 MySQL、PostgreSQL)在性能上的差异。
257 1
|
4月前
|
数据采集 存储 C#
C# 爬虫技术:京东视频内容抓取的实战案例分析
C# 爬虫技术:京东视频内容抓取的实战案例分析
|
1月前
|
存储 SQL Apache
Apache Doris 开源最顶级基于MPP架构的高性能实时分析数据库
Apache Doris 是一个基于 MPP 架构的高性能实时分析数据库,以其极高的速度和易用性著称。它支持高并发点查询和复杂分析场景,适用于报表分析、即席查询、数据仓库和数据湖查询加速等。最新发布的 2.0.2 版本在性能、稳定性和多租户支持方面有显著提升。社区活跃,已广泛应用于电商、广告、用户行为分析等领域。
Apache Doris 开源最顶级基于MPP架构的高性能实时分析数据库
|
5月前
|
SQL Linux 数据库
|
2月前
|
SQL 关系型数据库 MySQL
Vanna使用ollama分析本地数据库
这篇文章详细介绍了如何使用Vanna和Ollama框架来分析本地数据库,实现自然语言查询转换为SQL语句并与数据库交互的过程。
277 7
Vanna使用ollama分析本地数据库
|
1月前
|
存储 Java 关系型数据库
在Java开发中,数据库连接是应用与数据交互的关键环节。本文通过案例分析,深入探讨Java连接池的原理与最佳实践
在Java开发中,数据库连接是应用与数据交互的关键环节。本文通过案例分析,深入探讨Java连接池的原理与最佳实践,包括连接创建、分配、复用和释放等操作,并通过电商应用实例展示了如何选择合适的连接池库(如HikariCP)和配置参数,实现高效、稳定的数据库连接管理。
56 2
|
2月前
|
存储 分布式计算 数据库
阿里云国际版设置数据库云分析工作负载的 ClickHouse 版
阿里云国际版设置数据库云分析工作负载的 ClickHouse 版
|
2月前
|
SQL 自然语言处理 关系型数据库
Vanna使用ollama分析本地MySQL数据库
这篇文章详细介绍了如何使用Vanna结合Ollama框架来分析本地MySQL数据库,实现自然语言查询功能,包括环境搭建和配置流程。
253 0
|
2月前
|
C#
C# 接口(Interface)
接口定义了所有类继承接口时应遵循的语法合同。接口定义了语法合同 "是什么" 部分,派生类定义了语法合同 "怎么做" 部分。 接口定义了属性、方法和事件,这些都是接口的成员。接口只包含了成员的声明。成员的定义是派生类的责任。接口提供了派生类应遵循的标准结构。 接口使得实现接口的类或结构在形式上保持一致。 抽象类在某种程度上与接口类似,但是,它们大多只是用在当只有少数方法由基类声明由派生类实现时。 接口本身并不实现任何功能,它只是和声明实现该接口的对象订立一个必须实现哪些行为的契约。 抽象类不能直接实例化,但允许派生出具体的,具有实际功能的类。
49 9
|
3月前
|
Oracle NoSQL 关系型数据库
主流数据库对比:MySQL、PostgreSQL、Oracle和Redis的优缺点分析
主流数据库对比:MySQL、PostgreSQL、Oracle和Redis的优缺点分析
532 2