Prevent extent calculation when adding query layer to map

2394
3
07-18-2016 02:39 AM
FabianFusholler
New Contributor II

Hi,

when adding a query layer to ArcMap by ArcObjects code the extent of the newly created layer will be calculated based on data by default. This causes significant performance issues (i.e. full table scans with several millions rows).

When redefining a query layer in ArcMap manually an options-dialog is provided where you can choose between "Input Extent" and "Use Spatial Reference Extent" (see http://desktop.arcgis.com/en/arcmap/10.3/map/working-with-layers/creating-a-query-layer.htm).

The second option is what I need. Is there any ArcObjects interface to force this? Is there any way to prevent the extent calculation and to use a given Extent?

I've tried without effect to deal with: 

- Setting ILayer2.AreaOfInterest before loading layer

- Setting SpatialDomain in IFeatureClass.SpatialReference of the query class

- Loading a layerfile is no option in my case (the extent will be saved in layerfile)

Thank you.

Sample code:

    Protected Sub AddNewQueryLayerToFocusMap(ByVal sqlWorkspace As ISqlWorkspace, _

                                             ByVal featureClassName As String, _

                                             ByVal geomType As esriGeometryType, _

                                             ByVal spatialRef As ISpatialReference,

                                             ByVal map As IMap)

        Dim query = String.Format("SELECT * FROM {0}", featureClassName)

        Dim queryDesc = sqlWorkspace.GetQueryDescription(query)

        queryDesc.OIDFields = "OBJECTID"

        queryDesc.GeometryType = geomType

        queryDesc.SpatialReference = spatialRef

        ' Ensure that the specified name for the Query Layer feature class is not 

        ' already being used. 

        Dim newName = String.Empty

        sqlWorkspace.CheckDatasetName(featureClassName, queryDesc, newName)

        Dim queryClass = sqlWorkspace.OpenQueryClass(newName, queryDesc)

        Dim featureClass = TryCast(queryClass, IFeatureClass)

        Dim featureLayer = New FeatureLayerClass() With {.FeatureClass = featureClass}

        map.AddLayer(featureLayer) '==> extent calculation will be performed

    End Sub

0 Kudos
3 Replies
FabianFusholler
New Contributor II

Unfortunately, there is no built-in functionality that would allow one to choose between "Input Extent" and "Use Spatial Reference".  This requires usage of Custom Layers and overriding the default behaviour of a feature layers extent property (IFeatureLayer.Extent). See http://resources.arcgis.com/en/help/arcobjects-net/conceptualhelp/#/Creating_custom_layers/000100000...http://resources.arcgis.com/en/help/arcobjects-net/conceptualhelp/#/Creating_custom_layers/000100000... for details.

See custom layer class below which makes it possible to define a fixed extent for a underlying feature layer:

<Guid("3460FB55-4326-4d28-9F96-D62211B0C754"), ClassInterface(ClassInterfaceType.None), ComVisible(True), ProgId("CustomLayer")> _Public NotInheritable Class CustomLayer    Inherits BaseCustomLayer    Implements IIdentify    Implements ILegendInfo      Private _featureLayer As IFeatureLayer    Private _env As IEnvelope      Public Sub New(feautreLayer As IFeatureLayerByVal env As IEnvelope)         _featureLayer = feautreLayer     End Sub      Public Overrides Sub Draw(drawPhase As ESRI.ArcGIS.esriSystem.esriDrawPhase, Display As ESRI.ArcGIS.Display.IDisplay, trackCancel As ESRI.ArcGIS.esriSystem.ITrackCancel)         _featureLayer.Draw(drawPhase, Display, trackCancel)     End Sub      Public Overrides ReadOnly Property Extent() As IEnvelope        Get            Return _env         End Get    End Property      Public Function Identify(pGeom As IGeometryAs ESRI.ArcGIS.esriSystem.IArray Implements IIdentify.Identify         Return CType(_featureLayer, IIdentify).Identify(pGeom)     End Function      Public ReadOnly Property LegendGroup(Index As IntegerAs ILegendGroup Implements ILegendInfo.LegendGroup         Get            Return CType(_featureLayer, ILegendInfo).LegendGroup(Index)         End Get    End Property      Public ReadOnly Property LegendGroupCount As Integer Implements ILegendInfo.LegendGroupCount         Get            Return CType(_featureLayer, ILegendInfo).LegendGroupCount         End Get    End Property      Public ReadOnly Property LegendItem As ILegendItem Implements ILegendInfo.LegendItem         Get            Return CType(_featureLayer, ILegendInfo).LegendItem         End Get    End Property      Public Property SymbolsAreGraduated As Boolean Implements ILegendInfo.SymbolsAreGraduated         Get            Return CType(_featureLayer, ILegendInfo).SymbolsAreGraduated         End Get        Set(value As Boolean)             CType(_featureLayer, ILegendInfo).SymbolsAreGraduated = value         End Set    End Property
AJR
by
Occasional Contributor II

Did you ever find a workaround for this (e.g. some way to pass in the known extent)?

0 Kudos
FabianFusholler
New Contributor II

Please see the workaround I mentioned in my previous posting, which is working for my purposes. Implementing a custom layer enables you to write you own code to determine layers's extent and passing to custom layer class.

I didn't find any other approaches to fix this problem.

0 Kudos