Library Reference  

Geodatabase Library Overview

Supported with: ArcGIS Engine, ArcGIS Desktop, ArcGIS Server

Library dependencies: System, SystemUI, Geometry, Display, Server, Output

Additional library information: Contents, Object Model Diagram

The GeoDatabase library provides the programming API for the geodatabase. The geodatabase is a repository of geographic data built on standard industry relational and object relational database technology. The objects within the library provide a unified programming model for all supported data sources within ArcGIS. The GeoDatabase library defines many of the interfaces that are implemented by data source providers higher in the architecture.

The geodatabase can be extended by developers to support specialized types of data objects (Features, Classes, and so on). In addition it can have custom vector data sources added using the plug-in data source objects. The native data types supported by the geodatabase cannot be extended.

The objects that implement this functionality are grouped into a number of library subsystems. These library subsystems are:

Core geodatabase

The diagram shown above is a simplified view of the most important geodatabase objects, which are summarized as follows:


A Workspace is a container of spatial and nonspatial datasets such as feature classes, raster datasets, and tables. It provides methods to instantiate existing datasets and to create new datasets.

Workspaces are classified into types specified by the esriWorkspaceType enumerator: esriFileSystemWorkspace, esriLocalDatabaseWorkspace, and esriRemoteDatabaseWorkspace.

Shapefiles and ArcInfo workspaces are examples of esriFileSystemWorkspace. A personal geodatabase stored in Microsoft Access is an example of an esriLocalDatabaseWorkspace. An enterprise geodatabase stored in an RDBMS, such as Oracle, DB2, SQL Server, or Informix, and accessed via ArcSDE is an example of an esriRemoteDatabaseWorkspace.

Other workspace types include:

A WorkspaceFactory is a dispenser of workspaces and allows a client to connect to a workspace specified by a set of connection properties. A workspace represents a database or a data source that contains one or more datasets. Examples of datasets include tables, feature classes, and relationship classes.

A WorkspaceFactory is a cocreatable, singleton object. A WorkspaceFactory maintains a pool of currently connected, active workspaces that are being referenced by the application. Connection properties are specified using a PropertySet object and can be saved to a connection file.

A WorkspaceFactory also supports methods that can be used to browse and manage file system workspaces and methods to manage connection files for remote database workspaces.

This example connects to an ArcSDE for Oracle geodatabase.

[Visual Basic 6.0]
Dim pWorkspace As IWorkspace
Dim pWorkspaceFactory As IWorkspaceFactory
Dim pPropSet As IPropertySet
Set pPropSet = New PropertySet
With pPropSet
  .SetProperty "SERVER", "cuillin"
  .SetProperty "INSTANCE", "esri_sde"
  .SetProperty "USER", "scott"
  .SetProperty "PASSWORD", "tiger"
  .SetProperty "VERSION", "SDE.DEFAULT"
End With
Set pWorkspaceFactory = New SdeWorkspaceFactory
Set pWorkspace = pWorkspaceFactory.Open(pPropSet, 0)

The IFeatureWorkspace interface is used to access and manage datasets that are a key component of a feature-based geodatabase: Tables and ObjectClasses, FeatureClasses, FeatureDatasets, and RelationshipClasses.

All of the Open methods (such as OpenTable) take a dataset name as input. When working with an enterprise geodatabase, the name may be fully qualified (for example, "database.owner.tablename" or "owner.tablename") using the qualification character appropriate to the underlying database (see ISQLSyntax). If the input name is not fully qualified, then it is qualified using the currently connected user for the workspace.

When working with geodatabases (personal or enterprise), the workspace keeps a running object table of instantiated datasets. Multiple calls to open an already instantiated dataset will return a reference to the already instantiated dataset.

The OpenTable method can be used to open any existing table or object class in the workspace given its fully qualified name. The table object returned will always support the ITable interface. The returned table object will support additional interfaces depending on the type of table—for example, ObjectClasses will additionally support the IObjectClass interface.

The OpenFeatureClass method can be used to open any existing feature class in the workspace given its fully qualified name. Note that every feature class in a geodatabase has a unique fully qualified name, and the OpenFeatureClass method can be used to directly open FeatureClasses that are part of a FeatureDataset.

This example opens a shapefile as a feature class.

[Visual Basic 6.0]
Public Sub OpenFeatureClass_Example()
  Dim pWorkspaceFactory As IWorkspaceFactory
  Set pWorkspaceFactory = New ShapefileWorkspaceFactory
  Dim pFeatureWorkspace As IFeatureWorkspace
  Set pFeatureWorkspace = _
   pWorkspaceFactory.OpenFromFile("D:\Data\Esridata\USA", 0)
  Dim pFeatureClass As IFeatureClass
  Set pFeatureClass = pFeatureWorkspace.OpenFeatureClass("States")
  MsgBox "There are " & pFeatureClass.FeatureCount(Nothing) & " states"
End Sub

Applications can use the ISQLSyntax interface to help them construct SQL queries and where clauses that are database-system independent.

GetSpecialCharacter can be used to return the DBMS-dependent character that represents an SQL special character, including the following:

Applications should use the ParseTableName and ParseColumnName methods to split the fully qualified name for a dataset or for a column in a table into its components (database, owner, table, column). Applications that wish to be RDBMS independent should not assume that “.” is the delimiter used to separate the components of a fully qualified dataset name. Note that both the IDataset::Name property for a dataset in a geodatabase and the IDatasetName::Name property for a dataset name object return the fully qualified name for the dataset (the name object for the dataset, obtained using the IDataset::FullName property itself).

Applications should use the QualifyTableName and QualifyColumnName methods to construct fully qualified dataset and column names.

Editing data

Applications can use transactions to manage direct updates, for example, updates made outside of an edit session on object and feature classes that are tagged as not requiring an edit session. When using transactions to manage direct updates, applications are responsible for discarding any cached row objects at transaction boundaries.

ITransactions is an optional interface that allows an application to explicitly control database transactions. The interface does not support nested transactions.

Applications should not use transactions when performing updates within an edit session (for information on edit sessions, see the documentation below). In the context of an edit session, transactions are managed by the workspace and automatically started and stopped as needed.

Applications should be aware that DDL operations made through the ArcObjects geodatabase data access objects (for example, deleting a feature dataset or creating a new feature class) use database transactions to ensure integrity of the data dictionary tables and commit the transaction at the end of the operation. Applications should not invoke DDL operations within an application transaction—application transactions should be restricted to DML operations (such as data updates).

Applications can make use of Geodatabase edit sessions to manage long transactions. The IWorkspaceEdit interface allows the application to start and stop edit sessions during which the objects in a geodatabase can be updated. An edit session corresponds to a long transaction. The only changes to data that an application sees within an edit session are changes that are made by the application. Changes made by other concurrently executing applications (if allowed) are not seen until the edit session is saved or discarded. You should not use this interface to control editing if you are already editing the workspace using the ESRI Object Editor.

An edit session is begun using the StartEditing method. The withUndoRedo parameter can be used to suppress undo/redo logging if the workspace supports such suppression. Shapefiles support this, but SDE doesn't.

If undo/redo facilities are required, all related changes to objects in the database within an edit session should be grouped into edit operations. An edit operation is begun using the StartEditOperation method. An edit operation may be thought of as a short transaction nested within the long transaction corresponding to the edit session.

Applications are responsible for calling the AbortEditOperation method to abort an edit operation if errors are detected within the methods executed for an edit operation.

Applications are responsible for calling StopEditOperation to mark the end of a successfully completed edit operation. Completed edit operations can be thought of as being pushed onto an undo stack.

The UndoEditOperation can be used to roll the state of the edit session back to what it was prior to the execution of the edit operation at the top of the undo stack. Undoing an edit operation pops the edit operation from the Undo stack and adds it to a Redo stack.

The RedoEditOperation rolls the state of the edit session forward to what it was after the execution of the edit operation at the top of the Redo stack, pops the redone edit operation from the Redo stack, and pushes it back onto the Undo stack. Performing a new edit operation clears the Redo stack.

The StopEditing method is used to end an edit session. The saveEdits parameter controls whether or not edits are saved or discarded. A multiversioned database can support multiple concurrent edit sessions on the same version of the database. In such a scenario, StopEditing will return an error code of FDO_E_VERSION_REDEFINED if it detects that the database state associated with the version being edited is no longer the same as it was at the beginning of the edit session (indicating that the version was modified by some other edit session). In this case, the application is responsible for calling the IVersionEdit::Reconcile method to reconcile the edit session against the current state of the version being edited. StopEditing may be called again after reconciliation.

The geodatabase guarantees “unique instancing” of row objects retrieved from the database within an edit session. Any data access call that retrieves a nonrecycling object with a particular object ID will return the in-memory instance of the object if the object has already been instantiated by the application. Such behavior is needed to ensure application correctness when updating complex object models—for example, models with relationship-based messaging or models with network features where updates to the geometry of a feature affect the geometry of topologically related features.

The example below shows a simple edit session on a workspace. Note that if the user chooses to undo the edit operation, there will be no outstanding edits, so the prompt to save the work will not appear. For this reason, all object editing should be done within an edit session. The geodatabase data access APIs (such as IRow::Store, ITable::Update, and ITable::Insert) will fail if you attempt to use them outside of an edit session on object and feature classes that are marked as requiring an edit session to ensure unique instancing semantics. Use IObjectClassInfo2::CanBypassEditSession to determine the situation.

[Visual Basic 6.0]

Public Sub WorkspaceEdit()
  Dim pWorkspaceFactory As IWorkspaceFactory
  Set pWorkspaceFactory = New esriDataSourcesGDB.AccessWorkspaceFactory

  Dim pFeatureWorkspace As IFeatureWorkspace
  Set pFeatureWorkspace = pWorkspaceFactory.OpenFromFile("D:\Usa.mdb", 0)

  Dim pFeatureClass As IFeatureClass
  Set pFeatureClass = pFeatureWorkspace.OpenFeatureClass("States")

  Dim pWorkspaceEdit As IWorkspaceEdit
  Set pWorkspaceEdit = pFeatureWorkspace

  Dim pFeature As IFeature
  Dim iResponse As Integer
  Dim bHasEdits As Boolean

  pWorkspaceEdit.StartEditing True

  Set pFeature = pFeatureClass.GetFeature(1)

  iResponse = MsgBox("Undo operation?", vbYesNo)
  If iResponse = vbYes Then
  End If

  pWorkspaceEdit.HasEdits bHasEdits
  If bHasEdits Then
    pWorkspaceEdit.StopEditing MsgBox("Save edits?", vbYesNo)
  End If
End Sub

The rules for correct object editing on a geodatabase are summarized below:

  1. All object editing should be done within an edit session.
  2. Group changes into edit operations.
  3. Discard all references to row objects retrieved at the edit session boundary (on StartEditing). If references to row objects will be maintained across edit operations, then discard all references and refetch objects in response to the undo, redo, and abort edit operation calls made by the application, as well as the reconcile call made within an edit session on versioned databases. In the context of ArcMap, these calls are made by the editor, which broadcasts corresponding editor events via the IEditorEvents and IEditorEvents2 interfaces. Personal and enterprise geodatabase workspaces support the IWorkspaceEditEvents and the IVersionEvents outbound interfaces and directly broadcast these events.
  4. Use nonrecycling search cursors to fetch objects that are to be updated (using any of the Search, GetRow, or GetRows methods supported by tables, feature classes, and selection sets). Recycling cursors should only be used for drawing and read-only access to object states.
  5. Always fetch all properties of the objects to be edited. Query filters should always use “*” for the subfields property (attempts to instantiate nonrecycling cursors with less than all fields will still result in all row object fields being hydrated).
  6. After changing a row object, call the IRow::Store method to mark the object as changed and trigger propagation of the OnChanged message; propagate messages to related objects by calling the IRow::Store method on the object. Delete objects by calling the IRow::Delete method on the object, which triggers the OnDelete message. Stored and deleted objects within an edit operation are automatically and periodically flushed to the underlying database as needed to ensure read/query consistency and update efficiency. Use the set versions of these methods (for example, IRowEdit::DeleteSet) if updates or deletions are being made to a set of objects in order to increase performance.
  7. Update and insert cursors are bulk data-loading and data-update APIs designed to perform direct updates and inserts outside of an edit session on simple data during the data-loading phase of a project. Following the editing rules on this page will help ensure geodatabase integrity, particularly where custom objects and geodatabase behavior is concerned. Avoid using these APIs in editing applications. Using these APIs within an edit session or on complex objects (objects with nonsimple row or feature behavior, or on objects participating in composite relationships or relationships with notification) negates any performance advantages they may have.

Workspace extensions

A workspace representing a geodatabase can have one or more workspace extensions. A workspace extension extends the functionality of a workspace in some way, for example, by managing a new type of custom dataset or by maintaining custom data dictionary information on datasets. A workspace extension is usually used in conjunction with an application or editor extension that acts as the client of the workspace extension.

The Workspace instantiates all WorkspaceExtensions that are registered in the component category CATID_GeodatabaseWorkspaceExtensions at connect time. An application extension can find a workspace extension by its well-known GUID and invoke methods supported by the extension as appropriate. It will also instantiate all workspace extensions registered with a workspace using IWorkspaceExtensionManager.RegisterExtension.

IWorkspaceExtension is a mandatory interface that must be supported by all workspace extensions. The GUID property returns the well-known GUID for the extension and is guaranteed to be unique. The Name property is the name of the extension. The PrivateDatasetNames and DataDictionaryNames properties return the names of tables and datasets that are private to the extension and will not be exposed to browsing clients by the workspace.


A Dataset is an abstract class that represents a named collection of data in a workspace. Datasets may contain other datasets. All datasets support the IDataset interface and may optionally support other interfaces, including IDatasetEdit, ISchemaLock, and IMetadata.

Examples of datasets include tables, feature classes, relationship classes, feature datasets, topologies, and geometric networks. Datasets appear as items in the ArcCatalog treeview under their workspace:

Feature datasets are collections of feature classes and may also contain relationship classes, geometric networks, or topologies. Feature classes that store simple features can be organized either inside or outside a feature dataset. Those outside a feature dataset are called standalone feature classes. Feature classes that store topological features, for example, those participating in geometric networks or topologies, must be contained within a feature dataset to ensure a common spatial reference. A FeatureDataset is a dataset that exists only in a geodatabase workspace; all the datasets contained in the FeatureDataset are also part of the same geodatabase.

When programming with feature classes, you need to remember that the feature class may or may not belong to a feature dataset.

This code to get the workspace for a feature class assumes a feature dataset exists and therefore may fail.

[Visual Basic 6.0]
' This excerpt won't work for standalone feature classes
Dim pFeatureDataset As IFeatureDataset
Set pFeatureDataset = pFeatureClass.FeatureDataset
Dim pWorkspace As IWorkspace
Set pWorkspace = pFeatureDataset.Workspace

This piece of code will work for both standalone feature classes and those in feature datasets.

[Visual Basic 6.0]
Dim pDataset As IDataset
Set pDataset = pFeatureClass
Dim pWorkspace As IWorkspace
Set pWorkspace = pDataset.Workspace

Each dataset in a geodatabase must have a unique name. In particular, each feature class in a geodatabase must have a unique name independent of the feature dataset that contains it. Note that this is different from a file system model, where two folders may contain files with the same local name within the folder.

Table, object class, and feature class

A Table object has one or more columns, referred to as fields, and contains an unordered collection of rows. For each field, each row has exactly one value in the data type of the field.

A Table is a Dataset; properties such as the name of the table, the persistable name object for the table, and the workspace containing the table may be obtained via the IDataset interface. In relational terms, a Table object represents an RDBMS table or view. In objected-oriented terms, a Table object represents an ObjectClass or a RelationshipClass in a geodatabase. A Table object hands out Row objects that support application- callable methods, depending on the type of data stored in the table. The Name property of a Table, accessible via the IDataset interface, returns its fully qualified name. The level of qualification may vary depending on the host DBMS. For example, a table named "pipes" owned by a user named "gas" may be called "pipes" on Access, "gas.pipes" on Oracle, and "mydb.gas.pipes" on SQL Server. The ParseTableName method on the ISQLSyntax interface supported by the table’s workspace can be used to split the fully qualified name into its components.

An object class is a table whose rows represent entities, modeled as objects with properties and behavior. The row objects handed out by an object class support the IRow and the IObject interfaces.

An object class may participate in any number of relationship classes that relate its instances to objects (entities) in other object classes. An object class may contain a discriminating field, referred to as the subtype field, that may be used to partition its instances into a number of subtypes. All subtypes share the same field definition and are stored in the same table; however, individual subtypes may differ in the default values and domains assigned to fields. The subtyping mechanism can also be used in defining attribute and connectivity rules that apply to the instances of the object class. The subtyping mechanism is a lightweight alternative to creating multiple subclasses, and each is represented by its own object class.

An object class has a nonnegative object class ID that is unique within the geodatabase. This ID is assigned to the object class at the time that it is created or at the time that an existing table in the RDBMS is registered with the geodatabase as an object class. The Name of the object class is the same as the name of the table in the DBMS in which the objects in the object class are stored; it follows the same fully qualified naming conventions.

An object class may have an AliasName property that is stored as part of its definition by the geodatabase. The AliasName may be retrieved and used for display purposes by applications.

An object class may have a ModelName property that is stored as part of its definition by the geodatabase. The model name is not exposed to end users and, if defined, can be used as a search key to find an object class by a standard model name that is adhered to across databases. A model name must be unique across the workspace.

Although all objects in a feature class or object class must have the same behavior and attributes, not all objects have to share the same default values and validation rules. You can group features and objects into subtypes. Subtypes differentiate objects based on their rules.

A FeatureClass is an ObjectClass whose objects are features, that is, a feature class is a collection of spatial entities, modeled as objects with properties and behavior. All of the features in a feature class share the same attribute schema (they have the same set of named fields). The row objects handed out by a feature class support the IRow, IObject, and IFeature interfaces.

A feature class has a distinguished field of type Geometry, referred to as the shape field. The shape field stores the geometry (referred to as the shape property) for the features in the FeatureClass.

This code example uses the Workspace object to return a FeatureClass object.

[Visual Basic 6.0]
Dim pFact As IWorkspaceFactory
Dim pWorkspace As IWorkspace
Dim pFeatws As IFeatureWorkspace
Dim pFeatcls As IFeatureClass
Set pFact = New esriDataSourcesGDB.AccessWorkspaceFactory
Set pWorkspace = pFact.OpenFromFile("C:\data\usa.mdb", 0)
Set pFeatws = pWorkspace
Set pFeatcls = pFeatws.OpenFeatureClass("states")

Rows, objects and features

A RowBuffer is a transient object that is capable of holding the state of a row but has no object identity. It is used primarily during data loading as the argument to the InsertRow method on an insert cursor. A Row- Buffer is obtained from a Table using the CreateRowBuffer method.

The IRowBuffer interface contains methods to access the state (the set of field values) for a row buffer. These methods take as an argument the numeric index of the field to be accessed.

A Row object is an instantiated software object that represents a persistent row in a Table. A row object is normally obtained from a cursor on a table (for example, ICursor::NextRow) or fetched directly given its object ID (for example, ITable::GetRow).

Once retrieved, clients may query the row object for additional interfaces and invoke methods on the row object. The CLSID property of a Table determines the type of row object returned by the Table. A new persistent row object is created using the ITable::CreateRow method. The act of creating the row assigns it identity. Note that applications should use the CreateRow method to create new persistent row objects, as opposed to directly cocreating the row objects. The latter will not create a row in the underlying persistent store.

