ThinkGeo.com    |     Documentation    |     Premium Support

Mapsuite 10.0 MsSqlFeatureLayer - Column does not belong to table when using where clause

I am upgrading from version 9 to version 10 where we were previously using a MsSql2008FeatureLayer to pull results from a view defined in the database.

One of the limitations in using the MsSql2008FeatureLayer was that we couldn’t execute a stored procedure to return the results. As a workaround for this, we inserted the results we wanted to display into a separate table and created a view that joined from this table to our geospatial table. This drastically improved our query execution and performance. This view contains a column called Is_Adjacent as well as all the other columns from our geospatial table. We then simply specified the WhereClause to indicate if we were fetching the adjacent records or not.

When upgrading to version 10 and using a MsSqlFeatureLayer, we can return the results from the view just fine, the FeatureSource.Columns even contains the Is_Adjacent column. However, if we specify the WhereClause as “WHERE Is_Adjacent = 0”, we receive an error when trying to open the FeatureSource that the column Is_Adjacent doesn’t belong to the table.

Any ideas?

Also as a follow-up, I don’t suppose there has been any changes in the new MsSqlFeatureLayer to be capable of executing a stored procedure instead has there?

Hi Nathan,

The only change for MsSqlFeatureLayer, we support 2016 but not only 2008 in new V10, and sqltypes 2016 is upgraded also, I don’t know whether you are also use that. The mainly logic hadn’t get changed.

So we suggest you do some test like this:

MsSqlFeatureLayer layer = new MsSqlFeatureLayer();
((MsSqlFeatureSource)layer.FeatureSource).ExecutingSqlStatement += (o, e) =>
{
Console.WriteLine(e.SqlStatement);
};

So you can see what’s the sent Sql statement and test that in server side to see whether it get correct result.

If the sent Sql statement is incorrect or it get correct result but failed on map please let us know, and a project which can reproduce that with a test very small database should be helpful.

Regards,

Don

Printing out the debug output, it doesn’t make any logical sense with what’s it’s attempting to do.

Here is what I receive at the point where the error occurs:
select max_length from sys.columns where object_name(object_id) = ‘v_Mapping_Counties’ and name = ‘Artificial_Key’ AND ( Is_Adjacent = 1);

What it appears to be doing is injecting the where clause before the actual execution of the select statement for the FeatureSource. Now, running that query as a select * from the sys.columns based solely on the object name, I can see the Is_Adjacent column existing. This log is called when I call FeatureSource.Open, and not the GetAllFeatures (this will be important further below).

What appears to be happening is that it is injecting the WHERE clause when it is attempting to get the information for the Index, not when it is actually executing the statement.

Now, to further back this up. If I comment out the where clause, I see the following:
SELECT allColumns.name, allTypes.name, allTypes.max_length FROM sys.columns allColumns, sys.tables allTables, sys.types allTypes where allColumns.object_id=allTables.object_id AND allColumns.user_type_id=allTypes.user_type_id AND allTables.name=‘v_Mapping_Counties’

So, as you can see, it appears to be retrieving column information from the view. It then proceeds to fetch column information for each of the columns returned from this result, one of which is the Is_Adjacent column. Now, when I call the GetAllFeatures without the WHERE clause, I see the following:
SELECT [Artificial_Key],[Shape].STAsBinary() as [Shape],[Shape_Type],[County_Code],[State_Code],[Reins_Year],[Is_Adjacent],[Display_Name] FROM v_Mapping_Counties;

Here, is where I’d expect to see the WHERE clause injected, which I believe is how and where earlier versions was placing the WHERE clause.

It may be important to note, here is how we were previously setting up the constructor for the layer:
var sqlLayer =
new MsSql2008FeatureLayer(ConnectionHelper.GetClientMappingDBConnection(), “v_Mapping_Counties”, “Artificial_Key”, 4326)
{
WhereClause = $“WHERE Is_Adjacent = {Convert.ToByte(adjacent)}”,
SpatialIndexName = “IX_dbo_Mapping_GIS_County_Info_Spatial”
};

So what appears to be the problem is that you are injecting the WHERE clause in the sys.columns calls and not in the actual execution call.

Any recommendations?

