ThinkGeo.com    |     Blog    |     Wiki    |     Support

ShapeFileFeatureLayer.QueryTools.ExecuteQuery Throws ArgumentOutOfRangeException

Running ShapeFileFeatureLayer.QueryTools.ExecuteQuery() on a shape file layer with the latest ThinkGeo MapSuite NuGet packages throws the following exection:

System.ArgumentOutOfRangeException
  HResult=0x80131502
  Message=StartIndex cannot be less than zero.
Parameter name: startIndex
  Source=mscorlib
  StackTrace:
   at System.String.Substring(Int32 startIndex, Int32 length)
   at hyY=.kEk=.kkk=(String sqlStatement, String shapePathFilename)
   at hyY=.kEk=.ExecuteQuery(String sqlStatement, String pathFilename)
   at ThinkGeo.MapSuite.Layers.ShapeFileFeatureSource.ExecuteQueryCore(String sqlStatement)
   at CSHowDoISamples.SqlQueryAFeatureLayer.btnExecute_Click(Object sender, RoutedEventArgs e) in D:\HowDoISample-ForWpf-master\HowDoI\Querying Feature Layers\SqlQueryAFeatureLayer.xaml.cs:line 54
   at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
   at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
   at System.Windows.Controls.Primitives.ButtonBase.OnClick()
   at System.Windows.Controls.Button.OnClick()
   at System.Windows.Controls.Primitives.ButtonBase.OnMouseLeftButtonUp(MouseButtonEventArgs e)
   at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
   at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
   at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
   at System.Windows.UIElement.ReRaiseEventAs(DependencyObject sender, RoutedEventArgs args, RoutedEvent newEvent)
   at System.Windows.UIElement.OnMouseUpThunk(Object sender, MouseButtonEventArgs e)
   at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
   at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
   at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
   at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
   at System.Windows.UIElement.RaiseTrustedEvent(RoutedEventArgs args)
   at System.Windows.Input.InputManager.ProcessStagingArea()
   at System.Windows.Input.InputManager.ProcessInput(InputEventArgs input)
   at System.Windows.Input.InputProviderSite.ReportInput(InputReport inputReport)
   at System.Windows.Interop.HwndMouseInputProvider.ReportInput(IntPtr hwnd, InputMode mode, Int32 timestamp, RawMouseActions actions, Int32 x, Int32 y, Int32 wheel)
   at System.Windows.Interop.HwndMouseInputProvider.FilterMessage(IntPtr hwnd, WindowMessage msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at System.Windows.Interop.HwndSource.InputFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
   at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
   at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
   at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
   at System.Windows.Application.RunDispatcher(Object ignore)
   at System.Windows.Application.RunInternal(Window window)
   at WpfApplication1.App.Main()

I thought I might be using the MapSuite’s API the wrong way, so I checked the samples provided by ThinkGeo on github. The result were the same.
The sample I tried was : Querying feature layer > Sql query a feature layer with the default values.

and the code is (taken from that repository) is the following:

public partial class SqlQueryAFeatureLayer : UserControl
    {
        public SqlQueryAFeatureLayer()
        {
            InitializeComponent();
        }

        private void WpfMap_Loaded(object sender, RoutedEventArgs e)
        {
            wpfMap1.MapUnit = GeographyUnit.Meter;
            wpfMap1.CurrentExtent = new RectangleShape(-14833496.0849081, 32062644.1224434, 14126965.1917795, -26821163.932136);
            wpfMap1.ZoomLevelSet = new ThinkGeoCloudMapsZoomLevelSet();

            // Please input your ThinkGeo Cloud Client ID / Client Secret to enable the background map.
            ThinkGeoCloudRasterMapsOverlay backgroundOverlay = new ThinkGeoCloudRasterMapsOverlay("ThinkGeo Cloud Client ID", "ThinkGeo Cloud Client Secret");
            wpfMap1.Overlays.Add(backgroundOverlay);

            ShapeFileFeatureLayer statesLayer = new ShapeFileFeatureLayer(Samples.RootDirectory + @"Data\USStates_3857.shp");
            statesLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = AreaStyles.CreateSimpleAreaStyle(GeoColor.SimpleColors.Transparent, GeoColor.FromArgb(100, GeoColor.SimpleColors.Green));
            statesLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle.OutlinePen.LineJoin = DrawingLineJoin.Round;
            statesLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;

            LayerOverlay staticOverlay = new LayerOverlay();
            staticOverlay.TransitionEffect = TransitionEffect.None;
            staticOverlay.Layers.Add("StatesLayer", statesLayer);
            wpfMap1.Overlays.Add(staticOverlay);

            wpfMap1.Refresh();
        }

        private void btnExecute_Click(object sender, RoutedEventArgs e)
        {
            ShapeFileFeatureLayer statesLayer = (ShapeFileFeatureLayer)wpfMap1.FindFeatureLayer("StatesLayer");

            statesLayer.Open();
            DataTable dataTable = statesLayer.QueryTools.ExecuteQuery(tbxSQL.Text); // <== this line throws exception
            statesLayer.Close();

            dgridResult.DataContext = dataTable;
        }
    }

Is there a per-requisite that is not followed, raising this exception?
Is there another way to query feature layers that are loaded by shape files (.shp files)?

Environment:
Windows 10
.NET 4.6.1

Hi John,

From the exception, it looks that’s maybe because you hadn’t build index for your shape file.

Please try to do that first: ShapeFileFeatureLayer.BuildIndexFile("")

If it still don’t works, could you please upload your data so we can try to reproduce it.

Regards,

Ethan

It didn’t work. If you pay attention to stack trace, it seems the index ins related to the string index in Substring function.

Here is the code after adding BuildIndexFile function call:

        private void btnExecute_Click(object sender, RoutedEventArgs e)
        {
            ShapeFileFeatureLayer statesLayer = (ShapeFileFeatureLayer)wpfMap1.FindFeatureLayer("StatesLayer");

            statesLayer.Open();

            ShapeFileFeatureLayer.BuildIndexFile(Samples.RootDirectory + @"Data\USStates_3857.shp");
            DataTable dataTable = statesLayer.QueryTools.ExecuteQuery(tbxSQL.Text);
            statesLayer.Close();

            dgridResult.DataContext = dataTable;
        }

As I mentioned in the Original post the sample data and the code can be found in ThinkGeo’s HowDoISample repository for wpf. To make thing easier to reproduce I checked this in the SqlQueryAFeatureLayer example provided there.
You can just run that code sample without any modification with the provided sample query, and you’ll be able to reproduce it.

Please let me know if there is anything else I can provide to make it easier for you to reproduce the issue.

P.S. The sample uses this shape file as can be seen in the code: https://github.com/ThinkGeo/HowDoISample-ForWpf/blob/master/HowDoI/Data/USStates_3857.shp

Hi John,

Thanks for your detail information.

I think that’s because our data get updated but the code hadn’t get updated in the sample.

You can use this line to make it works:

tbxSQL.Text = tbxSQL.Text.Replace(“USStates”, “USStates_3857”);

The table name should be USStates_3857 but it still be USStates in the sample.

Wish that’s helpful.

Regards,

Ethan

1 Like

Thank you very much for you help Ethan.

The original issue is resolved.

I also realized that the name of the table is the same as the filename, so in this case, when the name of the file has changed, the table name in the SQL query also must have changed accordingly.
Also, the queries need Microsoft.ACE.OLEDB.12.0 to be installed on the host machine.

Hi John,

Yes, it looks you need to install the package for that.

My win10 machine don’t need install it, but it looks the win7 need it.

I think this topic is helpful: https://social.msdn.microsoft.com/Forums/en-US/1d5c04c7-157f-4955-a14b-41d912d50a64/how-to-fix-error-quotthe-microsoftaceoledb120-provider-is-not-registered-on-the-local?forum=vstsdb

Regards,

Ethan

1 Like