A Row has a set of Fields. The set of Fields for a Row is the same as the set of Fields for its Table. In particular, the numeric index of a field in the Fields collection of its table is the same as the numeric index of the field in the Fields collection of the row, which is the same as the numeric index used to access the value of the field from the row. This means that application programs can and should cache field numeric indexes using the FindField method on the Table object, rather than invoking the FindField method once per row returned by a Cursor.

This example shows the creation of a row, then an update, followed by the deletion of the row.

[Visual Basic 6.0]
Dim pRow As IRow
Dim i As Long
i = pTable.FindField("Name")

' Insert Row
Set pRow = pTable.CreateRow
pRow.Value(i) = "Exploits"

' Update Row
pRow.Value(i) = "Badger"

' Delete Row

An ObjectClass is a Table whose Row objects represent entities. The Row objects handed out by an ObjectClass support the IRow and the IObject interface and are referred to as Object objects or simply as Objects. An alternative name for Object object in this context is Entity object.

The IObject interface is almost identical to IRow, from which it inherits. The only additional property is a direct link to the object class.

The instances of an ObjectClass may be partitioned into a number of subtypes. The IRowSubtypes interface on an Object contains methods that allow determination and modification of the Subtype to which an Object belongs and allow initialization or resetting of the field values of an Object to the default values defined for its subtype.

It is important to note that when Objects are programmatically created via the CreateRow method on the ITable interface (or for features with the CreateFeature method on the IFeatureClass interface), the default subtype is not automatically set, nor are the default values initialized. When using ArcMap, these tasks are automatically performed. However, if you are programmatically creating an Object (or Feature) that has default values, the following VBA code fragment indicates the proper sequence that should be followed.

[Visual Basic 6.0]
'Assume that we have an IFeatureClass pointer
Dim pFeature As IFeature
Set pFeature = pFeatureClass.CreateFeature

'Get the default subtype code for the feature class
Dim defaultSubtype As Long, pSubtypes As ISubtypes
Set pSubtypes = pFeatureClass
defaultSubtype = pSubtypes.DefaultSubtypeCode

'Set the subtype and initialize the default values for the feature
Dim pRowSubtypes As IRowSubtypes
Set pRowSubtypes = pFeature
pRowSubtypes.SubtypeCode = defaultSubtype

A Feature is a spatial Object. It is also a member of a feature class, being a row in the feature class table. A feature has an associated shape, the type of which is defined by the feature class. The possible shape objects are Point, Multipoint, Polyline, and Polygon—these are all objects in the Geometry object model.

Mostly you will deal with simple features, but there are various special kinds as defined by the esriFeatureType enumeration. These include annotation, dimension, and various network features.

The IFeature interface extends IObject and IRow, from which it inherits. The additional facilities are to do with the shape of the feature. You can use the Shape property to get or set the shape. This can be much more convenient than the alternative of using the Value property since you don’t have to work out the index of the shape field.

Query, cursors, and selection


A Cursor is a data-access object that can either be used to iterate over the set of rows in a table or query or insert new rows into a table. There are three forms of Cursor, referred to as search, insert, and update cursors. Each of these types of cursors is returned by the corresponding method (Search, Insert, or Update) on a Table or FeatureClass object. The Search and Update methods take a QueryFilter as input, which can be used to restrict the set of rows returned.

A Search cursor can be used to retrieve rows specified by a query filter; it supports a NextRow method. An Update cursor can be used to positionally update and delete rows specified by a query filter; it supports the NextRow, UpdateRow, and DeleteRow method. An Insert cursor is used to insert rows into a table and supports the InsertRow method. All of these methods are available in the single ICursor interface—it is your responsibility to make the calls appropriate to the type of cursor.

The NextRow method on a search or update cursor returns the next row in the result set to the application. The row object returned is allocated and hydrated by the cursor, and a reference to it is handed to the application. To retrieve all rows in a result set containing N rows, the application must make N calls to NextRow. In VB, a call to NextRow after the last row in the result set has been retrieved returns Nothing. In C++, a call to NextRow after the last row in the result set has been retrieved returns a value of S_FALSE and sets the output row reference to 0.

Cursors are forward only; they do not support backing up and retrieving rows that have already been retrieved or making multiple passes over data. If an application needs to make multiple passes over the data, the application needs to reexecute the query that returned the cursor. If both executions of the query are made within the same edit session (or database transaction with the appropriate level of isolation), the application is guaranteed not to see any changes made to the data by other concurrently executing applications.

This example shows a very simple cursor operation. It prints out the value of the first field for each row in a table.

[Visual Basic 6.0]
Dim pCursor As ICursor
Dim pRow As IRow
Set pCursor = pTable.Search(Nothing, False)
Set pRow = pCursor.NextRow
Do Until pRow Is Nothing
  Debug.Print pRow.Value(0)
  Set pRow = pCursor.NextRow

Note that no data is fetched from the database until the NextRow method is called.

A Cursor has a recycling property that controls how it allocates row objects. Recycling cursors allocate a single row object and rehydrate it on each fetch. They can be used to optimize read-only access, for example, when drawing. It is illegal to maintain a reference on a row object returned by a recycling cursor across multiple calls to NextRow on the cursor. Row objects returned by a recycling cursor should not be modified. Nonrecycling cursors return a separate row object on each fetch. The objects returned by a nonrecycling cursor may be modified (setting the IRow::Value property or any other custom accessor supported by the Row) and stored with polymorphic behavior. The geodatabase guarantees “unique instance semantics” on nonrecycling row objects fetched during an edit session. If the row object to be retrieved by a call to NextRow has already been instantiated in the calling application, then a reference to the existing row object will be returned.

All Row objects retrieved from a Table using a Cursor logically contain the same ordered set of fields, and this set is the same as the ordered set of fields for the Cursor and the Table. In particular, the numeric index of a field in the Fields collection of the table is the same as the numeric index of the field in the Fields collection of the cursor, which is the same as the numeric index of the field for the row. So, the FindField method needs to be used only once per table or cursor. If the query filter used in generating a cursor does not include certain fields, then the resulting row objects will still logically contain these fields; however, they will not have hydrated values for these fields. If an application accesses these field values for the row, a variant of type empty (VT_EMPTY) will be returned. Note that this value is different from the Null value (VT_NULL) that is returned when the value of a fetched field is null.

