I use “GetFeaturesInsideBoundingBox” on a MsSql2008Feature and this method takes 5 seconds.
The result returns more than 160000 items. It’ so long so I try to reduce the execution time.
I launch sql profiler to see what query is executed with the method GetFeaturesInsideBoundingBox
The query (Query1) is : exec sp_executesql N’SELECT [Geom].STAsBinary() as [Geom],[CartoId] FROM [Carto].[CartoD ] with(index(Carto_01)) WHERE (geometry::STGeomFromWKB(@Geometry,2154).STIntersects(Geom)=1) AND ( TYPE = 4);’,N’@Geometry varbinary(93)’,@Geometry=0x01030000000100000005000000000000005C47154100000040A5265941000000005C4715410000000027995841000000007C621C410000000027995841000000007C621C4100000040A5265941000000005C47154100000040A5265941 go
In fact , I just need to know if the number of returned items is greater than 0, si I tested this query (Query2) :
exec sp_executesql N’SELECT [CartoId] FROM [Carto].[CartoD ] with(index(Carto_01)) WHERE (geometry::STGeomFromWKB(@Geometry,2154).STIntersects(Geom)=1) AND ( TYPE = 4);’,N’@Geometry varbinary(93)’,@Geometry=0x01030000000100000005000000000000005C47154100000040A5265941000000005C4715410000000027995841000000007C621C410000000027995841000000007C621C4100000040A5265941000000005C47154100000040A5265941 go
And the Query2 takes 1 second, which is better.
Question 1 :
Is it possible to overload querytools and to add a method like QueryTools.GetFeaturesIdInsideBoundingBox(f.GetBoundingBox(), ReturningColumnsType.NoColumns);
And this method would perform Query2 ?
Question 2 :
5 seconds to return 160,000 items with QueryTools.GetFeaturesInsideBoundingBox(f.GetBoundingBox(), ReturningColumnsType.NoColumns); It seems you normal ? If not, do you think the problem may be a bad spatial index ? Or other things ?
I think you should extend the class with your wanted functions. If you do as you describe, and get just the IDs, the server will still have to get all the 160 k answers for you. It will return less data as the IDs occupy less space than the geometries, but nevertheless.
If you were to create a function, which could be named MyQueryTools.IsAnyFeaturesInsideBoundingBox(f.GetBoundingBox), then it should execute something like:
exec sp_executesql N’IF EXISTS (SELECT * FROM [Carto].[CartoD ] with(index(Carto_01)) WHERE (geometry::STGeomFromWKB(@Geometry,2154).STIntersects(Geom)=1) AND ( TYPE = 4);’,N’@Geometry varbinary(93)’,@Geometry=0x01030000000100000005000000000000005C47154100000040A5265941000000005C4715410000000027995841000000007C621C410000000027995841000000007C621C4100000040A5265941000000005C47154100000040A5265941) RETURN 1 ELSE RETURN 0 go
Then you would allow the SQL server to hunt for any result, and return as soon as it found just one. If, after this, you ask for more, then you will get the penalty of the complete query.
The reason for asking for SELECT * in the above is that this allows the SQL server to use ANY index it seems fit to answer your question. This is one of the very few examples of using asterisk instead of a column list that is recommended.
Thanks a lot for your help.
I tested the sample and when I executed , I have an error message “Incorrect syntax near ‘)’.”
I changed few things and I still have an error message
My second question is for the extend class QueryTools
I create a class like this : public static class QueryToolsExtension { public static bool IsAnyFeaturesInsideBoundingBox(this QueryTools queryTools, BaseShape targetShape) { return true; } }
I would like the extended methods are generic such you do for GetFeaturesInsideBoundingBox.
How can I do that ?
Thanks.
But my goal is to extend the class querytools.
So I did :
public static class QueryToolsExtension {
public static bool IsAnyFeaturesInsideBoundingBox(this QueryTools queryTools, BaseShape targetShape,Couche coucheFg) { var geometry= coucheFg.ColonneGeometry; var id = coucheFg.ColonneId; var schéma = coucheFg.Schema; var table = coucheFg.Table; string whereClause = “(geometry::STGeomFromWKB(@Geometry,”+(int)coucheFg.SRID+").STIntersects("+geometry+")=1)";
Thanks.
I tested the code and I can not run the code. Below the different problems I’ve had.
GetDbConnection() :
The value “source.GetType().GetField(“connection”, BindingFlags.Instance | BindingFlags.NonPublic)” return null, so the db connection does not work
I changed public static bool IsAnyFeaturesInsideBoundingBox(this MsSql2008FeatureSource featureSource, RectangleShape boundingBox) { using (var conn = new SqlConnection(Connect.DefaultConnectionString)) { //var connection = GetDbConnection(featureSource); if (conn.State != ConnectionState.Open) { conn.Open(); } var command = conn.CreateCommand(); SetCommand(featureSource, command, boundingBox); var reader = command.ExecuteReader(); // remember to dispose this command if necessary. return reader.HasRows; } }
And that works. By doing so, i dispose the connexion … no ?
I tested again and I have an error with $ ==> command.CommandText = $"SELECT {featureSource.FeatureIdColumn}
I delete this character and now I have :
command.CommandText =“SELECT {featureSource.FeatureIdColumn} …”
Now, i have this error
L’exception System.Data.SqlClient.SqlException n’a pas été gérée
HResult=-2146232060
Message=Syntaxe incorrecte vers ‘.’. Source=.Net SqlClient Data Provider
ErrorCode=-2146232060
Class=15
LineNumber=1
Number=102
Procedure=""
Server=.\SQLEXPRESS2014
State=1