Hi Nathan,

Have you tried to upgrade all of your dlls to the latest version? I build a sample to test that today.

It looks the where clause will be placed into the sql statement when you call GetAllFeatures, do you think that’s related with the {Convert.ToByte(adjacent)}, have you tried to hardcode a value here?

Plase view the image as below, the GetAllFeatures append my where clause, and the render result is OK.

Our test database is just a simple table, it hadn’t contains the other object like view. But I think that’s not related with the situation you mentioned before, because it looks in application side, your app hadn’t sent the correct sql statement.

So please just upgrade your application, and if that still don’t works, please build a very simple sample which can reproduce this problem, so we can replace with our connection string and value to test that.

Regards,

Don

I had just installed version 10 from the NuGet packages right before running into this problem, and none of them show as us having any updates available. Also, I’m not sure I get how my app isn’t sending the correct sql statement. I never had to specify a sql statement before when using the MsSql2008FeatureLayer, are you saying you have to in the new one?

I can’t really “build you a really simple application” because you wouldn’t have access to the database tables or any of that.

Here is how I am loading the layer:

            // Define a SQL layer
            // To speed up access times and to better utilize indexing, all MsSqlFeatureLayers are loaded via a view.
            // These views use a table marked via a _Display keyword that contains the PKs for the spatial data we will be viewing.
            var sqlLayer =
                new MsSqlFeatureLayer(ConnectionHelper.GetClientMappingDBConnection(), "v_Mapping_Counties", "Artificial_Key", 4326)
                {
                    WhereClause = $"WHERE Is_Adjacent = {Convert.ToByte(adjacent)}",
                    SpatialIndexName = "IX_dbo_Mapping_GIS_County_Info_Spatial"
                };

            // DEBUGGING
            ((MsSqlFeatureSource) sqlLayer.FeatureSource).ExecutingSqlStatement += (o, e) => { Console.WriteLine(e.SqlStatement); };

            // Setup our projection
            // All county entries are stored using a SRID of 4326, this needs to be re-projected to the UTM SRID the map is using
            var projection = new Proj4Projection()
            {
                InternalProjectionParametersString = Proj4Projection.GetEpsgParametersString(4326),
                ExternalProjectionParametersString = Proj4Projection.GetEpsgParametersString(Srid)
            };
            projection.Open();

            // Set the Projection for the MsSqlFeatureLayer, this will automatically convert the features
            // contained within this layer to the UTM SRID for us
            sqlLayer.FeatureSource.Projection = projection;
            sqlLayer.FeatureSource.Open();

            // To further boost performance, we convert the MsSqlFeatureLayer to an InMemoryFeatureLayer
            // This prevents database hits each time the extent or zoom of the map is changed

            // To accomplish this, we first pull all the features from the MsSqlFeatureLayer, this does perform a database hit
            var features = sqlLayer.FeatureSource.GetAllFeatures(ReturningColumnsType.AllColumns);
            sqlLayer.FeatureSource.Close();

My view is just a joined from the Counties table to a Counties display table based on the PK to FK relationship, and includes all the columns from the Counties table and the Is_Adjacent column from the display table.

For you guys to reproduce, it should be pretty easy to set up.

Take your existing table, then create another table called Countries02_Display. Add a column which is a FK to the Countries02 table’s PK, then another column called Is_Adjacent as a BIT which defaults to 0. Insert records from your Countries02 table into the Countries02_Display with a few of them being flagged as Is_Adjacent = 1 whereas the others are 0.

Now, create a view for these two, we can call it vCounties02. All this view needs to do is select from Countires02 joined to Countires02_Display on the keys, return all the columns from Countires02 and then the Is_Adjacent column from Countires02_Display.

Now, you can use the same code I have above to load it:

            // Define a SQL layer
            // To speed up access times and to better utilize indexing, all MsSqlFeatureLayers are loaded via a view.
            // These views use a table marked via a _Display keyword that contains the PKs for the spatial data we will be viewing.
            var sqlLayer =
                new MsSqlFeatureLayer(ConnectionHelper.GetClientMappingDBConnection(), "v_Counties02", "Artificial_Key", 4326)
                {
                    WhereClause = $"WHERE Is_Adjacent = {Convert.ToByte(adjacent)}",
                    SpatialIndexName = "IX_dbo_Mapping_GIS_County_Info_Spatial"
                };

