/// <summary>
        /// For each table in the query, return a FeatureCollection.
        /// </summary>
        /// <param name="query">query with a bounding box</param>
        /// <returns>set of GeoJson Features</returns>
        public Bitmap GetImage(BoundingBoxQuery query)
        {
            Bitmap  bmp     = new Bitmap(query.Width, query.Height);
            Metrics metrics = new Metrics(this._metricsType);


            try
            {
                metrics.Start("Global");

                using (Graphics g = Graphics.FromImage(bmp))
                {
                    foreach (string table in query.Tables())
                    {
                        Bitmap bmpTable = null;

                        #region Preload cache if necessary

                        if (UseInMemoryCache)
                        {
                            metrics.Start("Cache");
                            if (!GeometryCache.IsCacheLoaded(table))
                            {
                                while (!GeometryCache.IsCacheLoaded(table))
                                {
                                    GeometryCache.LoadCache(table, this.GetConnectionString());
                                    Trace.WriteLine(string.Format("Thread {0} waiting for cache...", Thread.CurrentThread.ManagedThreadId));
                                }
                            }
                            metrics.Stop("Cache");
                        }
                        #endregion

                        if (query.IsBench)
                        {
                            bmpTable = GetBenchImageGeneric(query, metrics, table, UseInMemoryCache);
                        }
                        else if (UseInMemoryCache)
                        {
                            bmpTable = GetImage_BBox(query, metrics, table);
                        }
                        //else
                        //  bmpTable = GetImageGeneric_FromDB(query, metrics, table, false);

                        g.DrawImageUnscaled(bmpTable, 0, 0);
                        bmp.Tag = bmpTable.Tag;
                        bmpTable.Dispose();
                    }
                }

                metrics.Stop("Global");

                #region Calculate metrics to return.
                // Calculate metrics to return.
                switch (_metricsType)
                {
                case enMetricsType.OnlyTime:

                    string msg = null;
                    foreach (var kv in metrics.GetTaskTimes())
                    {
                        msg += string.Format("{0}: {1,6:###,###} ms{2}", kv.Key, kv.Value.TotalMilliseconds, Environment.NewLine);
                    }
                    this.DrawMsgInImage(ref bmp, msg);



                    break;

                default:

                    break;
                }

                #endregion
            }
            catch (Exception ex)
            {
                #region Write exception in image
                // Write exception in image
                using (Graphics g = Graphics.FromImage(bmp))
                {
                    g.Clear(Color.FromArgb(128, Color.Red));

                    using (Font font = new Font(FontFamily.GenericMonospace, 11, FontStyle.Regular, GraphicsUnit.Pixel))
                        g.DrawString(ex.ToString(), font, Brushes.Black, new RectangleF(0, 0, 256, 256));
                }
                #endregion
            }

            return(bmp);
        }
        /// <summary>
        /// For each table in the query, return a FeatureCollection.
        /// </summary>
        /// <param name="query">query with a bounding box</param>
        /// <returns>set of GeoJson Features</returns>
        public List <SqlGeometry> GetGeometries(BoundingBoxQuery query)
        {
            List <SqlGeometry> outGeom = new List <SqlGeometry>();
            Metrics            metrics = new Metrics(this._metricsType);


            try
            {
                metrics.Start("Global");

                foreach (string table in query.Tables())
                {
                    #region Preload cache if necessary

                    if (UseInMemoryCache)
                    {
                        metrics.Start("Cache");
                        if (!GeometryCache.IsCacheLoaded(table))
                        {
                            while (!GeometryCache.IsCacheLoaded(table))
                            {
                                GeometryCache.LoadCache(table, this.GetConnectionString());
                                Trace.WriteLine(string.Format("Thread {0} waiting for cache...", Thread.CurrentThread.ManagedThreadId));
                            }
                        }
                        metrics.Stop("Cache");
                    }
                    #endregion

                    outGeom.AddRange(GetGeometries_BBox(query, metrics, table));
                }


                metrics.Stop("Global");

                #region Calculate metrics to return. (TODO)
                // Calculate metrics to return.
                switch (_metricsType)
                {
                case enMetricsType.OnlyTime:

                    string msg = null;
                    foreach (var kv in metrics.GetTaskTimes())
                    {
                        msg += string.Format("{0}: {1,6:###,###} ms{2}", kv.Key, kv.Value.TotalMilliseconds, Environment.NewLine);
                    }
                    //this.DrawMsgInImage(ref bmp, msg);



                    break;

                default:

                    break;
                }

                #endregion
            }
            catch (Exception ex)
            {
                throw;
            }

            return(outGeom);
        }