Working with query cursors


Summary This topic explains how to create and use a query cursor.

In this topic


Eligibility of data for query cursors

Query cursors are slightly more flexible than query classes with the types of queries they can use. Unique identifiers are not needed for query cursors in the same way they are for query classes; since a query description is not created as an intermediate step, ID mapping cannot be specified. However, other query class restrictions do apply to query cursors, such as the following:
  • Geometry fields—A geometry field is not required, but a maximum of one geometry field can be in the result set.
  • Spatial references—All geometries in a geometry field should share the same spatial reference identifier (SRID).
If these restrictions are violated, creating the cursor will not immediately fail, but an error will be raised when the first row is retrieved (or when the first row with a different spatial reference is retrieved, in the second case).
One notable difference from query classes is that the rows returning a query cursor can contain different geometry types. That is, if a table contains a single geometry column with a combination of point, lines, and polygons in different rows, a query cursor can still be used to read each row.

Creating a query cursor

To create a query cursor, pass a Spatial Query Language (SQL) query into the ISqlWorkspace.OpenQueryCursor method; the cursor is returned.
The following code shows how a query cursor can be used to read the rows of a SQL join:
[C#]
// Construct a SQL query.
StringBuilder queryBuilder = new StringBuilder();
queryBuilder.Append("SELECT CITY_NAME, STATE_NAME, CITYSHAPE ");
queryBuilder.Append("FROM CAPITALS JOIN STATES ");
queryBuilder.Append("ON CAPITALS.FIPS = STATES.FIPS ");
queryBuilder.Append("ORDER BY CITY_NAME");
String query = queryBuilder.ToString();

using(ComReleaser comReleaser = new ComReleaser())
{
    // Create the query cursor.
    IFeatureCursor featureCursor = (IFeatureCursor)sqlWorkspace.OpenQueryCursor
        (query);
    comReleaser.ManageLifetime(featureCursor);

    // Iterate through the features.
    IFeature feature = null;
    while ((feature = featureCursor.NextFeature()) != null)
    {
        // Write the values to the console.
        Console.WriteLine("City: {0}", feature.get_Value(0));
        Console.WriteLine("State: {0}", feature.get_Value(1));
        IPoint point = feature.get_Value(2)as IPoint;
        if (point != null)
        {
            Console.WriteLine("Location: {0}, {1}", point.X, point.Y);
        }
    }
}
[VB.NET]
' Construct a SQL query.
Dim queryBuilder As StringBuilder = New StringBuilder()
queryBuilder.Append("SELECT CITY_NAME, STATE_NAME, CITYSHAPE ")
queryBuilder.Append("FROM CAPITALS JOIN STATES ")
queryBuilder.Append("ON CAPITALS.FIPS = STATES.FIPS ")
queryBuilder.Append("ORDER BY CITY_NAME")
Dim query As String = queryBuilder.ToString()

Using comReleaser As ComReleaser = New ComReleaser()
' Create the query cursor.
Dim featureCursor As IFeatureCursor = CType(sqlWorkspace.OpenQueryCursor(query), IFeatureCursor)
comReleaser.ManageLifetime(featureCursor)

' Iterate through the features.
Dim feature As IFeature = featureCursor.NextFeature()
While Not feature Is Nothing
    ' Write the values to the console.
    Console.WriteLine("City: {0}", feature.Value(0))
    Console.WriteLine("State: {0}", feature.Value(1))
    Dim point As IPoint = TryCast(feature.Value(2), IPoint)
    If Not point Is Nothing Then
        Console.WriteLine("Location: {0}, {1}", point.X, point.Y)
    End If
    feature = featureCursor.NextFeature()
End While
End Using
Query cursors can implement the IFeatureCursor interface, depending on whether or not their query includes a geometry column.
Query cursors are always non-recycling cursors, providing them with the flexibility to handle multiple geometry types in a single column.


See Also:

Working with SQL workspaces
Working with query classes
Query classes and cursors




To use the code in this topic, reference the following assemblies in your Visual Studio project. In the code files, you will need using (C#) or Imports (VB .NET) directives for the corresponding namespaces (given in parenthesis below if different from the assembly name):
Development licensing Deployment licensing
ArcView ArcView
ArcEditor ArcEditor
ArcInfo ArcInfo
Engine Developer Kit Engine Runtime