ArcObject中的游标Cursor
此文是ArcUser 2006 7-9月一期中的一篇文章,介绍了
Arcobjects中的Cursor对象,给大家介绍了洋人是如何认识Cursor
的。文章内容浅显,易于理解。
作者:Eric Pimpler, President, GeoSpatial Training & Consulting, LLC
翻译:浩淼
当你听到cursor这个术语的时候,你的脑海中会出现什么?它是在屏幕上显示何处将开始下一个输入活动的符号吗(就是屏幕上的鼠标)?在AO中,cursor代表了一个对要素类或表通过使用属性或空间查询而获得的记录子集。这个子集保存在内存中而不是可视化显示出来。不要将它与选择集(selection set)弄混淆。选择集对象是在ArcMap中用于显示当前被选择的要素或行记录,而cursor缺不是为了显示的目的而使用的。
例如,一个查询cursor可以被用于编程产生一个租金表,这个表包含了所有在100中受过涝灾且其财产价值超过了10万美元的平原。AO提供了从地理数据集(要素类)和普通数据表中获取cursor的能力。这些cursor对象允许在一个单个对象中管理记录集。本文将介绍这些AO对象,方法和属性,它们都用于操作cursor对象。
Cursor VS FeatureCursor
AO使用何种cursor来管理记录子集取决于数据源的不同。cursor和featurecursor是非常相似的对象,除了cursor是用于操作表,而后者用于操作要素类。换而言之,cursor是一种为了特定目的——操作存储在传统数据库表中的记录子集——而建立的类结构,而featurecursor的记录子集则是存储在shapefile文件、个人geodatabase或企业级geodatabase中。
Cursors类型
在Cursor和FeatureCursor类群中有三种类型的cursor。最常用的是Search Cursor,它被用于查询操作以返回一个满足查询条件的记录子集。Search Cursor是一种只读的cursor,你可以用它遍历获取的信息。
你不能使用这种游标来插入、更新或删除表中的记录。Insert Cursor是专门用于往一个表中插入一条新记录,而Update Cursor则是用于更新或删除记录,这两个cursor返回的记录可以通过一个属性或空间查询来限定。
为了你进行的操作产生恰当类型的cursor是非常重要的。例如,不要产生一个search cursor,如果你试图更新一个表中的记录。正如前面提到的,search cursor是一种让你不能更新数据的只读结构。在本文中,我们将揭示每一种cursor的细节。
Cursor Class
正如前面提到的,cursor类是用于产生一个与数据库表进行交互交互的对象。在AO中,cursor类是一个非实例化对象,它意味着你必须使用另一个对象来获得一个cursor类的实例。既然如此,在AO中,表类被用于产生一个cursor类的实例,表类包含了三种方法能够产生一个cursor类的实例,而返回的cursor类型取决于程序员调用的方法。Fig1显示了AO中的Table Class的OMD。ITable接口拥有三种方法能够返回特定类型的cursor。ITable接口的Search、Insert和Update方法能够用于返回cursor实例。这些方法的名字与返回的cursor类型相对应。
在这些方法其中一个被调用以后,AO返回一个ICursor的实例。Fig2显示了一个Cursor类的OMD,Search、Insert和Update都可以返回一个ICursor的实例。ICursor有一个属性Fields和许多能够操作记录子集的方法,但这些方法是否可用取决于你使用的cursor类型。例如,如果你产生了一个search cursor,当你调用InsertRow和UpdateRow方法聚会返回一个错误。
FeatureCursor Class
FeatureCursor类与Cursor类非常相似,其区别在于前者是操作地理数据集而后者是操作传统数据库表。shapefile和geodatabase的地理数据集在AO中表现为一个AO 要素类的形式。与cursor类相似,FeatureCursor类也是一个通过FeatureClass对象的方法产生的非实例化对象。与ITable接口类似,IFeatureClass接口也包含了Search、Insert和Update方法用于返回一个IFeatureCursor实例。
在其中一个方法被调用后,一个IFeatureCursor的实例将会被返回,IFeatureCursor可以的属性和方法尽管与ICursor的在名字上稍微不同,但其功能却是差别很大,例如,InsertFeature VS InsertRow。
使用属性和空间约束条件
看看FeatureClass和Table的OMD图,查找Search、Insert和Update方法。注意每一个方法都可以用于返回一个cursor,cursor包含了一个参数,这个参数是IQueryFilter的实例。注意IQueryFilter参数,IQueryFilter是一个可以在内存中产生用于限制记录子集的对象。
例如,如果正在查询一个parcel数据库,你可能需要限制返回的parcels结果,让它们的值都大于10万美元。你可以使用IQueryFilter接口来约束。除此以外,如果你使用一个FeatureClass对象,还可以使用ISpatialFilter接口来产生SpatialFilter。这样你可以返回所有在洪水区的parcel(使用空间查询),且其价值高于10万美元(使用属性查询)。记住空间查询只能用于要素类上,如果在一个数据库表上使用空间查询则会返回错误,因为没有地理对象可以用过滤器过虑。让我们看看QueryFilter和SpatialFilter类的细节。
QueryFilter
在从一个数据集产生一个cursor或featurecursor之前,你能定义一个QueryFilter来设置约束限制返回记录的条数。QueryFilter是一个可产生的类(组件类),你可以在VBA中使用NEW关键字来产生一个此类的实例对象。你将能够使用IQueryFilter接口来处理QueryFilter类来定义一个属性约束。WhereClause属性则用于限制这个查询,下列代码就是一个例子:
Dim pQueryFilter as IQueryFilter
Set pQueryFilter=New QueryFilter
pQueryFilter.WhereClause="Prop_Val>=100000"
SpatialFilter
SpatialFilter可以用于产生一个基于空间约束的记录子集。它能够使用在FeatureClass上,但不能用于Table。SpatialFilter是一个组件类,也可以使用New关键字来产生一个类的实例。SpatialFilter使用Geometry属性和SpatialRel属性来设置查询约束条件。Geometry属性用于设置一个特定的地理要素,而SpatialRel则用于预设其空间关系,如相交、叠加或相邻。
由于SpatialFilter是一种QueryFilter,它也可以访问其所有的属性和方法。因此,你能够使用IQueryFilter的WhereClause属性来绑定空间和属性限制。下面是一个联合使用的例子:
Dim pSpatialFilter As ISpatialFilter
Set pSpatialFilter = New SpatialFilter
Set pSpatialFilter.Geometry = pFloodPolygon
pSpatialFilter.SpatialRel = esriSpatialRelContains
pSpatialFilter.WhereClause = “prop_val > 100000”
Set pFCursor = pCustomerLayer.Search(pSpatialFilter,True)
使用Cursor来访问记录
现在你已经对产生cursor的一般机制有了很好的了解,让我们来看看如何使用一个cursor来访问返回的记录。记住,cursor是仅仅存在内存中的来自一个表或要素类的记录集合。
当一个cursor第一次产生后,一个关联指针也产生了。你使用一次可以使用一个cursor来访问一行记录。这个指针可以帮助你追踪目前是哪一条行记录在被访问。使用初始化,指针实际上可以指向第一条记录。为了通过cursor获得第一条记录,你必须调用NextRow或NextFeature方法。这两个方法指向了cursor的下一条记录。但当它第一次调用的时候,实际指向第一条记录。之后每一次调用这些方法都是指向下一条记录。
通过某些方法你还可以到达游标中可以记录的末尾位置,如使用NewRow或NewFeature将返回Nothing对象,指示目前已经在cursor的末尾。在AO中的cursor是一个单向移动的对象,它不允许你返回之前的位置。一旦你访问过了一条记录,你就不能再返回去了。
结论
AO cursor结构提供了程序员查询、插入、更新和删除要素类和表中记录的能力。这些易于产生和适用性强的cursor结构诗存在内存中的记录集合,他们能够使用QueryFilter或SpatialFilter来设置约束条件。一旦成生后,这些cursor结构就能够提供一个易于访问、只能向前移的结构来访问单个记录的内容。