The UpdateRow method can be used to update the row at the current position of an update cursor (making a call to NextRow on a cursor returns a Row and positions the cursor on that Row). After fetching a Row object using NextRow, the application can modify the Row as needed and then call UpdateRow, passing in the modified Row. This is an alternative to calling Store on the retrieved row. Using a recycling update cursor can be faster than calling Store on the rows returned by a search cursor when performing direct updates outside an edit session on simple data. If the row objects for the table are not simple (they don't have custom behavior or participate in composite relationships or relationships with notification), then calling UpdateRow on the cursor will generate a call to Store on the row object to trigger the custom behavior, and there will be no performance gain.

The DeleteRow method can be used to delete the row at the current position of an Update cursor (that is, to delete the Row returned by the last call to NextRow on this cursor). After fetching the Row object using NextRow, the application should call DeleteRow on the cursor to delete the row. The application is responsible for discarding the husk deleted row object. Using a recycling update cursor to delete rows can be faster then calling Delete on the rows returned by a Search cursor when performing direct updates outside an edit session on simple data. If the row objects for the table are not simple (they don't have custom behavior) or participate in composite relationships or relationships with notification, then DeleteRow on the cursor will generate a call to Delete on the row object in order to trigger custom behavior, and there will be no performance gain.

Insert cursors are used to bulk insert rows. Using an insert cursor offers significantly faster performance for data loading into simple tables and feature classes (tables whose CLSID is esriGeoDatabase.Row, esriGeoDatabase.Object, or esriGeoDatabase.Feature) than the alternative: making multiple calls to CreateRow on the table followed by calling Store on the created row.

Insert cursors on tables that contain non-simple objects, such as internally use the CreateRow and Store methods to achieve polymorphism, and there is no difference in performance in these cases. The InsertRow method takes a RowBuffer as an argument.

Applications obtain a RowBuffer using the CreateRowBuffer method on the Table object into which rows are to be inserted. Each call to InsertRow on the cursor creates a new row in the database whose initial values are set to the values in the input row buffer. The object ID for the created row is returned by the InsertRow method.

The UseBuffering method argument to the Insert method on a table returns an insert cursor that buffers rows on the clients and sends them to the server in batches for increased performance. The application is responsible for calling Flush on the insert cursor after all rows have been inserted. If a call to Flush is not made, the cursor will flush its buffers on destruction (when the application releases all references on the cursor). However, relying on the destructor to flush the insert cursor does not give the application the chance to detect errors that may arise on the call to flush (for example, if the tablespace [disk] for the Table in the underlying database fills up).

The FeatureCursor object is a kind of Cursor object. It performs in the same way, except it is based on a feature class rather than a generic table.

The IFeatureCursor interface provides access to a set of features in a feature class. It operates in the same way as ICursor, although it does not inherit from that interface. This saves you from having to use Query-Interface when dealing with features rather than rows.

All the discussion for Cursor objects is appropriate to feature cursors—there is a direct correspondence between the methods on the various interfaces.

Query filters and spatial filters

A QueryFilter object specifies a filter for tabular data based on attribute values. It is used to restrict the set of rows or the set of columns retrieved from a single table or feature class. The primary use of a query filter is to specify the set of rows to be returned when opening a cursor on a Table. It is also used in a number of other cases where a subset of the data in a table needs to be specified.

Some scenarios of using a QueryFilter include opening a cursor on some of the rows in a table, selecting features in ArcMap, deleting some features meeting certain criteria, counting the number of features satisfying a condition, and defining which features will be rendered on the map.

The example below shows how to select features for the State of California. This code will work on any feature layer with a STATE_NAME attribute —QueryFilters are not specific to any particular dataset.

[Visual Basic 6.0]
Dim pQueryFilter As IQueryFilter
Set pQueryFilter = New QueryFilter
pQueryFilter.WhereClause = "STATE_NAME = 'California'"
Dim pFeatureSelection As IFeatureSelection
Set pFeatureSelection = pFeatureLayer
pFeatureSelection.SelectFeatures pQueryFilter, _
esriSelectionResultNew, False

There is no need to specify a WhereClause if you just want to filter the fields of data. You can also normally use the VB keyword "Nothing" in place of a QueryFilter for those methods that require one—for example, to count the features in a feature class.

MsgBox "num features:" & pFeatureClass.FeatureCount(Nothing)

You can use the SubFields property to improve performance when using query filters. The performance gain comes from just fetching the field values that you require rather than all the data for each row. The default value for SubFields is "*", which indicates that all field values will be returned. It isn't necessary to set the subfields when the query filter is used in a context in which no attribute values are fetched, for example, when selecting features.

A QueryFilter has properties named SubFields and WhereClause and represents a subset of the single table queries that may be made against a table in a SQL database using the SQL SELECT statement. QueryFilters map on to simple SQL select statements of the form SELECT <field names> FROM <table name> WHERE <where-clause that references only table name>.

The SQL syntax used to specify the WhereClause of QueryFilter objects is the same as that of the underlying database holding the data. An application can use the ISqlSyntax interface on a Workspace to determine information about the SQL syntax used, such as the delimiter character used in qualifying table and field names and the identifier quote character. This information is available for the different types of workspaces (ArcSDE:Oracle, ArcSDE:SqlServer, Access, shapefile, coverage, and others). Unlike QueryDef objects, QueryFilter objects are supported across all the workspace types, including shapefiles and coverages.

A SpatialFilter is a QueryFilter that includes both spatial and attribute constraints. A SpatialFilter can be used to restrict the set of features retrieved from a feature class using both spatial and attribute restrictions. A spatial filter has a single query geometry that specifies the geometry against which the features in the feature class will be tested. Because ArcObjects supports a number of different geometry types, including both single and multipart geometries and geometry collections, one way of expressing a complex spatial query is by building an appropriate query geometry to pass as input to the spatial filter.

A spatial filter has a single geometric shape that is used in the query. You can form more complicated spatial queries by using several spatial filters in succession.

You can use spatial filters everywhere that query filters are used, as long as the dataset to be queried has a spatial field. Some example tasks might be:

The ISpatialFilter interface is used to define a query with geographic criteria.

You must always set these three properties: Geometry, GeometryField, and SpatialRel. The GeometryEx method may be used to set the query geometry in the case of large query geometries where the application is willing to surrender ownership of the geometry to the filter. In this case, the filter may modify (project) the query geometry in place if the spatial reference of the query geometry is different from the native spatial reference of the feature class or the requested output spatial reference. The spatial reference in which the features should be returned by the query is specified using the OutputSpatialReference property in the IQueryFilter interface.

This simple example shows a simple selection of features that intersect a given shape. It assumes an existing feature layer and a valid geometry pointer (perhaps derived from end user input).

[Visual Basic 6.0]
Dim pSpatialFilter As ISpatialFilter
Set pSpatialFilter = New SpatialFilter
With pSpatialFilter
  Set .Geometry = pGeometry
  .GeometryField = pFeatureLayer.FeatureClass.ShapeFieldName
  .SpatialRel = esriSpatialRelIntersects
End With

Dim pFeatureSelection As IFeatureSelection
Set pFeatureSelection = pFeatureLayer
pFeatureSelection.SelectFeatures pSpatialFilter, _
esriSelectionResultNew, False

ISpatialFilter inherits the members of IQueryFilter—the example above could be extended by setting the WhereClause property on the spatial filter.

The SpatialRel property takes an enumeration that defines the relationship between the query geometry and the target feature geometry; this must be satisfied for the target feature to be returned by the query. The spatial relationships supported are the basic Clementini relationships, specified as part of the OpenGIS® Simple Feature data-access standard.

The five basic Clementini relationships are Disjoint, Touches, Overlaps, Crosses, and Within. esriSpatialRelIntersects, esriSpatialRelTouches, esriSpatialRelCrosses, esriSpatialRelOverlaps, esriSpatialRelWithin, and esriSpatialRelContains map to the corresponding Clementini relationships. Intersects maps to Not(Disjoint), Contains(a,b) maps to Within(b,a), and the rest correspond directly to the Clementini relationship.

esriSpatialRelEnvelopeIntersects is True if the envelope of the query geometry intersects the envelope of the target geometry.

esriSpatialRelIndexIntersects may be specified as the filter spatial relationship if the application is prepared to deal with features that do not intersect the query geometry, as long as all features that do intersect the query geometry are returned. This is a hint to the database that only the primary filter based on the spatial index needs to be applied; this results in faster query execution. This can be appropriate for drawing applications that rely on clipping to do the secondary filtering.

esriSpatialRelRelate may be specified as the filter spatial relationship if the application wishes to directly specify the relationships between the topological interior, boundary, and exterior of the query geometry and the topological interior, boundary, and exterior of the target geometry, using the dimensionally extended nine-intersection model. The spatial relationships between the components are specified using a string of nine characters that is set as the value for the esriSpatialRelDescription property of the filter.

The characters are drawn from the alphabet {T, F, *} and indicate the dimension of the point set resulting from the intersection of the two components that map to that character position. F indicates no intersection, T indicates intersection, and * indicates don’t care. The mapping of components to character position in the string is shown in the diagram to the left. The character string is constructed by reading out the entries in the 3 x 3 matrix in the order left to right and top to bottom.

The values in this diagram translate into the nine-character string reading from left to right and top to bottom (TT*TT***).

Some of the spatial relationships exposed to the end user in the ArcMap Select By Location dialog box do not correspond directly to the basic Clementini relationships described above. These spatial relationships can be implemented using the Clementini spatial filter relationships combined with preprocessing and postprocessing. Preprocessing is used to assemble the appropriate query geometry (for example, in the case of distance-based relationships, using buffer). Postprocessing can be used to further restrict retrieved geometries returned by the Clementini operator. The following table shows examples of such processing: relationships between the query and target geometries.

The SpatialRelDescription property is only used when SpatialRel is set to esriSpatialRelRelation. You can use it to define various complex spatial relationships.

The SearchOrder property determines whether the spatial part of the query is performed before the attribute part of the query. By default, the spatial relationship is tested first, but in the case of queries where the attribute criteria are much more specific than the spatial, it is better to change the SearchOrder. An example of this kind of query might be "find all worldwide cities with population greater than a million that are not in Spain".

If you want to want to query a feature class based on a collection of shapes, for example, "select the cities that are within the selected states", you have several different options. One option is to apply successive spatial filters for each query shape. Another option is to make a single multipart query shape from the collection of original query shapes, then use a single spatial filter.

The following example shows how to form a single geometry from the selected features in a layer.

[Visual Basic 6.0]
Dim pFeatureSelection As IFeatureSelection
Set pFeatureSelection = pFeatureLayer

Dim pSelectionSet As ISelectionSet
Set pSelectionSet = pFeatureSelection.SelectionSet

Dim pEnumGeom As IEnumGeometry
Dim pEnumGeometryBind As IEnumGeometryBind

Set pEnumGeom = New EnumFeatureGeometry
Set pEnumGeometryBind = pEnumGeom
pEnumGeometryBind.BindGeometrySource Nothing, pSelectionSet

Dim pGeomFactory As IGeometryFactory
Set pGeomFactory = New GeometryEnvironment

Dim pGeom As IGeometry
Set pGeom = pGeomFactory.CreateGeometryFromEnumerator(pEnumGeom)


A SelectionSet object allows an application to reference a selected set of rows all belonging to a single table or feature class.

Selection sets are normally used throughout ArcObjects when a temporary subset of rows or features is required for some operation. It is important to note that the selection set only applies to a single table; you cannot sensibly combine two selection sets from different tables.

A selection set can be based on either a set of ObjectIDs that correspond to the selected rows, or on an actual set of row objects, instantiated and referenced by the selection set. In either case, the selection set provides methods to iterate over the set of row objects in the selection. The SelectionType property of a selection set, specified by an application at the time that it creates the selection set, determines the type of representation (object IDs or Row object references) used by the SelectionSet.

A selection set is typically created from a table or feature class using the Select method on the table. A query filter is used to specify the subset of rows to include in the selection set:

[Visual Basic 6.0]
Dim pSelectionSet As ISelectionSet
Set pSelectionSet = pFeatureClass.Select(pQueryFilter, _
esriSelectionTypeHybrid, esriSelectionOptionNormal, Nothing)

An application can create multiple SelectionSets on a Table or FeatureClass coclass. The SelectionSets reference their target table, but the latter have no knowledge of the selection sets that reference them. Applications are responsible for associating the created selection sets with the target table as appropriate. For example, a FeatureLayer in ArcMap holds a reference to a geodatabase FeatureClass and also to a SelectionSet that it creates on the feature class—at draw time the selected features are retrieved and drawn in a distinguished manner.

The ISelectionSet interface is used to manage and query the selection set.

The Search method is used to iterate over the rows in the selection set and returns a cursor. Note that the Search method takes a query filter that can be used to further restrict the set of rows in the selection that are returned for ID set selections. Using a query filter with hybrid selections will force the representation of the selection to become an ID set selection.

The Select method is used to create a new selection based on a subset of the current selection using a query filter to specify the restriction. The Add, AddList, and RemoveList methods can be used to alter the selection set by adding and removing rows specified by object IDs. The Combine method can be used to combine two SelectionSets using the standard set operations of union, intersection, difference, and symmetric difference. Only use Combine on two selection sets from the same target—it doesn't make sense to mix lists of IDs from different datasets.

The ISelectionSet2 interface provides a method Update that creates an update cursor on the selection set; this can be used to update and delete rows from the table or feature class of the selection set.

This example returns the average population of the selected features in a counties feature layer; it illustrates a transition from using ArcMap objects to using the geodatabase data-access objects.

[Visual Basic 6.0]
Dim pFeatureSelection As IFeatureSelection
Set pFeatureSelection = pFeatureLayer

Dim pSelectionSet As ISelectionSet
Set pSelectionSet = pFeatureSelection.SelectionSet

Dim pFeatureCursor As IFeatureCursor
pSelectionSet.Search Nothing, True, pFeatureCursor

Dim pDataStats As IDataStatistics
Set pDataStats = New DataStatistics
Set pDataStats.Cursor = pFeatureCursor
pDataStats.Field = "POP1990"
MsgBox pDataStats.Statistics.Mean

As described in this section, the main interface for geodatabase selection sets is ISelectionSet. There are, however, some other similarly named interfaces in ArcObjects—the following table summarizes these other interfaces.


A QueryDef object represents a database query on one or more tables or feature classes.

A QueryDef may be evaluated, resulting in the execution of the query on the database server. The results of the query are returned to the application as a cursor. The application can iterate over the cursor to fetch the row objects in the result set of the query. The row objects returned by a cursor on a QueryDef are always of type esriGeoDatabase.Row— they never have custom behavior or support additional interfaces, even if the table names specified in the QueryDef correspond to tables representing ObjectClasses with behavior. The row objects returned by evaluating a QueryDef are read-only—these row objects do not reference a parent table, and the Store method may not be called on them. Attempting to Store a row object returned by evaluating a QueryDef will result in an error.

The primary use of QueryDefs is to directly evaluate database queries on arbitrary tables. They can be used to join tables with the assurance that the join query will execute in the underlying RDBMS. All of the tables in a QueryDef must belong to the same workspace (RDBMS). A QueryDef may include geometry fields in the specification of the list of fields to be returned but may not include geometry fields in the where clause specification unless the underlying DBMS is a spatially extended DBMS that supports geometric types, and unless the geometry fields for feature classes are using those native DBMS geometry types for storage.

The IQueryDef interface is used to set up and define the query and also provides an Evaluate method that is used to execute the query, returning a cursor.

This example shows how to create a QueryDef that defines a join between USA counties and states. A valid pointer to the workspace containing the data is assumed.

[Visual Basic 6.0]
Dim pQueryDef As IQueryDef
Set pQueryDef = pFeatureWorkspace.CreateQueryDef
pQueryDef.Tables = "Counties, States"
pQueryDef.SubFields = "COUNTIES.Shape, COUNTIES.NAME, _

Note that QueryDef objects cannot be cocreated. They can only be created from the IFeatureWorkspace interface. This guarantees that all tables in the query are within the same workspace.

The SubFields property is optional when creating QueryDef objects. The default value is “*”, which means that all fields are returned.

The OpenFeatureQuery method on a workspace (available in the IFeatureWorkspace interface) can be used to create a FeatureClass that is based on a QueryDef. Such a feature class may be added to a Map (as a FeatureLayer) and may be used to visually represent the results of a database join query. Such a FeatureClass is similar in concept to an ArcSDE view.

The following example adds a new layer to a map based on the QueryDef created in the previous example. The IQueryDef::SubFields property must define one and only one spatial field in order to create the feature class.

[Visual Basic 6.0]
Dim pFeatureClass As IFeatureClass
Dim pFeatureClassContainer As IFeatureClassContainer
Set pFeatureClassContainer = pFeatureWorkspace.OpenFeatureQuery _
("My counties join", pQueryDef)
If (pFeatureClassContainer.ClassCount <> 1) Then
  MsgBox "Failed to create feature class by query"
  Set pFeatureClass = pFeatureClassContainer.Class(0)
End If
' Add feature class as layer to the map
Dim pMap As IMap, pDoc As IMxDocument
Set pDoc = ThisDocument
Set pMap = pDoc.FocusMap
Dim pFeatureLayer As IFeatureLayer
Set pFeatureLayer = New FeatureLayer
Set pFeatureLayer.FeatureClass = pFeatureClass
pFeatureLayer.Name = pFeatureClass.AliasName
pMap.AddLayer pFeatureLayer

The SQL syntax used with QueryDef objects is the same as that of the underlying database holding the data. An application can use the ISQLSyntax interface on a Workspace to determine information about the SQL syntax for the database, such as the delimiter character used in qualifying table and field names and the identifier quote character.

QueryDefs represent a subset of the queries that may be made against an SQL database using the SQL SELECT statement. QueryDefs map onto simple SQL select statements of the form: SELECT <field names> FROM <list of table names> WHERE <where-clause referencing only tables in from list of tables>.

QueryDefs do not guarantee to support SQL statements that do not map onto the above simple form. In particular, QueryDefs do not guarantee to support ORDER BY and GROUP BY clauses embedded within the WhereClause property, nested SELECT statements or correlated subqueries in the WhereClause property, AS keywords embedded in the SubFields property, the use of table aliases in the Tables property, the use of Aggregate functions (for example, MIN, MAX, and SUM), or the use of DISTINCT clauses. Support for such capabilities is not guaranteed across all configurations, and applications that rely on such capabilities risk failure.


A RelationshipClass is an association between two object classes; one is the origin class and the other the destination class. The relationship class represents a set of relationships between the objects belonging to two classes.

You can create a relationship class with either IRelationshipClassContainer or IFeatureWorkspace. RelationshipClass objects implement IDataset (useful for getting the name or the workspace), but they do not implement IClass (unless they are attributed). This is because a nonattributed relationship class does not have any fields of its own.

The IRelationshipClass interface provides information about a relationship class, functionality to create and delete individual relationships, and methods to find related objects. The members of this interface can be split into three logical groups: the properties that correspond to how the relationship class was created, the object-to-object methods that deal with individual relationships, and the relationship rules methods.

The OriginPrimaryKey, OriginForeignKey, DestinationPrimaryKey, and DestinationForeignKey properties can be somewhat confusing—their uses are different depending on whether the relationship class is attributed.

The object-to-object methods, such as GetObjectsRelatedToObjectSet, make use of the ISet interface, which manipulates a set of generic objects. When adding objects to a set with a cursor, make sure that the cursor recycling is turned off, as shown in this example (which deletes all the relationships for features with areas less than a certain value).

[Visual Basic 6.0]
Dim pQueryFilter As IQueryFilter
Set pQueryFilter = New QueryFilter
pQueryFilter.WhereClause = "Shape_Area < 25"

Dim pFCursor As IFeatureCursor
Set pFCursor = pFeatureClass.Search(pQueryFilter, False)
Dim pFeature As IFeature
Set pFeature = pFCursor.NextFeature
Dim pFeatSet As ISet
Set pFeatSet = New esriSystem.Set

Do While Not pFeature Is Nothing
  pFeatSet.Add pFeature
  Set pFeature = pFCursor.NextFeature
MsgBox pFeatSet.count
pRelClass.DeleteRelationshipsForObjectSet pFeatSet

The identify dialog in ArcMap allows you to dicsover objects related to other objects through a relatiohsip class:

When using CreateRelationship, remember that this operation will write a value into the foreign key field. Therefore, it is possible that you could overwrite, and therefore delete, an existing relationship. Similarly, DeleteRelationship will remove the foreign key value, so that field must allow null values unless you want to ensure that all objects in the class belong to relationships.

The ArcMap editor's property inspector allows you to both discover, add and remove relationships for an object:

The IRelationshipClass2 interface was added to provide a method to get matching objects.

An AttributedRelationshipClass is a special kind of relationship class and is also a kind of table known as the relationship table. For nonattributed relationship classes, the relationships are stored with the objects themselves in the foreign key values. For attributed relationship classes, the relationships are defined by the objects in conjunction with the rows in the relationship table.

A good way of testing whether you have an AttributedRelationshipClass object is as follows:

[Visual Basic 6.0]
If TypeOf pRelClass Is ITable Then
  Debug.Print "Attributed Relationship Class"
End If

The IRelationshipClass::IsAttributed property only returns True if there are extra relationship attributes beyond those required to relate the objects. The IRelationshipClass::GetRelationship method is useful for accessing the relationship attributes.

A relationship represents a pair of related objects or features. Relationship is an abstract class that covers SimpleRelationship and AttributedRelationship objects.

The IRelationship interface provides read-only information about a relationship. It is most useful with attributed relationships since it can form a bridge between the attribute information, which is in row form, and the related objects. When dealing with relationships, you will normally use the IRelationshipClass interface rather than IRelationship.

The SimpleRelationship object represents a pair of related geodatabase objects or features. There are no attribute values associated with the relationship. You should not cocreate a simple relationship. Instead, use IRelationshipClass::CreateRelationship.

The AttributedRelationship object is a kind of row that represents a pair of related objects or features with extra information about the pairing. The extra information is stored in the row.

You should not cocreate an attributed relationship. Instead, use IRelationshipClass::CreateRelationship. The IRelationshipClassEvents Interface provides information as to when two objects are related or unrelated and when attributes on an attributed relationship are modified. You can use this interface to listen to the events on the relationship class you care about.

[Visual Basic 6.0]
Private WithEvents RelClassEvents as RelationshipClassEvents
Private Sub StartListeningToEvents (By Val pF Work as IFEatureWorkspace)
  set RelClassEvents = pf Work.OpenRelationshipClass(“myRelClass”)
End Sub

Private Sub RelClassEvents_OnCreate(By Val rel as IRelationship)
  MsgBox “Relationship was created”
End Sub

Class Extensions

A ClassExtension is an object that gives developers the ability to customize and extend advanced Geodatabase functionality. ClassExtensions allow developers to implement optional interfaces to customize geodatabase behavior. A ClassExtension can also be used to add additional behavior to an ObjectClass or FeatureClass by supporting custom interfaces.

The IClassExtension interface is the main interface required for implementing a ClassExtension.

The Init method provides a pointer to the ClassHelper object that should be used to access the Extension object’s ObjectClass. A ClassExtension should not maintain a reference to the ObjectClass directly, but rather should access it via the ClassHelper as necessary. In addition to the ClassHelper, a PropertySet contains any data stored with the ObjectClass.

The value of PropertySet can be modified by using IClassSchemaEdit::AlterClassExtensionCLSID or IClassSchemaEdit2::AlterClassExtensionProperties. If the properties do not exist for the Extension, the pExtensionProperties argument will be Nothing.

The Init method is called when the ObjectClass is opened for the first time. Before the ObjectClass is closed, the Shutdown method is called. This code demonstrates how to implement a simple ClassExtension that utilizes ClassExtension properties to store a symbol that may be used for custom feature.

[Visual Basic 6.0]
Implements IClassExtension

Private m_pClassHelper As esriGeoDatabase.IClassHelper
Private m_pSymbol As ISymbol

Private Sub IClassExtension_Init(ByVal pClassHelper As _
  esriGeoDatabase.IClassHelper, ByVal pExtensionProperties As _
    Set m_pClassHelper = pClassHelper

    If Not pExtensionProperties Is Nothing Then
      Set m_pSymbol = pExtensionProperties.GetProperty("Symbol")
    End If
End Sub

Private Sub IClassExtension_Shutdown()
  Set m_pClassHelper = Nothing
End Sub

A ClassHelper is passed as an argument to the Init method on IClassExtension interface. The class helper is an intermediate object used to prevent circular references between an ObjectClass and a ClassExtension.

Developers can optionally implement the following class extension interfaces:

Domains and validation rules

Rules are associated with object classes and are used during the process of validating objects within an object class. There are four categories of rules that are subclassed from the Rule abstract class. They are attribute rules (AttributeRule), relationship rules (RelationshipRule), topology rules (TopologyRule), and connectivity rules (ConnectivityRule), further broken down into JunctionConnectivityRule and EdgeConnectivityRule.

For a detailed discussion on topology rules, see the Topology section in this document.

Associating a rule with a class does not guarantee that all objects within the class will always be valid; the validation process still needs to be run through the Editor toolbar or with IValidation::Validate. Through the IValidation interface (found on the Object class), the set of currently defined rules can be accessed, new rules can be added, and objects can be validated.

IRule is a generic interface that supports validation rules on an object class. Use this interface when you want to determine the type of rule and the helpstring associated with it.

Helpstring displays the message associated with the rule. This message is displayed during the process of validating a single feature when that feature is found to be invalid. The helpstring of the first (of possibly many) validation rule that is found to be invalid is displayed through the ArcMap user interface.

Type specifies the type of rule (attribute, relationship, or connectivity) and can be used to determine what validation rule object you are holding. Alternatively, you can attempt to probe for the appropriate interfaces (for example, if the Rule supports IAttributeRule, then it is an AttributeRule).

The following VBA code extracts the rules defined for a layer called "pipes" and prints the type of the rule and helpstring associated with the rule.

[Visual Basic 6.0]
Private Sub GetRules()
  Dim pDoc As IMxDocument, pMap As IMap, pFLayer As IFeatureLayer
  Dim lLoop As Long
  Set pDoc = ThisDocument
  Set pMap = pDoc.FocusMap

  'Find the feature layer containing "pipes"
  For lLoop = 0 To pMap.LayerCount - 1
  For lLoop = 0 To pMap.LayerCount - 1
   If pMap.Layer(lLoop).Name = "pipes" Then
    Set pFLayer = pMap.Layer(lLoop)
     Exit For
   End If
  Next lLoop

  If pFLayer Is Nothing Then Exit Sub

  Dim pObjClass As IValidation, pEnumRule As IEnumRule, pRule As IRule
  Set pObjClass = pFLayer.FeatureClass
  Set pEnumRule = pObjClass.Rules
  Set pRule = pEnumRule.Next

  Do While Not pRule Is Nothing
   If TypeOf pRule Is IAttributeRule Then
    Debug.Print "Attribute rule - " & pRule.Type & " - " & _
   ElseIf TypeOf pRule Is IRelationshipRule Then
    Debug.Print "Relationship rule - " & pRule.Type & " - " & _
   ElseIf TypeOf pRule Is IJunctionConnectivityRule Then
    Debug.Print "JunctionConnectivity rule - " & pRule.Type & " - " & _
   ElseIf TypeOf pRule Is IEdgeConnectivityRule Then
    Debug.Print "EdgeConnectivity rule - " & pRule.Type & " - " & _
   End If

   Set pRule = pEnumRule.Next
End Sub

Creating a class extension can extend the types of rules that can be defined for an object class. By implementing IObjectClassValidation (along with IClassExtension), any type of custom validation rule can be coded.

Attribute rules and domains

An attribute rule applies an attribute domain to a field of an object class.

The AttributeRule class is used to define attribute-specific rules on an object class. This type of rule applies a specified domain to a field name with a specific subtype. Domains can be used to limit the attribute values to a set of valid values or to a range of values. Domains can also define how values in the field are distributed during a split. The process of associating a domain with a field in an object class creates an AttributeRule as a side effect—thus, it is generally not the case that users must explicitly create AttributeRules.

A domain is used to specify the permissible values that a field in an object class may take.

A Domain is an abstract class that defines an interface used by RangeDomain and CodedValueDomain coclasses to constrain the per missible values that may be associated with a particular field on an object or feature class. Domains are assigned on a subtype basis.

The IDomain interface provides access to the common properties shared across both types of Domains. Each of the properties are read-write except for the Type property. When creating and assigning a Domain to a particular field, the client is required to set the Name and FieldType properties.

A range domain is used to specify the legal minimum and maximum values that a field may have.

A coded value domain is used to specify a set of permissible values that a field may take.

Domains are used by the ArcMap property inspector to constrain the values that the user can enter for a field, as well as during the validation process within the geodatabase.

A Domain may be shared by any number of fields. Domains are associated with a Field object. Domains are added to a dataset at the workspace level through IWorkspaceDomains::AddDomain.

RangeDomains may be associated with fields that are either numeric fields (such as esriFieldTypeSmallInteger or esriFieldTypeDouble) or date fields. RangeDomains may not be associated with string or character fields (esriFieldTypeString).

CodedValueDomains store a set of (value, name) pairs that represent the discrete values that a field may take. The value is what is actually persisted inside a field; the name is what is displayed by the ArcMap property inspector. The name can be considered to be a human-readable string that describes what the value represents. In contrast to RangeDomains, CodedValueDomains may also be associated with string fields (esriFieldTypeString)—the value may be a string.

The ArcMap identify dialog and editor's property inspector make use of coded value domains to display the human-readable description of values for an attribute. The object inspector also provides a list of valid values for users to select when editing an attribute with a coded value domain, as shown below:

The following VBA® code fragment demonstrates how a user could use these properties in order to display all the (value, name) pairs associated with a CodedValueDomain.

[Visual Basic 6.0]
Dim pCodedValueDomain as ICodedValueDomain
Set pCodedValueDomain = pDomain 'assume an existing domain
Dim lCount as Long
lCount = pCodedValueDomain.CodeCount

'Iterate through the coded value pairs
Dim i As Long, vValue As Variant, sName As String
For i = 0 To lCount - 1
  vValue = pCodedValueDomain.Value(i)
  sName = pCodedValueDomain.Name(i)
  MsgBox "value: " & vValue & vbCr & "name: " & sName
Next i

Domains are managed at the workspace level. The following graphic is the ArcCatalog user interface for creating, deleting and modifying domains:

Relationship rules

A RelationshipRule constrains the cardinalities between two subtypes that participate in a RelationshipClass. Thus, if the RelationshipClass is a one-to-many relationship, a RelationshipRule may, for example, constrain the cardinalities between two subtypes to be one–three. The RelationshipRule may not conflict with the RelationshipClass. For example, a one-to-many RelationshipClass may not have any associated relationship rules that constrain the cardinalities to be two to two. One RelationshipRule is necessary for each subtype pair that participates in the RelationshipClass.

The IRelationshipRule interface inherits from IRule. This interface provides access to the various parameters of a relationship rule that are used to refine the cardinalities between subtypes participating in the RelationshipClass. Use this interface when you want to set or retrieve these parameters.

DestinationMaximumCardinality and DestinationMinimumCardinality are only applicable in one-to-many and many-to-many relationships.

OriginMaximumCardinality and OriginMinimumCardinality are only applicable in many-to-many relationships.

Connectivity rules

A connectivity rule constrains the type of network connectivity that may be established between edges and junctions in the geometric network.

Within a geometric network, any edge may connect to any junction. ConnectivityRules are used to constrain the permissible connectivity between edges and junctions. There are two types of connectivity rules that can be applied. JunctionConnectivityRules are placed on junction object classes and determine the valid types of edges that can be connected. EdgeConnectivityRules are placed on edge object classes and determine the valid types of junction or edges (through a junction) that can be connected. Connectivity rules can only be established between network feature classes.

The JunctionConnectivityRule class is a type of ConnectivityRule that constrains the possible valid network connections that may exist between a pair of edge and junction subtypes. It may also constrain the cardinalities of the connectivity relationships.

The IJunctionConnectivityRule interface inherits from IConnectivityRule. This interface defines the junction connectivity properties and the valid types of edges that can connect to them. Use this interface when you want to define or manipulate rules between an edge and a junction.

The EdgeConnectivityRule class is a type of ConnectivityRule that defines the permissible relationship between two edge features. In addition, it specifies all the valid junctions that may exist at the connection point between the two edges. It is also possible to specify the default junction that will be placed at the point of connectivity between the two edges.

The IEdgeConnectivityRule interface inherits from IConnectivityRule. This interface defines the two types of edges (they can be of the same type) and the valid junctions that can exist between them.

DefaultJunctionClassID and DefaultJunctionSubtypeCode define the default junction that will be added at the location where connectivity is established between two edges of the specified type.

The number of junctions associated with the EdgeConnectivityRule is unlimited. Junctions are managed through this interface and are accessed on an index basis (the JunctionCount property and the JunctionClassID and JunctionSubtypeCode index-based properties). It is not possible to remove a junction from the rule; if this is required, the rule must be deleted and then re-created, less the junction, to be deleted.

The following graphic illustrates the ArcCatalog user interface for configuring connectivity rules for a geometric network:

For more information on geometric networks, see the Geometric network section in this document.


The following samples illustrate the use of these objects.


Extending ArcObjects contains the following fully documented samples with code samples in a number of languages.


Geometric network

A geometric network is a type of graph that is uniquely associated with a logical network, which represents network topology.

GeometricNetworks are responsible for detecting and maintaining network connectivity among a set of feature classes that participate in the network. When new network features are created, the GeometricNetwork is responsible for detecting endpoint coincidence (in the case of edge features) with other network features, then communicating with the logical network in order to establish network connectivity.

The GeometricNetwork is also responsible for managing and validating all connectivity rules.

The most common type of third-party client applications that will consume the IGeometricNetwork interface are custom network solvers. The associated logical network may be accessed through the Network property.

The direct accessibility of the logical network obviates the need to expose the functionality of the logical network through redundant convenience methods at the geometric network level. Functionality that is related to the mapping between geometry (found at the feature level) and network elements (found at the logical network level) is necessarily supported outside of the logical network. This is because the logical network does not have any understanding of feature geometry, only logical connectivity.

You can determine the network elements associated with a network feature at a given location through the EdgeElement and JunctionElement properties. If there is more than one network feature of the appropriate type at the location, then the edge or junction element that corresponds to the first one encountered is returned.

Complementary functionality is also provided where, for a given edge or junction element, the associated feature geometry is returned via the GeometryForEdgeEID and GeometryForJunctionEID properties, respectively.

In contrast to the results returned by the EdgeElement and JunctionElement methods, the GeometryForEdgeEID and GeometryForJunctionEID properties return an unambiguous result, as only one piece of geometry corresponds to a given EID. An EID is an element ID for an element in a logical network.

A final method found on IGeometricNetwork that may commonly be called by third-party client applications is SearchForNetworkFeature. This method, given a point location and a feature type, will return all the network features that are found within the machine precision of this point. If more than one network feature is coincident with the point, then all are returned. The returned network features may span different feature classes; the only restriction is that all features must be of the same feature type.

The IGeometricNetworkErrorDetection interface identifies errors between a geometric network and its logical network.

In order to maintain correct network connectivity in large production environments, it is necessary to have a collection of tools that will enable the user to detect a variety of connectivity problems within a geometric network. In production environments, it is often impractical to drop the network and rebuild when connectivity problems are encountered during general editing of the network. For this reason, it is necessary to provide a set of tools that will enable the end user to detect and repair such problems.

Philosophically, there should not be any need for such tools—the network should always be correct. From this standpoint, the geodatabase will not waver. However, there are certain circumstances where this may be violated:

The CreateErrorTable method is used to create a table that can be used to persist information related to corrupt network features (using a fixed table schema) with the specified name. Such network error information can only be persisted by the geometric network in a table with this schema. This table is user managed and should remain unversioned.

The DeleteNetworkElements method takes an ISet of ISelectionSets. All of the network features contained in the various selection sets will have their network elements deleted from the logical network. The primary reason why one would want to do this is to correct the geometry of an edge feature that was loaded (prior to ArcGIS 8.1) with corrupt polyline geometry.

If network connectivity errors are found in the geometric network, they can generally be corrected through the use of the RebuildConnectivity method on the IGeometricNetworkConnectivity interface. This method takes an envelope that should contain all the network features for which connectivity should be rebuilt.

A graph is a set of topologically related feature classes. A Graph is an abstract class that factors behavior and attribution common to the different types of topological collections within the geodatabase.

The IGraph interface specifies the attributes and properties expected on all the different types of topological collections within the geodatabase. These attributes and methods are not unique to a particular type of topology. It is not expected that third-party client applications will call many of these methods. The primary clients of these methods on this interface are ArcMap, ArcCatalog, and the polymorphic implementations of the features managed by the Graph.

Network features

NetworkFeature is an abstract component that supports network connectivity and participates in a geometric network.

The INetworkFeature interface is supported at the NetworkFeature level within the geodatabase; all features participating in a GeometricNetwork support this interface. Because each NetworkFeature may either be enabled (can trace through) or disabled (cannot trace through) within the logical network, the Enabled property is read–write. It is important to note that although a complex edge may correspond to one or more network elements, setting the Enabled property will either enable or disable all associated network elements. It is not possible to individually set the enabled or disabled status of an individual network element associated with a complex network feature through this interface.

When a NetworkFeature is being created and added to a GeometricNetwork coclass, the GeometricNetwork will call the CreateNetworkElements method on the NetworkFeature. It will not be necessary for a custom feature developer to override this method in their implementation.

It is important to note that if network features are being programmatically created (for example, using a sequence similar to IFeatureClass::CreateFeature, setting the feature’s Shape, then calling Store on the feature), the network feature’s spatial reference must match that of the containing FeatureClass. More specifically, if you call IGeometry::Project on the geometry prior to it being set as the feature’s Shape, you must take care to ensure that the SpatialReference that is being passed as an argument to Project match that of the FeatureClass. It is not always the case that the Map’s SpatialReference is the correct one to use (for example, the Map may contain two FeatureDatasets with differing SpatialReferences).

Junction features are used to maintain network integrity within a geometric network. They are found at the locations that correspond to the endpoints of edge features. They may also be freestanding (unconnected to any edge feature) or connected to complex edges at midspan.

The SimpleJunctionFeature class represents simple junctions on a network that may be added to GeometricNetworks.

The SimpleJunctionFeature class can be aggregated, and possibly overridden, by custom feature developers.

Simple junction features have point geometry and may be connected to any number of other edge features.

A simple junction feature may not be directly connected to another junction feature without an intervening edge feature.

The ISimpleJunctionFeature interface contains three properties that are unique to simple junctions.

The EdgeFeatureCount property and EdgeFeature property array are used to specify the connected edge features to the client. The index for EdgeFeature is zero-based.

The following VBA code fragment shows how a client might use this information to display the object IDs of the connected edge features.

[Visual Basic 6.0]
'Assume we already have a pointer to a junction feature.
Dim pSimpleJunction As ISimpleJunctionFeature
Set pSimpleJunction = pJunction
Dim i As Long, pEdgeFeature As IEdgeFeature, pRow as IRow
For i = 0 To (pSimpleJunction.EdgeFeatureCount – 1)
Set pEdgeFeature = pSimpleJunction.EdgeFeature(i)
Set pRow = pEdgeFeature
MsgBox "EdgeFeature [" & i & "]: " & pRow.OID
Next i

Edge features correspond to features with polyline geometry that are part of the network topology within a geometric network. They have two or more connected junction features—one at each location corresponding to the endpoints of their polyline geometries. Complex edges may also have any number of connected mid-span junction features. An EdgeFeature is an abstract class.

The IEdgeFeature interface must be supported by both simple and complex edges. This interface is found on the EdgeFeature abstract class. The various properties found on this interface are intended to facilitate network feature navigation for client applications.

The FromToJunctionEIDs property hands back both the FROM and TO junction EIDs; it is more efficient to access this property than to call FromJunctionEID and ToJunctionEID. It is important to note that these properties are generally computationally expensive. For certain clients (that is, those that do not require access to the geometry, attributes, or feature class associated with the network feature), it may prove more advantageous to directly utilize the logical network when performing navigation between large numbers of network features. For example, this is the case with network solvers.

The Update method is reserved for internal consumption (during the process of updating the shape and storing the result); there is no need for clients to call this method directly.

Simple edge features correspond to features with polyline geometry that are part of the network topology within a geometric network. They have two connected junction features—one at each location corresponding to the endpoints of their polyline geometries. Junction features connected at mid-span are not allowed. If you attempt to connect a junction at mid-span on a SimpleEdgeFeature, a split operation occurs (the original SimpleEdgeFeature is deleted and replaced by two new SimpleEdgeFeatures that are commonly connected at the junction feature that caused the subdivision).

Complex edge features correspond to features with polyline geometry that are part of the network topology within a geometric network. They have two or more connected junction features—one at each location corresponding to the endpoints of their polyline geometries. They may also have any number of connected mid-span junction features.

Connecting a junction feature to a ComplexEdgeFeature does not result in a physical subdivision of the edge; instead, it results in a logical subdivision (that is, new edge elements in the logical network that are associated with the complex edge).

The geometry of ComplexEdgeFeatures may not be self-intersecting; there may be discontinuities with the geometry (they may be multipart), and the geometry may not have the same start and stop vertex (that is, a closed loop).

The IComplexEdgeFeature interface is supported on a ComplexEdgeFeature. The GeometryForEID property allows clients to obtain the portion of the complex edge’s geometry that corresponds to a specified EID. This is useful for network solvers in particular. The JunctionFeature property array is a mechanism for clients to obtain all the junction features that are associated with the complex edge.


The following samples illustrate the use of Geodatasets.



A topology is a collection of simple feature classes within the same feature dataset that participate in topological relationships with a set of rules that govern those relationships. Topologies can have multiple feature classes in the same topological role. A feature dataset may have multiple topologies but a feature class can only belong to one topology. Each topology has one associated topology graph. The topology graph is a planar representation of the geometries in the feature classes participating in a geodatabase topology.

When new features are created, edited or deleted, the topology is responsible for creating or modifying a dirty area that will encompass the envelope of the feature. A dirty area is a special type of feature under which, the state of the topology is unknown:

Features that are covered by dirty areas can still be edited and queried, but their topological relationships cannot be guaranteed to be correct. A dirty area must be validated in order to discover the topology of its underlying features.

The Topology object is not cocreateable, topologies must be created through another method call, ITopologyContainer::CreateTopology.

The ITopology interface provides properties of a topology and methods for adding feature classes and validating dirty areas.

The following code shows you how to obtain a reference to a topology in your feature workspace:

[Visual Basic 6.0]
Dim pFeatureWorkspace As IFeatureWorkspace
Dim pFeatureDataset As IFeatureDataset
Dim pTopologyContainer As ITopologyContainer
Dim pTopology As ITopology
Set pFeatureDataset = pFeatureWorkspace.OpenFeatureDataset(“Your feature
dataset’s name”)
Set pTopologyContainer = pFeatureDataset
Set pTopology = pTopologyContainer.TopologyByName(“Your topology’s name”)

The following VBA code demonstrates how to quickly obtain a reference to a topology in ArcMap using the TopologyExtension object while in an edit session.

[Visual Basic for Applications]
Dim pTopologyExt As esriEditorExt.ITopologyExtension
Dim pUID As New esriSystem.UID
Dim pTopology As ITopology
pUID = “esriEditorExt.TopologyExtension”
Set pTopologyExt = Application.FindExtensionByCLSID(pUID)
Set pTopology = pTopologyExt.CurrentTopology

The AddClass method is used to add a feature class to the topology, with the specified weight and ranks.

Non-simple feature classes, such as annotation, dimension and geometric network feature classes cannot be added to a Topology. Object classes or tables and versioned simple feature classes, cannot be added to a Topology. After a populated feature class is added to a topology that has already been validated, in whole or in part, the state of the topology will be changed and a dirty area corresponding to the extent of the feature class will be created. If an unpopulated feature class is added to a topology, the topology’s state will not change and no dirty area will be created. The AddClass method cannot be called on versioned topologies in ArcSDE, but can be called on non-versioned topologies in ArcSDE and topologies in a personal geodatabase.

Topologies support the IFeatureClassContainer interface that can be used to return the feature classes participating in the topology.

The Cache property returns a reference to the topology graph of the Topology. The topology graph can be used for working with topological primitives such as edges and nodes. For more information, see the the discussion on the topology graph later in this section.

The ClusterTolerance property returns the tolerance that was specified when the topology was built. The ClusterTolerance of the topology cannot be changed. In order to modify the tolerance, the Topology must be deleted and rebuilt with the new ClusterTolerance.

The DirtyArea method returns the dirty area polygon of the topology. The DirtyArea property requires an IPolygon object as input. The IPolygon can correspond to the extent of the topology or a subset of the extent. If there is no dirty area intersecting the specified area, an empty polygon is returned. The dirty area polygon that is returned may be a multipart polygon.

The following VBA code example demonstrates how to obtain the DirtyArea for the entire Topology.

[Visual Basic for Applications]
‘Assume we have a reference to a Topology called pTopo
Dim pGeoDS As IGeoDataset
Dim pLocation As ISegmentCollection
Dim pPoly As IPolygon
Dim pAreaToValidate As IEnvelope
Dim pAreaValidated As IEnvelope
‘Create a new polygon object
Set pLocation = New Polygon
‘QI to the IGeoDataset so we can get the extent of the Topology
Set pGeoDS = pTopo
‘Set the rectangle of the pLocation polygon to be equal to the Topology
pLocation.SetRectangle pGeoDS.Extent
‘Get the Dirty Area for the entire Topology
Set pPoly = pTopo.DirtyArea(pLocation)

Each topology has a maximum number of errors that can be generated on Validate, which can be determined through the MaximumGeneratedErrorCount property. MaximumGeneratedErrorCount can only be specified when a Topology is created programmatically. All topologies created with the New Topology wizard in ArcCatalog have a MaximumGeneratedErrorCount of –1, indicating no limit to the number of errors that can be generated. As with the ClusterTolerance, the MaximumGeneratedErrorCount property cannot be changed, a topology must be deleted and rebuilt in order to specify a new value.

The RemoveClass method is not implemented for ArcGIS 9.0.

The State property indicates the current status of the Topology; whether the topology has been validated and if so, whether any topology errors have been discovered.

ValidateTopology validates the dirty area of the topology in the area specified by the areaToValidate envelope. ValidateTopology evaluates all the rules and produces any topology errors corresponding to areas in which a rule has been violated. The ValidateTopology function returns the envelope of the validated area. If an empty envelope is supplied, ValidateTopology will return an empty validated area. ValidateTopology can be performed outside of an edit session on topologies within personal geodatabases or on topologies within ArcSDE geodatabases that have not been registered as versioned. Once a topology is registered as versioned, ValidateTopology must be performed within an edit session and bracketed within an edit operation. The IWorkspaceEdit or IEditor interfaces can be used to manage edit sessions and edit operations.

An entire topology can be validated by supplying the envelope of the extent of the topology, demonstrated by the following VBA code example.

[Visual Basic for Applications]
‘Assume a reference to a Topology called pTopo
Dim pGeoDS As IGeoDataset
‘QI to the IGeoDataset so we can get the extent of the Topology
Set pGeoDS = pTopo
‘Validate the Topology
pTopo.ValidateTopology pGeoDS.Extent.Envelope

By supplying a polygon object to the ITopology::DirtyArea property, the dirty area at a particular location can be returned. The envelope of the returned dirty area polygon can then be passed into ValidateTopology.

‘Assume a reference to a Topology called pTopo
Dim pGeoDS As IGeoDataset
Dim pLocation As ISegmentCollection
Dim pPoly As IPolygon
Dim pAreaToValidate As IEnvelope
Dim pAreaValidated As IEnvelope
‘Create a new polygon object
Set pLocation = New Polygon
‘QI to the IGeoDataset so we can get the extent of the Topology
Set pGeoDS = pTopo
‘Set the rectangle of the pLocation polygon to be equal to the Topology
pLocation.SetRectangle pGeoDS.Extent
‘Get the Dirty Area for the entire Topology
Set pPoly = pTopo.DirtyArea(pLocation)
‘Set the Area to validate and validate the topology
Set pAreaToValidate = pPoly.Envelope
Set pAreaValidated =

The ITopologyRuleContainer interface provides access to members for adding, removing and returning topology rules from a topology. This interface also provides access to members that control the promotion and demotion of topology errors and exceptions.

The CanAddRule property returns a boolean value indicating if the topology rule is valid with respect to the existing rules. This property will return false if:

The AddRule method is used for adding a new rule to a topology. The addition of the new rule results in a dirty area created for the extent of the entire topology and a change to the state of the topology to esriTSUnanalyzed.

The DeleteRule method removes the specified rule from the topology, resulting in a dirty area created for the extent of the entire topology and a change to the state of the topology to esriTSUnanalyzed.

The DemoteFromRuleException method will demote the specified exception from being an exception to an error feature. On a topology in a versioned geodatabase, DemoteFromRuleException, must be called from within an edit session and edit operation.

The PromoteToRuleException method will promote an error feature from an error to an exception. On a topology in a versioned geodatabase, PromoteToRuleException, must be called from within an edit session and edit operation.

The ITopologyClass interface provides read-only access to the properties of feature classes in a Topology. Most of these properties are specified when the feature class is added to the Topology.

The ITopologyContainer interface can be used to manage and create topologies within a feature dataset. If your intention is to simply browse for the set of topologies in a feature dataset, it is not necessary to open the feature dataset and call the methods on ITopologyContainer. The IFeatureDatasetNames2::TopologyNames method can be used to efficiently obtain this information. Careful consideration should be given to specifying the parameters when creating a topology. Once the topology is built, none of the parameters can be modified. In order to change properties such as cluster tolerance, the topology must be deleted and rebuilt with the new parameters.

The ITopologyProperties interface provides access to additional properties of a topology not supplied through the ITopology interface such the enumeration of feature classes and spatial reference of the Topology.

The ITopologyWorkspace interface provides access to the OpenTopology method that allows you open a topology within a workspace given the topology’s name. Use this interface to open a topology when you only have a reference to a workspace object. For ArcSDE geodatabases, the fully qualified name can be used to return topologies owned by specific users. If multiple topologies with the same name and owned by different users exist within the geodatabase, OpenTopology will return the topology owned by the connected user if an unqualified name is supplied.

The ITopologyErrorFeature interface provides access to the read-only properties of topology error features. Topology error features represent violations of topology rules and are discovered during the validation process. Error features cannot be edited directly, so while you can QueryInterface for interfaces such as IFeature on a TopoloyErrorFeature, calling methods such as IFeature::Value or IFeature::Store will fail. The only modification that can be made to a topology error feature is to mark it as an exception using the ITopologyRuleContainer::PromoteToRuleException. Conversely, exceptions can be marked as an error by passing it as an argument to ITopologyRuleContainer::DemoteFromRuleException.

The OriginID and DestinationID properties represent the object class IDs of the origin and destination feature classes of the topology rule that the error feature is a violation of. The OriginOID and DestinationOID properties represent the object IDs of the origin and destination features that created the topology error.

In general, all topology errors for which only the origin class has been specified will return values for the OriginID and OriginOID properties and a value of zero for the DestinationID and DestinationOID properties. The exception is for topology errors generated from the esriTRTNoGaps rule, which will return a value of zero for the Origin as well as Destination ID and OID properties. In addition, topology rules whose origin and destination feature class have been specified will generally return zero for the Destination feature class properties. The exceptions to this rule are:

The exception to both of these statements is the esriTRTAreaAreaCoverEachOther rule, which may generate topology errors referencing either the Origin or Destination feature class.

The ErrorID of a topology error feature is not unique across all topology error features within the topology, but is unique for each topology error feature geometry type. While a topology error feature with polygon geometry may have the same ErrorID as a topology error feature with point geometry, the ErrorID will be unique for all topology error features with polygon geometry. Combining the ErrorID and ShapeType of a topology error feature will result in a unique value within the topology.

The TopologyRule class is used to define the permissible spatial relationships between features within a topology. Topology rules can be defined with a single feature class or between two feature classes. Topology rules can also be defined to the subtype level of a feature class. Topology rules have an origin and a destination feature class, either of which can be set to the subtype level. Depending on the type of topology rule that is implemented, the destination feature class properties may be irrelevant.

The ITopologyRule is the main interface for creating and returning information about a topology rule. Use this interface to create a new topology rule or return the properties of existing rules.

The AllDestinationSubtypes property specifies if the rule applies to all subtypes in the destination feature class. By default AllDestinationSubtypes is False and the DestinationSubtype property points to the default subtype. If AllDestinationSubtypes is explicitly set to False, the DestinationSubtype property must be set or the rule will be invalid. AllDestinationSubtypes returns the opposite value of the DestinationSubtypeSpecified property. If the topology rule is a single feature class rule, AllDestinationSubtypes is set to True once the rule is added to the Topology.

AllOriginSubtypes specifies if the rule applies to all subtypes in the origin feature class. By default AllOriginSubtypes is False and the OriginSubtype property points to the default subtype. If AllOriginSubtypes is explicitly set to False, the OriginSubtype property must be set or the rule will be invalid. AllOriginSubtypes returns the opposite value of the OriginSubtypeSpecified property.

The DestinationClassID property corresponds to the ObjectClassID of the destination feature class of the topology rule. If the topology rule is a single feature class rule, the DestinationClassID does not need to be set, it will be equal to the OriginClassID by default and if set, will be ignored when the rule is added to the Topology. The OriginClassID property corresponds to the ObjectClassID of the origin feature class of the topology rule. Every topology rule will have an OriginClassID.

OriginSubtype and DestinationSubtype correspond to the origin and destination subtypes of the topology rule. Setting the OriginSubtype or DestinationSubtype will result in the corresponding SubtypeSpecified property returning True. If AllOriginSubtypes or AllDestinationSubtypes is set to True, the value specified for OriginSubtype or DestinationSubtype will be ignored. The ErrorShapeTypes method indicates the error shape types that can be produced by the topology rule. If the rule supports a particular shape type, it will return a value of True.

The GUID property is read-only and returns the unique, geodatabase-controlled value that is set when the rule is added to the topology using ITopologyRuleContainer::AddRule. The GUID value can be used to return its associated topology rule using ITopologyRuleContainer::RulebyGUID. The Name property can be used to assign a user specified string to each rule. By default, the Name property is empty.

The TopologyRuleType property is used to return or set the type of topology rule from the esriTopologyRuleType constants. Every topology has one inherent rule, the esriTRTFeatureLargerThanClusterTolerance rule, which is added implicitly when the topology is created.

As mentioned previously, the Cache property on ITopology returns a reference to the topology graph of the Topology. The topology graph can be used for working with topological primitives such as edges and nodes.

A topology graph is a cached planar representation of the feature geometries participating in a topology, where the topological relationships are known. There is only one graph per topology. It is derived from the Topology object and cannot be cocreated. The TopologyGraph object was designed to allow editing of a topology without breaking adjacency or connectivity of the participating features, also known as “Shared Editing”. For example, TopologyGraph can be used to edit the shared boundaries of two polygons without breaking the adjacency of their geometries. Additionally, use it to move a set of overlapping routes while keeping all features coincident. There are a number of properties and methods that can be used on the TopologyGraph object and its components to:

  • Navigate through it
  • Modify the geometry of the topology elements
  • Discover the relationship between features
  • Modify the connectivity between features
  • A TopologyGraph object is accessed from a Topology object and is constructed for a given extent. It references the topology primitives that are cached. The topology primitive geometries present in memory have been modified, via cracking and clustering, during a round trip to the topology engine. However, it is important to understand that these geometries are not updated on disk yet. They are updated only if the topology elements are modified and those edits are posted back to disk. For example, one could programmatically move a topology node, which is shared by several features. This edit is cached in memory until the ITopologyGraph::Post method is called. That method will propagate the edit to all the features sharing that topology node; the geometries of those features will be updated.

    The TopologyGraph object is derived from a Topology object and is a singleton. As previously described, you can access a topology's topology graph using the ITopology::Cache method. The topology graph is empty initially and must be built to contain the topology primitives.

    For a given topology, the topology graph is built on demand with a user-defined envelope bounding its included features. At construction time, the feature geometries are sent to the topology engine, where they are cracked and clustered using the cluster tolerance for the topology. Cracking and clustering is a process where vertices are introduced at each feature intersection and the new and existing vertices are grouped into clusters. This process is necessary to remove ambiguities between features and discover their topological relationships. After cracking and clustering, the features are, at minimum, separated by the cluster tolerance of the given topology. For a second time, the topological relationships between features are discovered and sent back to the client code. The topology primitives (geometry and topological relationships) are persisted in memory for further uses.

    There are two types of topology primitives, or elements, that are cached—nodes and edges. A TopologyNode is an object holding a reference to an IPoint geometry. It is created at each feature's endpoints as well as at the intersections of feature geometries participating in the topology. The node also contains topological relationships information, such as incident TopologyEdges and corresponding TopologyParents. A TopologyParent is a pointer to a feature class coupled with a feature OID. This couple uniquely identifies a feature part of the topology.

    A TopologyEdge is defined as an object holding a reference to an IPolyline geometry (always single part) formed between two TopologyNodes. The edge also references the topological relationships information, such as FromTopologyNode, ToTopologyNode, and TopologyParents. The TopologyEdge also allows its left and right polygons to be identified when appropriate. At any time the relationship between nodes, edges, and features can be accessed using the TopologyGraph API. The diagrams below give representations of the TopologyGraph object.

    In this diagram, two polyline features are used to construct the topology graph. The TopologyGraph is persisted in memory and contains nine topology primitives: five nodes and four edges. Each TopologyNode knows which features were used to construct it; those features are called TopologyParents. For example, the parents of the center TopologyNode are the two polyline features. The TopologyNode also knows which TopologyEdges are connected to it. The edges, in turn, are aware of their TopologyParents, as well as the FromTopologyNode and the ToTopologyNode.

    In this diagram, a polyline feature overlaps the boundaries of two adjacent polygon features. In this case, the TopologyGraph contains five topology primitives: two nodes and three edges. Each TopologyNode has three TopologyParents—the polyline and both polygons. The black arrow shows the orientation of the polyline feature. The red arrows show the orientation of the TopologyEdges. For example, the central TopologyEdge has three parents, the polyline and both polygons. Using this TopologyEdge and the ITopologyEdge::LeftParents or ITopologyEdge::RightParents method, you can access the blue and green polygons. The orientation of the edge determines which polygon is the left or right parent. A TopologyEdge also knows which TopologyNodes are associated with it. You could use this information to navigate in the TopologyGraph. A topology element can have 1-N TopologyParents. The parents are, in fact, the features that share geometries at a given location.

    The ITopologyGraph interface exposes several methods for interacting with the elements of a topology and, therefore, the underlying features participating in the topology. You can access all or selected elements of a TopologyGraph. To access:

    Once you’ve accessed the topology elements, you can work with their associated topological relationships. Three methods are available. To retrieve

    As discussed earlier, the features associated with a topology element are known as its TopologyParents. Three methods are available providing access to:

    Topology elements can be moved or transformed in a variety of ways. The methods used vary according to the type of transformation. If you are

    By default, any operations done on the TopologyGraph will affect all TopologyParents (features) associated with its edited elements. However there is a way to control which features are affected by a given operation. The TopologyParent selection (used by the “Show Shared features” dialog on the Topology Toolbar in ArcMap) can help modify this behavior. The parent selection is defined as the state of the TopologyParents for a given operation. This state, by default, is set to true for all TopologyParents. By changing this state to false, some features can be subtracted from the subsequent TopologyGraph operation. This can be done using the ITopologyGraph::SetParentSelected method. The state is reset to its default after any TopologyGraph operation.

    Modifying a TopologyGraph element doesn’t immediately modify the features on disk. A topology edit exists in memory but the features are not modified until the ITopologyGraph::Post method is called. This method propagates the edits made on the topology element’s geometry into the features associated with it (TopologyParents). In basic terms, it replaces the edited feature’s geometry with the geometries that went to the topology engine and have the modified shape.

    Since all topology primitives are stored in memory, building the TopologyGraph for a large extent is not recommended. For efficiency reasons the smaller the extent of the TopologyGraph the better; however some applications could require larger extents. As an alternative, it is possible to build several smaller TopologyGraphs in some cases. The amount of RAM available on your machine is directly correlated to the performance of the TopologyGraph: the more RAM the better.


    The following samples illustrate the use of Tables.


    Extending ArcObjects contains the following fully documented samples with code samples in a number of languages.


    Data elements

    In general, data elements describe entities that can be used in geoprocessing functions. Examples of such classes are DEFolder, DETable, and DEShapeFile. These objects are simple structures whose properties describe the actual entity. For instance, DEShapeFile has properties such as Extent and SpatialReference. A subset of the data elements describes geodatabase datasets. The classes DEFeatureClass, DEFeatureDataset, and others can be used to describe actual geodatabase datasets.

    The workspace and feature dataset are containers of other datasets. Likewise the DEWorkspace and DEFeatureDataset will contain other data elements in their Children array (accessible through the IDataElement interface).

    Data elements support IXMLSerialize and IPersistStream, and thus a set of data elements can be serialized in XML or binary form.

    Data elements can be created in several ways. Data elements are cocreatable, and application developers can create new instances of a data element then fill its properties with appropriate values. In ArcCatalog the data element associated to a GxObject can be obtained by using the method GetDataElement in the interface IGxDataElement. Lastly, a workspace may implement the interface IWorkspaceDataElements, which can be used to request a data element for the whole workspace, or a data element for a particular dataset.

    The CatalogPath of a data element contains the path to the dataset. If retrieved from a GxObject, the data element's catalog path will correspond to the path displayed by ArcCatalog when the dataset is selected in the view pane. If retrieved from the workspace, the catalog path will be built by following this pattern:


    where the path elements are separated using a slash character and the dataset keywords are taken from the list below. The version can be empty if the source is a personal geodatabase.

    Dataset Type Keyword
    Feature dataset FD
    Feature class FC
    ObjectClass OC
    Relationship Class RC
    Geometric network GN
    Topology TOPO
    Raster band RB
    Raster dataset RD
    Raster catalog RCAT
    Toolbox TB

    These are sample catalog paths.


    The method GetDatasetDataElement in IWorkspaceDataElements allows client code to create a data element from a name object or from a dataset object. In the first case only the properties available in the name object will be populated in the resulting data element. The boolean RetrieveFullProperties property in DEBrowseOptions must be set to False when using a name object as input.

    [Visual Basic 6.0]
    ' assume pWS has connection to geodatabase.
    ' get data element w/base props for first feature class name
    Dim pWSDEs As IWorkspaceDataElements
    Set pWSDEs = pWS
    Dim pDSNs As IEnumDatasetName
    Set pDSNs = pWS.DatasetNames(esriDTFeatureClass)
    Dim pDSN As IDatasetName
    Set pDSN = pDSNs.Next
    ' if using name object, then must request base properties
    Dim pBOpts As IDEBrowseOptions
    Set pBOpts = New DEBrowseOptions
    pBOpts.RetrieveFullProperties = False
    pBOpts.ExpandType = esriDEExpandNone
    Dim pDEFC As IDEFeatureClass
    Set pDEFC = pWSDEs.GetDatasetDataElement(pDSN, pBOpts)

    When using a dataset as input, the GetDatasetDataElement method will return a fully populated data element.

    [Visual Basic 6.0]
    Dim pName As IName
    Set pName = pDSN
    Dim pDS As IDataset
    Set pDS = pName.Open
    ' if using dataset, then must request full properties
    pBOpts.RetrieveFullProperties = True
    Set pDEFC = pWSDEs.GetDatasetDataElement(pDS, pBOpts)

    The ExpandType property of DEBrowseOptions controls whether data elements should be created for children of the requested data element. Client code can request only immediate children or all descendants. For example, when using the method GetWorkspaceDataElement with immediate children, data elements for tables, feature datasets, and other datasets at the workspace level will be created, but no data element will be created for datasets under the feature datasets. Lastly, the dataset's metadata will be retrieved only if RetrieveMetadata is set to true.

    The GdbSchemaCreator class can be used to create the schema given an array of data elements.

    In the sample below the array has one DEFeatureClass instance. The schema creator requires full properties to be retrieved to create the datasets. The catalog path should be a geodatabase complaint catalog path.

    [Visual Basic 6.0]
    ' assume pWS2 has target workspace
    Dim pSCreator As IGdbSchemaCreator
    Set pSCreator = New GdbSchemaCreator
    ' assume pDEFC has a DEFeatureClass
    Dim pDEs As IArray
    Set pDEs = New esriSystem.Array
    pDEs.Insert 0, pDEFC
    Dim pENM As IEnumNameMapping
    Dim bHasConflict As Boolean
    pSCreator.GenerateNameMapping pWS2, pDEs, Nothing, pENM, bHasConflict
    pSCreator.CreateSchema pWS2, pENM

    The association between a feature class and a topology has extra attributes—for example, the rank of the feature class. The association of a feature class and a geometric network also has extra attributes—for example, the enabled field. These are attributes of the feature class’s membership in a controlling entity, be it the topology or the geometric network. They are attributes of the membership because they wouldn't exist if the feature class were not a member of the controller. The table data element has an array of controller memberships. Each membership contains the data about the relationship between the feature class and the controlling entity (rank or enabled field, for example).

    Some properties of data elements are instances of other classes in the geodatabase library. For example, the fields of a DETable are instances of the Fields and Field classes. This is done whenever the existing ArcObject class is a simple cocreatable structure that can be used detached from any dataset. Other examples are the rules (connectivity, topology), weights and weight associations, domains, and indexes.

    Simple classes were created for other geodatabase constructs that are not datasets, but required to be described as properties of data elements. Such classes have the GP prefix. For instance, the GPSubtype class represents a geodatabase subtype, and the table data element has an array of GPSubtypes. Other examples of these classes are GPTopologyMembership, GPGeometricNetworkMembership, and GPRelationshipClassKey.

    Data elements are simple structures with very little behavior. Caution must be exercised when setting their properties because there is little validation code. For example, a DEGdbTable could be defined to have a SubtypeFieldName, but no actual subtypes be placed in its Subtype array. Such instance would be invalid for most purposes.

    The following are the data element objects in the geodatabase:



    The TIN sub-system contains objects for accessing and working with Triangulated Irregular Networks (TINs).

    The Tin coclass is used for surface modeling and other forms of spatial analysis. A TIN is comprised of adjacent, non-overlapping, triangles. It is a complete planar graph that maintains topologic relationships between its constituent elements: nodes, edges, and triangles. Point, polyline, and polygon features can be incorporated into a TIN. The vertices are used as nodes which are connected by edges that form triangles. Edges connect nodes that are close to one another. The partitioning of continuous space into triangular facets facilitates surface modeling because a very close approximation of a surface can be made by fitting triangles to planar, or near planar, patches on the surface. Input vector data are incorporated directly in the model and any resulting query or analysis will honor them exactly. Since the triangulation is based on proximity, interpolation neighborhoods are always comprised of the closest input data/samples. Proximity based connectivity is useful for other analysis as well. For example, Thiessen polygons, also known as Voronoi diagrams, are constructed from TINs.

    Certain licensing issues apply when working with TINs. Creation, editing, and analysis functions require a 3D Analyst license while simple data managment such as copy, delete, and rename only require a core license. Additionally, the use of TIN layers for simple display and query only requires a core license.

    TINs can be in-memory only objects or persisted to disk as datasets. A TIN can be made from scratch in memory, have data added, analysis performed, and then be discarded without ever being written to disk. This is particularly useful when using TIN as a temporary data structure to handle some analysis problem because the expense of writing to disk can be avoided. On the other hand, people often create TINs and save them to disk for use at a later time. The most common example of this is the use of TIN as a surface model that will be used repeatedly over time.

    The following sample is used to open an existing TIN on disk via the TinWorkspace object:

    [Visual Basic 6.0]
    Public Function OpenTin(sDir As String, sName As String) As ITin
      Dim pWSFact As IWorkspaceFactory
      Dim pTinWS As ITinWorkspace
      Dim pTin As ITin
      Set pWSFact = New TinWorkspaceFactory
      If (pWSFact.IsWorkspace(sDir)) Then
        Set pTinWS = pWSFact.OpenFromFile(sDir, 0)
        If (pTinWS.IsTin(sName)) Then
          Set pTin = pTinWS.OpenTin(sName)
        End If
      End If
      Set OpenTin = pTin
    End Function

    Here is an alternate way to open an existing TIN on disk via the Tin object itself:

    [Visual Basic 6.0]
    Public Function OpenTin(sDir As String, sName As String) As ITin
      Dim pTinAdv As ITinAdvanced
      Set pTinAdv = New Tin
      pTinAdv.Init sDir & "\" & sName
      Set OpenTin = pTinAdv
    End Function

    Several notable interfaces implemented by the Tin object are ITinAdvanced2, ITinEdit, and ISurface. ITinAdvanced2 provides access to basic properties and is a jump off point for getting at the underlying data structure. ITinEdit is used for TIN construction and editing. ISurface provides surface analysis functions such as contouring, profiling, and volumetrics.

    Triangle, edges, and nodes are the basic elements that comprise a TIN. For advanced TIN editing and analysis you'll need access to these elements and the relationships between them. The TIN sub-system includes TinTriangle, TinEdge, and TinNode objects for this purpose as well as helper objects such as TinElementEnumerators and TinFilters that support iterative processing. The filters control which elements are passed through the enumerators. There's an enumerator for each TIN element type: TinNodeEnumerator, TinEdgeEnumerator, and TinTriangleEnumerator. A variety of filters can be used with the enumerators.

    The available TIN filters are:

    The existing filters provide a lot of capability. Additionally, it's relatively easy to program custom filters. This accomodates the specialized requirements of any application. See the Samples listed below for a link to custom filter examples.

    TinPolyline and TinPolygon helper objects are used to access logical polyline and polygon features in a TIN for the sake of conversion or analysis. A TinPolyline or TinPolygon is discovered dynamically by starting with a seed element (i.e. edge or triangle) and iteratively 'flooding' outward to all coincident elements that share a given property of interest. For example, you can extract polygons representing areas of like slope given a seed triangle for each area and a filter that defines the slope range. These helper objects enable you to construct and access complex entities in a TIN based on any user defined criteria.


    The following samples illustrate several methodologies for manipulating and using TINs and related objects:


    Data transfer

    The data transfer sub-system contains objects for copying and converting data into and out of geodatabases.

    Data conversion

    The two central data converter objects are FeatureDataConverter and GeoDBDataTransfer.

    FeatureDataConverter will be familiar to users of ArcCatalog; the import facilities make extensive use of this coclass.

    GeoDBDataTransfer will also be familiar to users of ArcCatalog; the copy/paste functionality to copy datasets between geodatabases makes use of this class.

    Some other objects and interfaces are useful in support of FeatureDataConverter and GeoDBDataTransfer and perform the following functions:

    The IFeatureDataConverter interface provides methods to convert data between different formats.

    This example shows conversion of a feature class to a new feature class in a given workspace.

    [Visual Basic 6.0]
    Public Sub ConvertFeatureClass(pFeatureClass As IFeatureClass, _
    	pOutWorkspace As IWorkspace)
      ' Get input FeatureClassName and Workspace
      Dim pInFCName As IFeatureClassName
      Dim pDataset As IDataset
      Set pDataset = pFeatureClass
      Set pInFCName = pDataset.FullName
      Dim pInWorkspace As IWorkspace
      Set pInWorkspace = pDataset.Workspace
      ' Set output WorkspaceName
      Set pDataset = pOutWorkspace
      Dim pOutWorkspaceName As IWorkspaceName
      Set pOutWorkspaceName = pDataset.FullName
      ' Set output FeatureClassName
      Dim pOutFCName As IFeatureClassName
      Set pOutFCName = New FeatureClassName
      Dim pDatasetName As IDatasetName
      Set pDatasetName = pOutFCName
      pDatasetName.Name = "NewFeatClass1"
      Set pDatasetName.WorkspaceName = pOutWorkspaceName
      ' Get fields for input feature class and run them through field checker
      Dim pFieldChecker As IFieldChecker
      Dim pFields As IFields
      Set pFields = pFeatureClass.Fields
      Dim pOutFields As IFields
      Set pFieldChecker = New FieldChecker
      pFieldChecker.InputWorkspace = pInWorkspace
      Set pFieldChecker.ValidateWorkspace = pOutWorkspace
      pFieldChecker.Validate pFields, Nothing, pOutFields
      ' Convert the data
      Dim pFeatureDataConverter As IFeatureDataConverter
      Set pFeatureDataConverter = New FeatureDataConverter
      pFeatureDataConverter.ConvertFeatureClass pInFCName, Nothing, _
    	Nothing, pOutFCName, Nothing, pOutFields, "", 100, 0
    End Sub

    The ConvertFeatureDataset method can import whole feature datasets.

    When using ConvertFeatureClass and ConvertFeatureDataset, if you specify Nothing for the OutputGeometryDef parameter, then the spatial reference will be taken from the input data or the destination feature dataset, and default spatial index data will be created. The InputQueryFilter parameter allows you to just import a subset of the input data.

    EnumInvalidObject is a standard enumerator like many others in ArcObjects. It represents a set of objects that failed a data-conversion process.

    The IEnumInvalidObject interface lets you step through the objects that failed conversion and gain access to InvalidObjectInfo.

    InvalidObjectInfo tells you why a particular row or feature could not be loaded.

    The IInvalidObjectInfo interface returns information about an object that could not be loaded. One example of ErrorDescription is: "The coordinates or measures are out of bounds."

    The InvalidObjectID will be -1 unless the source data is in a geodatabase.

    A FieldChecker object is used to validate a Fields collection. It is most often used in conjunction with FeatureDataConverter.

    FieldChecker is particularly useful when you are creating a new feature class based on an existing feature class and the input and output data are in different formats. For example, a shapefile field name of “UID” would be invalid in an Oracle geodatabase since it is a reserved word in that database.

    As well as reporting the problems it finds, FieldChecker also generates a new fields collection with standard fixes for the field name problems. In the previous example, a new field name of “UID_” would be generated. The kinds of errors that the field checker detects are listed by esriFieldNameErrorType.

    When converting to a geodatabase, the field checker will also rename geometry fields to "Shape" and object ID fields to "OBJECTID". No field errors are returned in this situation.

    The IFieldChecker interface validates field names and table names relative to a particular workspace.

    If you do not set ValidateWorkspace and InputWorkspace before validating the fields, then FieldChecker assumes a default set of reserved words and invalid characters. This may cause you to rename fields unnecessarily if the problem does not apply to the data format to which you are converting.

    The ValidateTableName method will check a proposed table name against reserved words and invalid characters. It will not check to see if that table name is already being used in the workspace.

    EnumFieldError is a standard enumerator like many others in ArcObjects. It represents a set of field names that would cause problems in a data-conversion process.

    The IEnumFieldError interface lets you step through the field errors found by the field checker. Each element returned is a FieldError object.

    A FieldError object provides information about a problem with a field.

    The IFieldError interface tells you what kind of error was found and to what field it applies.

    Distributed geodatabase

    The distributed geodatabase objects are for working with check-out information for active check-outs in a geodatabase. It consists of the Replica, ReplicaDataset, and ReplicaDescription objects, which act as specifications for a geodatabase check outs. The ReplicaDescription object is also used for defining data to check-out or extract.

    See the GeodatabaseDistributed library for information about objects to create check outs, and objects for checking in check out database changes.


    The following samples illustrate the use of the distributed geodatabase objects.



    Versioning allows multiple users to edit spatial and tabular data simultaneously in a long transaction environment. Users can directly modify the database without having to extract data or lock features in advance. The object model provides functionality to create and administer versions, register and unregister classes as versioned, detect differences between versions, and reconcile and post versions.

    A VersionedWorkspace is a Workspace that supports multiuser editing and multiple representations of features classes and tables in a relational database system. VersionedWorkspaces support the IVersionedWorkspace interface.

    A list of all versions to which the user has permissions can be retrieved using the Versions property. The versions returned are either owned by the connected user or have public access.

    The DefaultVersion property can be used to retrieve the DEFAULT version of the database. There is always a DEFAULT version owned by the ArcSDE user.

    Versions returns an enumeration of all public versions and those owned by the connected user.

    The FindVersion method can be used to retrieve other versions by name. Version names are case-sensitive and limited to 32 characters. Versioned workspace compression is available using the Compress method. Compressing a VersionedWorkspace will remove those database states not referenced by a version. Only the ArcSDE administrator user can execute the Compress method.

    FindVersion finds a specific version provided its name.

    The IVersion interface is used to manage the properties of a version as well as create new versions. Creating a new version requires an existing version to be the parent of the new version. When the new version is created, the parent and child versions are identical.

    Here is some sample VBA code for updating the Access property of the version associated with the first layer in the map.

    [Visual Basic 6.0]
    Dim pDoc As IMxDocument, pMap As IMap, pFLayer As IFeatureLayer
    Set pDoc = ThisDocument
    Set pMap = pDoc.FocusMap
    If TypeOf pMap.Layer(0) Is IFeatureLayer Then
      Set pFLayer = pMap.Layer(0)
      Dim pDataset As IDataset, pVersion As IVersion
      Set pDataset = pFLayer.FeatureClass
      Set pVersion = pDataset.Workspace
      If pVersion.VersionInfo.IsOwner Then
       pVersion.Access = esriVersionAccessPublic
      End If
    End If

    The IVersionEdit interface is used to reconcile a version with a target version. Once reconciled, the object provides the ability to work with representations of the version prior to start editing, the prereconcile version, the reconcile version, and the common ancestor version. The common ancestor version represents the state of the database when the start editing version was originally created from the reconcile version (at the time when each version was identical).

    You can only post a version that has first been reconciled with any of its ancestor versions. You are not limited to simply reconciling a version with its immediate parent version. Once you have performed the reconcile, the CanPost method will return True. But, if you perform an Undo operation, CanPost will become False.

    CommonAncestorVersion returns the common ancestor version of this version and the reconcile version.

    ConflictClasses returns an enumeration of all classes containing conflicts. ModifiedClasses returns an enumeration of all the classes modified in the version.

    PreReconcileVersion returns the version prior to reconciliation. ReconcileVersion returns the version against which this version is currently reconciling.

    StartEditingVersion returns the version before any edits were made. CanPost returns a Boolean if the version can be posted to the reconcile version.

    Post applies the changes in the current version to the reconciled version. Reconcile merges the current edit version with a target version.

    The example below shows how an application can reconcile the current version with the DEFAULT version. If conflicts are detected, the user will have to interactively perform conflict resolution. If not, then the application can verify that it can perform the post operation, and then it can perform the post.

    [Visual Basic 6.0]
    Dim pVersionEdit As IVersionEdit
    Set pVersionEdit = pCurrentVersion
    Dim pconflicts As Boolean
    pconflicts = pVersionEdit.Reconcile("SDE.DEFAULT")
    If pconflicts Is True Then
      MsgBox _
    "Conflicts have been detected, review and resolve prior to posting."
      MsgBox "The version has been successful reconciled with the " & _
    "target version, no conflicts were detected."
    End If
    ' Handle conflicts if necessary
    If pVersionEdit.CanPost = True Then
    pVersionEdit.Post "SDE.DEFAULT"

    Reconcile2 reconciles the current edit version with the specified target version. The target version must be an ancestor of the current version, or an error will be returned. The target version name passed in is case-sensitive and should take the form {owner}.{version_name}—for example, SDE.DEFAULT. The boolean argument specifies if locks should be obtained or not—True acquires the lock, while False does not acquire the locks. If the locks are not acquired, the version is able to be reconciled in parallel when other versions are currently being reconciled. You may desire this functionality when there is no intention of posting the version after the reconcile process. If the intention is to "post" the version after performing the reconcile, it is strongly recommended that the locks are acquired.

    Reconcile3 reconciles the current edit version with the specified target version. The target version must be an ancestor of the current version or an error will be returned. The target version name passed in is case-sensitive and should take the form {owner}.{version_name}—for example, SDE.DEFAULT. The first boolean argument specifies if locks should be obtained or not—True acquires the lock, while False does not acquire the locks. The second boolean argument specifies if the reconcile process should abort the reconcile if conflicts are detected for any class. Ideally, the second boolean is only set to true when performing a reconcile in a batch type environment where you do not have the ability to interactively resolve conflicts.

    A conflict class enumerator returns all classes containing conflicts after performing a reconcile. Objects of this type are created through the IVersionEdit::ConflictClasses property. The enumeration contains a set of IConflictClass objects that specify the conflict classes that were found during the execution of IVersionEdit::Reconcile.

    The VersionInfo interface is a read-only collection of methods used to obtain the different properties of a version. If you need to set the properties of a version, use the IVersion interface.

    The DifferenceCursor returns a cursor of object IDs and IRows based on the difference type used with IVersionedTable.

    The set of object IDs returned is dependent on the difference type category. For example, if the difference type DeleteNoChange is applied, the cursor will be empty for the table that has deleted the rows. In this case, the application will have to change the table the version references in the IVersionedTable interface.

    The IVersionedObject and IVersionedObject2 interfaces are used to register and unregister feature datasets and classes as versioned. They will also return the current version that a dataset or table references.

    Using the RegisterAsVersioned method on a feature dataset will register all classes in the dataset as versioned or, alternatively, one could RegisterAsVersioned an individual feature class. Only the feature dataset or feature class owner can register an object as versioned. The process will create two additional tables in the database.

    The IsRegisterAsVersioned method returns a boolean if the dataset or class is registered in the database as versioned. When called on a feature dataset, if any class is not registered as versioned, False will be returned.

    The Version method returns the current version the object references. This ensures that the application is working with the correct version of the database.

    RegisterAsVersioned provides the ability to register and unregister a feature dataset as versioned. A true value will register the dataset or class as versioned, and a false value will unregister the dataset or class as versioned.

    HasUncompressedEdits returns whether or not there are edits that have not yet been compressed.

    A table in a versioned workspace implements two additional interfaces, IConflictClass and IVersionedTable.

    IConflictClass is obtained from the IEnumConflictClass enumeration. It is provided as a mechanism to work with the conflicting rows from each conflict class after performing a reconcile. If IVersionEdit::Reconcile has not been called prior to this, the classes will not be available.

    The DeleteUpdates method returns an ISelectionSet of all the object IDs of rows that have been deleted in the edit version and updated in the target reconcile version. If no conflicts were detected, the selection set is null. HasConflicts returns a boolean if the reconcile detects conflicts.

    The UpdateDeletes method returns an ISelectionSet of all the object IDs of rows that have been updated in the edit version and deleted in the target reconcile version. If no conflicts were detected, the selection set is null.

    The UpdateUpdate method returns an ISelectionSet of all the object IDs of rows that have been updated in the edit version and updated in the target reconcile version. If no conflicts were detected, the selection set is null.

    The IVersionedTable interface can be used to detect the different conflict categories without first performing an IVersionEdit::Reconcile. By specifying the appropriate esriDifferenceType, such as TypeDeleteUpdate or TypeInsert, an IDifferenceCursor is returned with a set of OIDs and IRows for differences.

    Differences returns a cursor that can be used to retrieve the rows by the difference type.


    The following samples illustrate the use of the Versioning objects.


    Name objects

    A Name object is a persistable software object that identifies and locates a geodatabase object, such as a dataset or a workspace, or a map object such as a layer.

    A Name object supports an Open method that allows the client to get an instance of the actual object (for example, the dataset or workspace) given the name object. A name object thus acts as a moniker that supports binding to the named object.

    The geodatabase supports methods on workspaces that hand out name objects that can be used by browsing clients to display the names of datasets in the workspace and to instantiate any specific dataset. Name objects may also carry properties that describe the object being named. A browsing client can use these properties to display additional information about the object being named. A Name object may also support methods to access metadata, or methods to change permissions on the actual object. In these cases, a name object can be used as a lightweight surrogate of the actual object until such time as further properties of the object are needed or additional methods on the object need to be called.

    Name objects are cocreatable and can also be used to specify datasets that are yet to be created, for example, the output dataset to be created by a geoprocessing operation. There are several kinds of Name objects, for example, workspace, table, feature class, feature dataset, raster, and relationship class name objects.

    A workspace name is a key component of any dataset name for datasets in the workspace. The IWorkspaceName interface lets you access the properties of a workspace name.

    To create a new workspace name, you must set the WorkspaceFactoryProgID property followed by either PathName or ConnectionProperties.

    This example creates a new workspace name for a personal geodatabase.

    [Visual Basic 6.0]
    Dim pWorkspaceName As IWorkspaceName
    Set pWorkspaceName = New WorkspaceName
    pWorkspaceName.WorkspaceFactoryProgID =
    pWorkspaceName.PathName = "D:\data\geodatabases\Usa.mdb"

    The workspace factories for all the workspaces are in the various DataSources libraries. At the end of the example above, the name object could be referring to an existing workspace or one that is to be created. If the workspace already exists, it can be opened with IName::Open—effectively, this procedure is equivalent to opening a workspace using Open or OpenFromFile on IWorkspaceFactory. If the workspace does not exist and is to be created, use IWorkspaceFactory::Create.

    In some circumstances, you may already have a full workspace object but require a workspace name instead. The code below shows you how.

    [Visual Basic 6.0]
    Dim pWorkspaceName As IWorkspaceName
    Dim pDataset As IDataset
    Set pDataset = pWorkspace ' Workspaces implement IDataset
    Set pWorkspaceName = pDataset.FullName

    The Type, Category, WorkspaceFactoryProgID, and BrowseName properties all return information on the workspace.

    DatasetName is an abstract class that covers Name objects for datasets in a workspace. DatasetName objects identify and locate datasets within a workspace. In addition, they may carry additional properties that describe the named dataset.

    DatasetName objects support methods to access metadata for the named object (via the optional IMetadata interface) and to manage privileges for the dataset (via the ISQLPrivileges interface). The DatasetName object for any existing dataset can be obtained by reading the IDataset::FullName property. DatasetName objects may also be created to specify new datasets that are to be created by some operation.

    The IDatasetName interface provides access to the basic properties of a dataset name object.

    The Name property returns the identifier for the dataset within the context of its workspace. Note that the value of the name property of the dataset name object (IDatasetName::Name) is the same as the value of the name property for the dataset (IDataset::Name).

    The WorkspaceName property returns the workspace name object for the workspace containing the dataset being specified by this dataset name object.

    You can use the IDataset::FullName interface to get a dataset name object from the actual dataset object.

    This example goes from a feature class to a feature class name.

    [Visual Basic 6.0]
    Dim pFeatureClassName As IFeatureClassName
    Dim pDataset As IDataset
    Set pDataset = pFeatureclass
    Set pFeatureClassName = pDataset.FullName

    A dataset name can also refer to a dataset that does not yet exist. This is useful when creating new data, for example, with feature data converters.

    This code makes a new feature class name—the key properties to set are Name and WorkspaceName.

    [Visual Basic 6.0]
    Dim pWorkspaceName As IWorkspaceName
    Set pWorkspaceName = New WorkspaceName
    pWorkspaceName.WorkspaceFactoryProgID =
    pWorkspaceName.PathName = "D:\data\geodatabases\Usa.mdb"
    Dim pFeatureClassName As IFeatureClassName
    Set pFeatureClassName = New FeatureClassName
    Dim pDatasetName As IDatasetName
    Set pDatasetName = pFeatureClassName
    pDatasetName.Name = "Land_use"
    Set pDatasetName.WorkspaceName = pWorkspaceName

    The ISQLPrivilege optional interface provides information about the permissions you have on a database object; it also provides information about how to change the permissions for other users. It only applies to those datasets that are stored within a multiuser SQL environment, most typically an ArcSDE geodatabase. ISQLPrivilege controls access to database objects.

    The esriSQLPrivilege enumeration defines values that can be used with ISQLPrivilege.

    The values may be bitwise OR’d together if more than one privilege applies (note that this is equal to summing the integer values). For example, if the SQLPrivileges property returns a value of 9, this would mean that you have select and delete permission on the dataset but not insert or update. A value of 15 indicates full privileges.

    The following example grants select and update privileges to a user called Scott. The dataset name could be a feature dataset, in which case Scott would receive the privileges on all the contents of the feature dataset.

    [Visual Basic 6.0]
    If TypeOf pDatasetName Is ISQLPrivilege Then
      Dim pSQLPriv As ISQLPrivilege
      Set pSQLPriv = pDatasetName
      pSQLPriv.Grant "Scott", _
       esriSelectPrivilege + esriUpdatePrivilege, False
    End If

    The following are types of DatasetName objects in the geodatabase:


    The following samples illustrate the use of the name objects.


    Relationship query table

    The relationship query table sub-system contains objects for working with on-the-fly table joins (RelQueryTable) and memory relationships (MemoryRelationshipClass).

    A MemoryRelationshipClassFactory is an object that manages the memory relationship classes that exist in an application. You must use either a MemoryRelationshipClassFactory or a MemoryRelationshipClass- Name object to create new memory relationship classes.

    Like workspace factory objects, a MemoryRelationshipClassFactory is a singleton object. This means that you can have only one instance of this object in a process.

    The IMemoryRelationshipClassFactory interface provides an Open method that creates a new MemoryRelationshipClass.

    A MemoryRelationshipClass is a simple (noncomposite), nonattributed RelationshipClass that does not support relationship rules.

    A MemoryRelationshipClass inherits from a RelationshipClass and, although it implements the same interfaces, not all properties and methods are supported. The following section reviews each of these interfaces and describes which properties and methods behave differently or are not supported with memory relationship classes.

    The IRelationshipClass interface provides information on how the relationship class was defined, functionality to create and delete individual relationships, and methods to find related objects.

    The properties and methods of IRelationshipClass not listed in the table behave the same way with memory relationship classes as they do with other relationship classes.

    The following code example creates a MemoryRelationshipClass between the us_states feature class and the us_counties feature class. It then uses the MemoryRelationshipClass to print the counties that appear in the State of California.

    [Visual Basic 6.0]
    Dim pRelationshipClass As IRelationshipClass
    Dim pMemRelationshipClassFact As IMemoryRelationshipClassFactory
    Set pMemRelationshipClassFact = New MemoryRelationshipClassFactory
    Set pRelationshipClass = pMemRelationshipClassFact.Open("test", _
    	pFOBClass, "state_fips", pFOBClass2, "state_fips", "forward", _
    	"backward", esriRelCardinalityOneToMany)
    Dim pQFilter As IQueryFilter
    Set pQFilter = New QueryFilter
    pQFilter.WhereClause = """STATE_NAME"" = 'California'"
    Dim pFeatureClass As IFeatureClass
    Dim pFCursor As IFeatureCursor
    Dim pFeature As IFeature
    Set pFeatureClass = pFOBClass
    Set pFCursor = pFeatureClass.Search(pQFilter, True)
    Set pFeature = pFCursor.NextFeature
    Dim pRelateSet As ISet
    Dim pRowBuff As IRowBuffer
    Set pRelateSet = pRelationshipClass.GetObjectsRelatedToObject(pFeature)
    Set pRowBuff = pRelateSet.Next
    Do While Not pRowBuff Is Nothing
      Debug.Print pRowBuff.Value(2)
      Set pRowBuff = pRelateSet.Next

    A RelQueryTableFactory is an object that manages the RelQueryTables in the application. You must use either a RelQueryTableFactory or a RelQueryTableName object to create new RelQueryTables.

    Like the workspace factory objects, a RelQueryTableFactory is a singleton object. This means that you can only have one instance of this object in a process.

    The IRelQueryTableFactory interface provides an Open method to define the data a RelQueryTable represents and how that data is accessed. The following table describes in more detail the meaning of each of the input parameters.

    A RelationshipClass is used when creating a RelQueryTable to specify the tables involved and the fields on which the join is based. The RelationshipClass can be stored in a geodatabase or created in memory. Memory relationship classes can include tables that belong to different data sources. Therefore, a RelQueryTable can join tables from different data sources.

    A RelQueryTable includes a source table or feature class and a destination table or feature class. If you step through a cursor opened from a RelQueryTable, each row includes the columns from both input tables. The fields from the source appear on the left, while the fields from the destination appear on the right. Each row from the table is composed of the primary and foreign keys from IRelationshipClass to produce a single row.

    Shapes can only be retrieved from the source table. If the destination table has a geometry field, it will not be included in the RelQueryTable.

    When you perform a join in ArcMap, a RelQueryTable object is created and used as the table or layer’s data source for all display purposes. In ArcMap, you can use the IDisplayTable::DisplayTable property to get a joined table or layer’s RelQueryTable.

    Since a RelQueryTable implements IObjectClass and IFeatureClass and inherits from Table, it can be treated like any other Table or FeatureClass. The IFeatureClass interface is implemented only when the source is a FeatureClass. A RelQueryTable cursor is read-only, so you must edit the source and destination to change the data.

    A RelQueryTable is designed to work with relationships that have one-toone or many-to-one cardinality. If the cardinality is one-to-many, a row from the source will be associated with the first matching row in the destination—any other matching rows are ignored. A RelationshipClass with a many-to-many cardinality is not supported and will cause an error. If the relationship has a cardinality of one-to-many or many-tomany, use RelationshipClass objects to access the data. If the cardinality is really one-to-one but the Relationship is defined as one-to-many, the RelQueryTable will still process correctly.

    A RelQueryTable will have an ObjectID if the source has an ObjectID. When initialized, the RelQueryTable uses the values from the source’s ObjectID field to define its ObjectIDs. If the source is a nonObjectID object class, the RelQueryTable can still access the data, but there will be limitations, such as an inability to select rows.

    By definition, ObjectIDs must be unique. The reason relationships with one-to-many cardinalities match one row from the source to only one row in the destination is to prevent repeating ObjectIDs in the RelQueryTable. Repeating ObjectIDs will cause many objects, such as SelectionSets and table windows, to behave incorrectly.

    The IRelQueryTableManage interface provides an Init method to define what data a RelQueryTable represents and how that data is accessed.

    The following example uses a MemoryRelationshipClass and a RelQueryTable to join country demographic data to a countries feature class. The field names are then printed:

    [Visual Basic 6.0]
    Dim pMemRelClassFact As IMemoryRelationshipClassFactory
    Set pMemRelClassFact = New MemoryRelationshipClassFactory
    Dim pRelClass As IRelationshipClass
    Set pRelClass = pMemRelClassFact.Open("Country_Demog", _
      FeatureObjectClass, "fips_code", pTableObjectClass, "fips_code", _
      "forward", "backward", esriRelCardinalityOneToMany)
    Dim pRelQueryTableFact As IRelQueryTableFactory
    Dim pRelQueryTab As ITable
    Set pRelQueryTableFact = New RelQueryTableFactory
    Set pRelQueryTab = pRelQueryTableFact.Open(pRelClass, True, Nothing, _
      Nothing, "", True, True)
    Dim pCursor As ICursor
    Set pCursor = pRelQueryTab.Search(Nothing, True)
    Dim pField As IField
    Dim pFields As IFields
    Dim intI As Integer, intJ As Integer
    Set pFields = pCursor.Fields
    intI = pFields.FieldCount - 1
    For intJ = 0 To intI
      Set pField = pFields.Field(intJ)
      Debug.Print pField.Name
    Next intJ

    The IRelQueryTable interface allows you to get the source and destination as well as the RelationshipClass or MemoryRelationshipClass used to define the RelQueryTable. The source and destination can be tables, feature classes, or even other RelQueryTables.

    For example, if you wanted to join two tables to a feature class, you would first create a RelQueryTableA to join one of the tables to the feature class. You would then create a RelQueryTableB to join the second table to RelQueryTableA. RelQueryTableA would be the source for RelQueryTableB. The diagram below illustrates how this works.

    The following code example shows how to step through a RelQueryTable’s source and destination and prints the names of the joined tables and feature classes. This list is similar to the list of joined tables and feature classes that you see in the Joins and Relates tab in the Layer or Table Properties dialog boxes in ArcMap.

    [Visual Basic 6.0]
    Dim pFeatureLayer As IFeatureLayer
    Set pFeatureLayer = GetLayer(0)
    Dim pTable As ITable, pDisplayTable As IDisplayTable
    Set pDisplayTable = pFeatureLayer
    Set pTable = pDisplayTable.DisplayTable
    Dim pRelQueryTable As IRelQueryTable, pDestTable As ITable
    Dim pDataset As IDataset, sOut As String
    Do While TypeOf pTable Is IRelQueryTable
      Set pRelQueryTable = pTable
      Set pDestTable = pRelQueryTable.DestinationTable
      Set pDataset = pDestTable
      sOut = sOut & pDataset.Name & vbNewLine
      Set pTable = pRelQueryTable.SourceTable
    MsgBox "The joined tables include:" & vbNewLine & sOut

    A RelQueryCursor is created when you open a cursor on a RelQueryTable. You can use methods such as Search from ITable and IFeatureClass to open the cursor. Since it inherits from cursor, it implements ICursor and will implement IFeatureCursor if the RelQueryTable has geometry.

    A RelQueryCursor is read-only; therefore, performing edits using the IRow::Delete and IRow::Store methods is not supported. Also, trying to open an insert or update cursor will result in an error since there is no insert or update RelQueryCursor.

    The ICursor interface provides access to a set of rows.

    The table above outlines how the properties and methods of ICursor behave when used on a RelQueryCursor.

    A RelQueryRow can be obtained from a cursor (ICursor::NextRow) or methods, such as ITable::GetRow. The ITable::CreateRow method is not supported and will return an error if used.

    A MemoryRelationshipClassName object is a representation of a MemoryRelationshipClass object. A MemoryRelationshipClassName can be used to create new, work with existing, or persist MemoryRelationshipClasses.

    The IMemoryRelationshipClassName interface contains properties that correspond to the parameters used with the IMemoryRelationshipClassFactory::Open method. These include the Origin and Destination tables, the fields, and the forward and backward pathnames.

    The only parameters from the IMemoryRelationshipClassFactory::Open method that don’t have a corresponding property in IMemoryRelationshipClassName are the name and the cardinality. The name can be set using the IDatasetName interface, and the cardinality can be set using the IRelationshipClassName interface. Both of these interfaces are inherited by MemoryRelationshipClassName.

    When creating a new MemoryRelationshipClass using a MemoryRelationshipClassName object, only the properties described above need to be set.

    The example below creates a new MemoryRelationshipClass from a MemoryRelationshipClassName.

    [Visual Basic 6.0]
    Dim pMemoryRelationshipClassName As IMemoryRelationshipClassName
    Set pMemoryRelationshipClassName = New MemoryRelationshipClassName
    With pMemoryRelationshipClassName
      Set .OriginName = pOriginName
      Set .DestinationName = pDestinationName
      .OriginPrimaryKey = "STATE_FIPS"
      .OriginForeignKey = "STATE_FIPS"
      .ForwardPathLabel = "forward"
      .BackwardPathLabel = "backward"
    End With
    Dim pRelationshipClassName As IRelationshipClassName
    Set pRelationshipClassName = pMemoryRelationshipClassName
    pRelationshipClassName.Cardinality = esriRelCardinalityOneToOne
    Dim pDatasetName As IDatasetName
    Set pDatasetName = pRelationshipClassName
    pDatasetName.Name = "New_MemRC"
    Dim pName As IName
    Set pName = pRelationshipClassName
    Dim pMemoryRelationshipClass As IMemoryRelationshipClass
    Set pMemoryRelationshipClass = pName.Open
    Dim pRelationshipClassCollectionEdit as IRelationshipClassCollectionEdit
    Dim pRelationshipClassCollectionEdit = pFeatureLayer
    pRelationshipClassCollectionEdit.AddRelationshipClass _

    A RelQueryTableName is a representation of a RelQueryTable. A RelQueryTableName can be used to create new, work with existing, or persist RelQueryTables.

    The IRelQueryTableName interface contains properties that correspond to the parameters used with the IRelQueryTableFactory::Open method described above.

    The following code shows how to create a new RelQueryTable from a RelQueryTableName object. In this example, the MemoryRelationshipClassName has already been created.

    [Visual Basic 6.0]
    Dim pRelQueryTableName As IRelQueryTableName
    Set pRelQueryTableName = New RelQueryTableName
    With pRelQueryTableName
      Set .RelationshipClassName = pMemoryRelationshipClassName
      .ForwardDirection = True
      .DoNotPushJoinToDB = True
      .TargetColumns = ""
      .LeftOuterJoin = True
      Set .SrcQueryFilter = Nothing
      Set .SrcSelectionSet = Nothing
    End With
    Dim pName As IName
    Set pName = pRelQueryTableName
    Dim pRelQueryTable As IRelQueryTable
    Set pRelQueryTable = pName.Open

    The IDataset::FullName method can be used on an existing RelQueryTable object to get a corresponding RelQueryTableName object.



    The raster sub-system contains objects for accessing and working with rasters, raster datasets, and raster catalogs. These objects are used for accessing both file-based raster data as well as raster data stored in a geodatabase.

    Raster Data Access Objects

    Raster data consists of a rectangular array of equally spaced cells, which taken as a whole represent thematic, spectral, or picture data. Raster data can represent everything from qualities of a land surface, such as elevation or vegetation, to satellite images, scanned maps, and photographs.

    ArcGIS supports file-based raster data such as GRID, TIFF, ERDAS® IMAGINE®, JPEG, and so on. It also supports raster data in geodatabase including personal geodatabase and enterprise geodatabase. Regardless the various data sources, two data types are used to represent raster data: raster dataset and raster catalog. A raster dataset represents an existing dataset stored on disk in a particular raster format or in a geodatabase, while a raster catalog manages a collection of raster datasets as one entity - a special feature class in geodatabase. A raster dataset consists one or more raster bands. A raster dataset may contain pyramids, statistics, or a colormap, which are used to provide fast access and better display, and it may also contain a raster table.

    For raster data, a Workspace is a raster workspace (or a directory) for file based raster data, an Access workspace for raster data in a personal geodatabase, or a database workspace for raster data in an enterprise geodatabase.

    To access raster data, you need to open a Workspace. A Workspace can not be co-created, it must be initiated from workspace factories. The RasterWorkspaceFactory is used to initialize a raster workspace, the AccessWorkspaceFactory is used to initialize an Access workspace, and the SdeWorkspaceFactory is used to initialize a database workspace.

    This function opens a raster workspace from a given directory:

    [Visual Basic 6.0]
    Public Function OpenRasterWorkspace(sPath As String) As IRasterWorkspace
      Dim pWKSF As IWorkspaceFactory
      Set pWKSF = New RasterWorkspaceFactory
      Dim pRasterWs As IRasterWorkspace
      Set pRasterWs = pWKSF.OpenFromFile(sPath, 0)
      Set OpenRasterWorkspace = pRasterWs
    End Function

    The following function opens an Access workspace:

    [Visual Basic 6.0]
    Public Function OpenAccessWorkspace (sPath As String) As IRasterWorkspaceEx
      Dim pWsFact As IWorkspaceFactory
      Set pWsFact = New AccessWorkspaceFactory
      Dim pPropset As IPropertySet
      Set pPropset = New PropertySet
      pPropset.SetProperty "database", sPath
      Set OpenAccessWorkspace = pWsFact.Open(pPropset, 0)
    End Function

    The following function opens a database workspace by passing the SDE connection information:

    [Visual Basic 6.0]
    Public Function OpenSDERasterWorkspace(sServer As String, sInstance As String, sDB As String, sUser As String,sPasswd As String,sVersion As String) As IRasterWorkspaceEx
      Dim pWKSF As IWorkspaceFactory
      Set pWKSF = New SDEWorkspaceFactory
      Dim pConn As IpropertySet
      Set pConn = New PropertySet
      With pConn
        .SetProperty "Server", sServer
        .SetProperty "Instance", sInstance
        .SetProperty "Database", sDB
        .SetProperty "User", sUser
        .SetProperty "Password", sPasswd
        .SetProperty "Version", sVersion
      End With
      Set OpenSDERasterWorkspace = pWKSF.Open(pConn,0)
    End Function

    The three interfaces on Workspace object provide access to RasterDataset and RasterCatalog objects. IRasterWorkspace and IRasterWorkspace2 are used to open and create a file based RasterDataset.

    The code below opens a Imagine file in a given directory:

    [Visual Basic 6.0]
    Dim pRasterDataset as IRasterdataset
    Dim pRasterWs as IRasterWorkspace2
    Set pRasterWs = OpenRasterWorkspace("D:\data")
    Set pRasterDataset = pRasterWs.OpenRasterDataset("airphoto.img",0)

    To create a file based raster dataset, the origin, width, and height of the raster dataset must be specified besides other required parameters and a raster dataset with the specified dimension and default pixel values will be created. The default pixel values of the raster dataset can be modified to what you want by writing pixel blocks to the dataset.

    [Visual Basic 6.0]
    Dim pRasterDataset as IRasterdataset
    Dim pRasterWs as IRasterWorkspace2
    Set pRasterWs = OpenRasterWorkspace("D:\data")
    'The origin is the lower left corner of the dataset in map space
    Dim pPoint As IPoint
    Set pPoint = New Point
    pPoint.PutCoords 0, 0
    Set pRasterDataset = pRasterWs.CreateRasterDataset("MyImage.img", "IMAGINE Image", pPoint,200, 100, 1, 1, 1, PT_UCHAR, New UnknownCoordinateSystem, True)

    IRasterWorkspaceEx provides access to RasterDataset and RasterCatalog. IRasterWorkspaceEx through an Access workspace accesses a file based RasterDataset and a RasterCatalog in personal geodatabase. IRasterWorkspaceEx through a database workspace accesses a database RasterDataset and a RasterCatalog in an enterprise geodatabase.

    This code opens a raster dataset and a raster catalog from geodatabase.

    [Visual Basic 6.0]
    Dim pWorkspace as IRasterWorkspaceEx
    Dim pRasterDataset as IRasterDataset
    Dim pRasterCatalog as IrasterCatalog
    'From a personal geodatabase.
    Set pWorkspace = OpenAccessWorkspace("D:\data\images.mdb")
    'Or from an enterprise geodatabase
    Set pWorkspace =  OpenSDEWorkspace("myserver","5151","raster", "raster","raster","SDE.default")
    Set pRasterDataset = pWorkspace.OpenRasterDataset("airphoto")
    Set pRasterCatalog = pWorkspace.OpenRasterCatalog("RedLandImages")

    Creating a raster dataset in geodatabase creates an empty raster dataset with no dimension, which is basically a placeholder for some attribute of this raster dataset, such as the number of bands, pixel type, RASTER field properties, and GEOMETRY field properties. Once the empty raster dataset is created, raster pixels can be appended from other raster data by mosaicking.

    The code below creates a raster dataset in geodatabase.

    [Visual Basic 6.0]
    Dim pWorkspace As IRasterWorkspaceEx
    Set pWorkspace = OpenSDEWorkspace ("myserver","5151","raster", "raster","raster","SDE.default")
    ' Create a RasterStorageDef object for storage parameters, define compression and use default for other parameters
    Dim pStorageDef As IRasterStorageDef
    Set pStorageDef = New RasterStorageDef
    pStorageDef.CompressionType = esriRasterSdeCompressionTypeJPEG2000
    ' Create a RasterDef object for the RASTER field
    Dim pRasterDef As IRasterDef
    Set pRasterDef = New RasterDef
    Set pRasterDef.SpatialReference = New UnknownCoordinateSystem
    ' Create a GeometryDef object for the GEOMETRY field
    Dim pGeoDef As IGeometryDef
    Set pGeoDef = New GeometryDef
    Set pGeoDef.SpatialReference = New UnknownCoordinateSystem
    Dim pSDERasterDs As IRasterDataset
    Set pSDERasterDs = pWorkspace .CreateRasterDataset("mydataset", 1, PT_UCHAR, pStorageDef, "defaults", pRasterDef, pGeoDef)

    Raster datasets

    RasterDataset object represents a raster dataset stored in file system or in a geodatabase. A RasterDataset is composed of one or more persistent raster bands. The RasterDataset object performs basic dataset management functions, such as copy, rename, and delete. It can also be used to examine dataset properties including raster format, extent, spatial reference, and number of bands, etc.

    The RasterDataset can be used to change some of the properties of the dataset. For example, RasterDataset can be used to change the spatial reference associated with the dataset, to manipulate the colormap of the raster dataset, to build pyramids (reduced-resolution datasets) which improve display performance for large raster datasets, and to build statistics which enhances raster renderering. RasterDataset object can merge pixels from another raster dataset to itself.

    The following code snippet, assuming that a pRaster (IRaster) and pColormap (IRasterColormap) have been created, alters dataset's colormap and mosaic pRaster to the raster dataset.

    [Visual Basic 6.0]
    Dim pRasterDatasetEdit as IRasterDatasetEdit
    Set pRasterDatasetEdit = pRasterDataset
    'Alter colormap
    PRastereDatasetEdit.AlterColormap pColormap
    'Mosaic pixels from pRaster to the dataset
    pRasterDatasetEdit.Mosaic pRaster, 0.5

    A RasterDataset can be saved to anther format using ISaveAs.

    The code snippet below saves a raster dataset to an IMAGINE format as well as to a geodatabase, assuming pRasterWs is a raster workspace and pWorkspace is an Access workspace or a database workspace.

    [Visual Basic 6.0]
    Dim pSaveAs as ISaveAs
    Set pSaveAs = pRasterDataset
    pSaveAs.SaveAs "MyImage.img", pRasterWs, "IMAGINE Image"
    pSaveAs.SaveAs "MyRaster", pWorkspace, "SDR"

    RasterDataset supports IRasterBandColoection interface, but adding or removing bands has no effect on the RasterDataset. The IRasterBandColoection::SaveAs plays the same role as ISaveAs::SaveAs.

    RasterDataset object can be used to initiate a Raster or a RasterBand objects representing other aspect of the data.

    This code snippet returns the first raster band from a raster dataset:

    [Visual Basic 6.0]
    Dim pBandCol As IRasterBandCollection
    Dim pRasterBand As IRasterBand
    pBandCol = pRasterDataset
    Set pRasterBand = pBandCol.Item(0)

    Two methods can be used to create a Raster object from a RasterDataset. CreateFullRaster method creates a Raster with all the properties from the raster dataset, such as number of bands, width and height of the raster dataset; while CreateDefaultRaster method creates a Raster that has a square cell size and contains only three raster bands if the dataset has more than three bands. The three bands are the default bands used in raster RGB renderer and are determined by the settings for default raster behavior made on the RasterDefaultsEnv object in the Carto library.

    [Visual Basic 6.0]
    Dim pRaster As IRaster
    Set pRaster = pRasterDataset::CreateDefaultRaster
    Dim pRasterDataset2 As IRasterDataset2
    Set pRasterDataset2 = pRasterDataset
    Set pRaster = pRasterDataset2.CreateFullRaster

    IRasterWorkspace interface and IRasterWorkspaceEx interface through Access workspace create a file based RasterDataset; while IRasterWorkspaceEx interface through database workspace creates a database RasterDataset. A file based RasterDataset and database RasterDataset work the same way except on a few interfaces. For example, ITemporyDataset and IWorldFileExport interfaces are not supported by a database RasterDataset and IRasterPyramid2 interface is not supported by a file base RasterDataset.

    Besides accessing through a workspace, RasterDataset may also be retrieved from a band in the dataset using the RasterDataset property. To access the RasterDataset from a Raster object, first access a band from the Raster, then obtain a reference to the dataset from the band.

    This technique is shown here:

    [Visual Basic 6.0]
    ‘QI IRasterBandCollection from the Raster object
    Dim pBandCol as IRasterBandCollection
    Set pBandCol = pRaster
    'Get the first band from the Raster
    Dim pRasterBand as IRasterBand
    Set pRasterBand = pBandCol.Item(0)
    'Get the Raster’s dataset from the band
    Dim pRasterDataset as IRasterDataset
    Set pRasterDataset = pRasterBand.RasterDataset

    Raster bands

    RasterBand object represents an existing band of a raster dataset. This band may be the only band in a single-band raster dataset or one band in a multiband raster dataset. The RasterBand may be accessed from either the Raster or the RasterDataset but, regardless of whether it is derived from the static RasterDataset or the transient Raster, the RasterBand always represents a static band of raster data.

    The following code shows how to access a RasterBand from either a Raster or a RasterDataset object.

    [Visual Basic 6.0]
    Dim pBandCol as IRasterBandCollection
    Set pBandCol = pRasterPtr 'May be a Raster or a RasterDataset
    ' Get the first band of the raster
    Dim pRasterBand as IRasterBand
    Set pRasterBand = pBandCol.Item(0)

    A raster band accessed from a file based RasterDataset is file based RasterBand and a raster band accessed from a database RasterDataset is a database RasterBand. You can see, from the object diagram, that some interfaces are only supported by a file based RasterBand but not by a database RasterBand.

    A raster band contains pixel values in the band. It may also contain statistics, a colormap, a histogram, or a table, which are accessible through the RasterBand.

    The code snippet below access a raster colormap.

    [Visual Basic 6.0]
    Dim pColormap As IRasterColormap
    Dim HasColormap As Boolean
    HasColormap = pRasterBand.HasColormap
    If HasColormap = True Then Set pColormap = pRasterBand.Colormap

    The RasterBand supports IRawPixel interface which allows to read and write pixels directly to the band. For a file base RasterBand, it is recommended to use AcquireCache method before writing pixel blocks, this can prevent unnecessary pyramid building and enhance performance. A file based RasterBand also supports IRasterTransTransition interfaces which can be used to manage the transaction of editing pixels.


    Raster object, in contrast to the static RasterDataset and RasterBand objects, is transient in nature and can be modified without affecting the source data. This allows the raster to represent what you want, as you may specify a projection, extent, and cell size into which the input data will be transformed. This makes the raster quite useful for performing display or analysis in a coordinate system different from that which is stored in the raster dataset on disk.

    Because of the transient nature of the raster, any modifications that are made to this object will be lost when the object is released. Although the Raster object is always transient in nature, it must be associated with one or more raster bands, which provide a source for data to be read through the raster. As such, the Raster is most easily understood as a vehicle to provide resampling, projection, and data type conversion from one or more raster bands to a desired output coordinate system. The modified Raster can be persisted to another raster dataset on disk or in a geodatabase using ISaveAs or IRasterBandCollection interface.

    IRasterProps is an important interface which is used to control the properties of the Raster, such as extent, width, height, spatial reference, pixel type, NoData value etc.

    You can get the cell size of a Raster. However, setting a cell size to a Raster should be done by adjusting width, height, and the extent of the Raster. If the height and/or width are changed, the cell size of the Raster will be re-calculated by using the new height and width to divide the current raster extent. In this case, it will most likely result in a Raster with non-square cell size. You can control to get a Raster with square cell size by specifying a pre-calculated height and width

    The NoData value of a Raster is represented as an array of values. This variant array of values has the pixel type of the Raster and contains one NoData value for each band. This allows the different bands in the Raster to contain a different NoData value. If there is no NoData value in the band, the value in the corresponding member of the array will be empty.

    Resampling sometime occurs when the properties of Raster are changed. The resampling method used when reading can be set using the ResampleMethod on the IRaster interface.

    The following code sets a new spatial reference (pNewSpatialReference) to the Raster and persists to a file, assuming pRaster is obtained.

    [Visual Basic 6.0]
    Dim pRasterProps as IRasterProps
    Set pRasterProps = pRaster
    pRaster.ResampleMethod = RSP_BilinearInterpolation
    pRasterProps.SpatialReference = pNewSpatialReference
    Dim pSaveAs as  ISaveAs
    Set pSaveAs = pRaster
    pSaveAs.SaveAs "MyRaster", pRasterWs, "GRID"

    Raster object can create PixelBlock and pixel value of the raster can be modified by a pixel filter using IPixelFilterOperation and persists to a raster dataset using SaveAs. The pixel values of the Raster can also be modified and written directly to the raster dataset using IRasterEdit interface.

    A Raster can be displayed using RasterLayer object, which is an object in the Carto library.

    Raster may be created from a RasterDataset,which is described in the previous section, and may be obtained from a RasterLayer, an object in the Carto library.

    [Visual Basic 6.0]
    Set pRaster = pRasterLayer.Raster

    The Raster may also be cocreated. Cocreating a new Raster results in an empty raster that is not useful until one or more bands are placed into the raster, providing data for the raster to read. Creating a new raster and populating it with the desired bands provides the most flexibility. Any time a band is added or removed from a raster, its default settings for spatial reference, extent, and cell size may be changed, and these default settings will be applied to the Raster if they have not been previously set by the user.

    [Visual Basic 6.0]
    Dim pRasterBandCol as IRasterBandCollection
    Set pRasterBandCol = new Raster
    pRasterBandCol.AppendBand pRasterBand

    Pixel blocks

    PixelBlock object contains a pixel array that can be read from a raster or a raster band. The PixelBlock object is designed to handle generic pixel arrays from any raster data source. This means it must be able to handle single and multiband data, as well as support different pixel types. To support different pixel types, the PixelBlock transports pixels in a SafeArray, which has the ability to contain many different data types. To support multiple bands, or planes, of raster data, the PixelBlock provides a separate array for each band in the raster.

    The PixelBlock object can be created from both Raster and RasterBand. The size of the pixel block is required when creating a pixel block. Once specified, pixel block size can not be changed. To read pixel values to the pixel block, the pixel location (in pixel space) in the raster band where the pixelblock start to read need to be specified.

    [Visual Basic 6.0]
    'Define the pixel block size
    Dim pSize As IPnt
    Set pSize = New Pnt
    pSize.SetCoords 512, 512
    'Create the pixel block from a Raster
    Dim pPixelBlock as IPixelBlock3
    Set pPixelBlock =pRaster.CreatePixelBlock(pSize)
    'Create the pixel block from band
    Dim pRawPixel As IRawPixels
    Set pRawPixel = pRasterBand
    Set pPixelBlock = pRawPixel.CreatePixelBlock(pSize)
    'Define the starting pixel in pixel space to read
    Dim pTopLeft As IPnt
    Set pTopLeft = New Pnt
    pTopLeft.SetCoords 0, 0
    'Read the pixel block from a band
    pRawPixel.Read pTopLeft, pPixelBlock

    You can get the pixel values from the pixel block, modify the pixel values, and write the pixel block with the modified pixel values to a raster band. If the pixel block is created from a Raster, the modified pixel block can be written to raster dataset using IRasterEdit::Write.

    This code snippet, continuing the previous code example, writes the modified pixel block to the raster band.

    [Visual Basic 6.0]
    Dim pixelvalues As Variant
    pixelvalues = pPixelBlock.PixelDataByRef
    pixelvalue(5, 5) = 10
    pRawPixel.Write pTopLeft, pPixelBlock

    For small raster datasets, the pixel block can be the size of the entire dataset, which can usually be held in memory at one time and the starting pixel to read the pixel block can be (0,0) Larger rasters can be read in as smaller pieces by creating a smaller PixelBlock and reading portions of the raster sequentially.

    PixelBlockCursor (or RasterCursor) are the two objects that allows you to divide a large image into many pixel blocks and read them one by one. The PixelBlockCursor is an enhanced object in ArcGIS 9.0 that works with reading pixel blocks from large image. You can loop through pixel blocks from a RasterBand> or a Raster. When reading pixel blocks from a Raster, the size of the pixel block is optimized automatically by the system according to the different raster formats that the Raster is created from, and the location of the top-left corner of the next pixel block is return each time a pixel block is read. Reading pixel blocks from a raster band, the size of the pixel block needs to be defined.

    Raster catalogs

    RasterCatalog is a new data type in ArcGIS 9.0 and only applies to raster catalogs in geodatabase. The RasterCatalog manages a collection of raster datasets as one entity, a special type of FeatureClass. This special type of feature class has a Name field that stores the name of the raster dataset, a Geometry field that stores the footprint (bounding box) of the raster dataset, a Raster field that stores pixel values of the raster dataset. It may also contain and any other fields such as metadata etc.

    The value stored in Raster field is called a RasterValue. A RasterValue contains a RasterDataset and a RasterStorageDef. The Raster field has a spatial reference that is applied to all raster values, and it is defined using RasterDef. The property of the Geometry field is defined by GeometryDef. The footprints of the raster datasets stored in the Geometry filed are automatically managed, populated and spatially indexed by the geodatabase. The spatial references of the Raster field and Geometry field are recommended to be same.

    In addition to define the spatial reference for the raster column, RasterDef also defines how the raster values are managed in the raster catalog. A managed raster catalog stores raster value in the raster catalog, while an unmanaged raster catalog stores only the paths to the raster datasets, and those raster datasets reside in file system. A raster catalog in an enterprise geodatabase is always managed, a raster catalog in personal geodatabase can be unmanaged, which means that the raster datasets in the raster catalog do not reside in the personal geodatabase, but in file system.

    The RasterStorageDef object defines how raster value is stored an enterprise geodatabase. You can define the tile size, cell size, origin of the raster value. You can also define the compression type as well as the resampling method of pyramids building.

    As a subclass of FeatureClass, the RasterCatalog consists of rows. The feature in each row is a RasterCatalogItem, a type of Feature. A RasterCatalog operates the same way as a FeatureClass when accessing or updating the raster datasets in the RasterCatalog e.g., enumeration of the raster datasets in a RasterCatalog is accomplished by acquiring a standard FeatureCursor on the RasterCatalog. Insert and update can be achieved by an insert cursor or an update cursor.

    To create a raster catalog, first create an empty raster catalog, which is described in the workspace section, and then add rows that contain raster values to the raster catalog.

    The following code snippet shows a way of loading a raster dataset to a raster catalog.

    [Visual Basic 6.0]
    'Create RasterValue from RasterDataset
    Dim pRasterValue As IRasterValue
    Set pRasterValue = New RasterValue
    Set pRasterValue.RasterDataset = pRasterDataset
    'Raster catalog is just a type of feature class
    Dim pFeatureClass As IFeatureClass
    Set pFeatureClass = pRasterCatalog
    'Insert a row and set the raster value
    Dim pCursor As IFeatureCursor
    Dim pRow As IFeatureBuffer
    Set pCursor = pFeatureClass.Insert(False)
    Set pRow = pFeatureClass.CreateFeatureBuffer
    pRow.Value(pRasterCatalog.RasterFieldIndex) = pRasterValue
    pCursor.InsertFeature pRow

    The code below shows how to get the raster dataset stored in first row in a raster catalog:

    [Visual Basic 6.0]
    Dim pFeatureClass As IFeatureClass
    Set pFeatureClass = pRasterCatalog
    Dim pCatalogItem As IRasterCatalogItem
    Set pCatalogItem = pFeatureClass.GetFeature(1)
    Set pRasterDataset = pCatalogItem.RasterDataset

    A RasterCatalog can be displayed using GdbRasterCatalogLayer object, an object in esriCarto library.


    The following samples illustrate how to open and create a raster dataset and a raster catalog in various workspaces.



    The Metadata sub-system contains the objects for creating, copying, editing, importing, exporting, and synchronizing metadata for datasets, maps, layers, geoprocessing tools, and other supported objects.

    Most supported objects in ArcGIS can have metadata. For datasets accessed using an OLE DB, ArcSDE 3, or an SDE for Coverages database connection, you can neither create metadata nor read metadata that already exists. For all other objects, if you have write permission or have been granted edit permissions, ArcCatalog will by default create and update the metadata automatically when you view it in the Metadata tab (not when the properties or content of the dataset are changed). This process is referred to as synchronization; the Catalog extracts properties from the dataset, calculates values, if necessary, and then stores the information in the dataset’s metadata.

    Metadata is stored in an XML document. For file-based datasets, the XML document resides in an appropriately named XML file on the file system. For example, a shapefile’s metadata is stored in a file that has the same name as the shapefile such as “myShapefile.shp.xml”. A coverage’s metadata is stored in a “metadata.xml” file within the coverage directory.

    For personal geodatabases, connections to a multiuser geodatabase, and objects stored within any geodatabase, the metadata XML document is stored within a BLOB column in the geodatabase administration table called “GDB_Metadata”. To manage metadata with ArcObjects you need some basic knowledge of XML as well as XPath to manipulate the metadata elements.

    The code below shows how to access the metadata for the selected object in the Catalog tree:

    [Visual Basic 6.0]
    Dim pGxApp As IGxApplication
    Dim pMD As IMetadata
    Dim pPS As IPropertySet
    Set pGxApp = Application
    Set pMD = pGxApp.SelectedObject
    Set pPS = pMD.Metadata

    You can get the value of a specific metadata element using IXmlPropertySet2::GetXML method and then can then change the value of the element using the SetPropertyX method

    [Visual Basic 6.0]
    Dim pGxApp As IGxApplication
    Dim pMD As IMetadata
    Dim pPS As IPropertySet
    Dim pXPS2 As IXmlPropertySet2
    Set pGxApp = Application
    Set pMD = pGxApp.SelectedObject
    Set pPS = pMD.Metadata
    Set pXPS2 = pPS
    'returns the Abstract element and its contents
    s = pXPS2.getXml("idinfo/descript/abstract")
    MsgBox s
    'changes the value contained in the Abstract element
    pXPS.setPropertyX "idinfo/descript/abstract", "New Abstract",esriXPTText, esriXSPAAddOrReplace, False
    'saves the metadata
    pMD.Metadata = pPS


    Plug-in data sources

    The plug-in data source sub-system contains objects that allow developers to create their own read-only datasources for the geodatabase, and for applications to access them.

    ArcGIS deals with several read-only data sources such as StreetMap, CAD, and the SDC format used by RouteMap IMS. The method by which ArcGIS handles some of these data sources has been exposed to developers—you can provide ArcGIS support for your own data formats by implementing a plug-in data source.

    A plug-in data source integrates a new data format completely into ArcGIS, albeit in a read-only manner. You can browse, preview, and manage the data in ArcCatalog. You can select, render, query, label, and join the data in ArcMap. You can also program with the data source using normal geodatabase interfaces such as IWorkspace and IFeatureClass.

    There are some limitations: only tables, feature classes, and feature datasets are supported—you cannot integrate plug-in data sources with geodatabase objects such as relationship classes and geometric networks. Additionally, no direct support is provided for dataset manipulation, for example Copy, Delete, Rename, New, Import, and Export.


    The following samples illustrate the use of the Edges objects.


    Network dataset

    A network dataset is a collection of junction, edge, and turn elements that are connected together modeling how real life entities are connected. The network dataset is used as the input to the solvers of the Network Analyst objects in order to solve graph theoretic problems. The junctions, edges, and turns of a network dataset are generated from simple features in network sources. The network dataset contains attributes to represent cost impedances, restrictions, and hierarchy values of the network elements.

    The NetworkDataset object is used to access the contents of the network dataset. Its main interface, INetworkDataset, allows you to inspect the sources, attributes, and other properties of the network dataset. The INetworkBuild interface allows you to make changes to the source and attribute definitions of the network dataset, as well as regenerate the elements of the network dataset from its sources.

    The INetworkQuery interface allows you to query for specific junction, edge, and turn elements in the network dataset. The INetworkQuery interface is also the place where you create a NetworkForwardStar object for querying repeatedly for adjacent elements in the network. The NetworkForwardStar is the basis object for traversing a network to solve a graph theoretic problem. The INetworkForwardStarSetup interfaces allows you to customize the NetworkForwardStar object to limit which elements get returned during the query based on restrictions, barriers, hierarchy, and backtrack settings.

    Once you query for a element in the network, you use the INetworkElement interface to access properties of the element, such as its element ID, the ID of the source that generated that element, and attribute values for that element. The INetworkJunction, INetworkEdge, and INetworkTurn interfaces allow access to properties of the element that are specific to a particular element type.

    The DENetworkDataset object is the data element representation of a network dataset. Its main interface, IDENetworkDataset, allows access to the network dataset's sources, attributes, and other properties. IDENetworkDataset also allows you to modify the data element. However, changes made to the data element are not applied to the actual network dataset until INetworkBuild::UpdateSchema() is called.

    The network source objects describe a network source in the network dataset. Each object implements INetworkSource allowing you to view the properties of that source. The object may implement a source-specific interface, such as IEdgeFeatureSource and IJunctionFeatureSource, which allows you to view and set the connectivity settings for that source.

    A source can also have specifications for which fields on the source are for generating driving directions. These settings are accessed by the INetworkSourceDirections interface.

    The INetworkAttribute interface accesses the properties of a network attribute. For network attributes in geodatabase and shapefile network datasets, the IEvaluatedNetworkAttribute specifies which evaluators are associated with this attribute. An evaluator is an object that determines how the attribute values of a network element are calcuated. In ArcGIS, there are three evaluators: NetworkConstantEvaluator, NetworkFieldEvaluator, and NetworkScriptEvaluator. The NetworkConstantEvaluator assigns a constant attribute value to all elements generated by the given source. The NetworkFieldEvaluator assigns attribute values from the values of a single field on the source feature class, or from a mathematical expression involving values from multiple fields. The NetworkScriptEvaluator calculates the attribute value from a script involving the properties of each network element. The user can also implement their own evaluators by creating objects that implement both INetworkEvaluator and INetworkEvaluatorSetup.


    The following samples illustrate the use of the network dataset objects.