I think it has to do with the View and not using straight up table. The select from the sys.columns appears to be totally different for what I am executing.

I can’t actually provide you with a working example b/c our database is in no state in which it can be exported or shared.

Hi Nathan,

Thanks for your further information, we have fixed this issue.

Please get the latest version ThinkGeo.MapSuite.Layers.MsSql 11.0.0-beta002 after it get updated in one or two days from NuGet.

Regards,

Don

How do you update to the beta and version 11? All I am seeing is version 10’s and no betas listed.

Hi Nathan,

Please check the “Include prerelease” NuGet manager when updating the package, it will let you find the beta release packages.

Please refer below snapshot:

If there is any question, please let us know that.

Thanks
Mark

So, in order to resolve this, I have to go from a stable release of ThinkGeo.MapSuite 10.0.4 to a potentially unstable pre-release of version 11 beta 2?

HI Nathan,

You are right. We fixed the user reported bug on development branch, it is mean the beta version, if you meet any issue on beta version, we can resolve them ASAP.

If we always apply the changes to release version, it makes the release version unstable. We will be apply all the changes on development branch to release version next minor release in 1-2 months.

Thanks
Mark

I’m not worried about it being in a beta branch/version itself, what worried me is the change you implemented is in a version 11 beta, and not a version 10 beta.

Now, instead of requiring me to just use a beta version of the sql layer package with a dependency on v10 of the core, I have to use a beta version of of both the sql and core packages for a version 11, which hasn’t even been released yet.

If it was fixed in a version 10 beta that didn’t have a dependency on core beta 10, I could have only imported a version 10 beta of the one package and not forced me into using a beta version of core as well.

Hi Nathan,

Base on NuGet version control, beta version code is always newer than release version, when we released 10.0, the beta version should be 11.0.x-beta or 10.1.x-beta. In this case, the NuGet manager can update the pre-release version from 10.0.x to latest beta version. We choice use 11.0.x-beta as the beta version, we can easy to know this beta branch is based on our release branch 10.0.x.

Release: 10.0.x–>11.0.x–>12.0.x.
Production builds in NuGet are our well-tested assemblies and for the most part the ones we suggest using. They all have a three-number version number which relates to the Major, Minor, and Patch versions. For example, 10.1.2 where 10 is the major version, 1 is the minor version, and 2 is the patch version. The next minor release will include all the beta branch code changes.

Beta: 11.0.x-BetaX–>12.0.x-BetaX.
The Development Branch is built daily which means that new changes will be available the day after they are made. These versions will always have the latest features as we add them, but may not be tested fully yet, and the APIs for the new features may change through development. The version numbers for daily builds are the next major version suffixed with “beta” and a build number.

Hope this can make you clear for our version strategy. If there is any question, please let’s know that.

Thanks
Mark

It does, my concern is why you placed it in version 11’s beta and not version 10’s beta?

HI Nathan,

We need to make the release version stable, so we only apply the urgent bug fixing on release version, like license, crash bug. Otherwise, the new features and normal bugs fixing will be applied on beta release.

Your report is one normal bug, if we apply that to release version, we need take more time to do the testing, you cannot get the fixing in daily.

Hope this make you clear for our version strategy. if there is any question, please let me know that.

Thanks
Mark

Agreed and I understand. Why was it done in a version 11 beta instead of a version 10.0.x beta though? Is 11 the beta for 10? If so, that seems rather confusing as I’d think 11 would be a major release with new features, not the place were bugs are pre-tested for 10’s minor releases.

Hi Nathan,

The beta version is ready for Major release (11, 12, 13, etc), 11 beta is pre-release for 11 release. We prefer to keep our beta release version is won’t be updated until one major released. we don’t care beta version number in minor release, the minor release contain all the beta changes but not update the beta version number. So the 10’s minor release bugs are pre-tested on 11 beta release.

It is a little confuse, but this is our version strategy. It has advantages to control the major release version.

If you have any questions, please feel free to let us know that.

Thanks
Mark