ThinkGeo.com    |     Documentation    |     Premium Support

WfsLayer GetFeaturesByColumnValue

I am in the process of migrating our software from Shape Files to WFS.  I have hit a usability problem and found the following command too slow in a real world production environment :



layerFromFeatureLayerProvider.FeatureSource.GetFeaturesByColumnValue(SearchColumn, SearchValue)



My understanding (from watching the network traffic) is ALL features are being sent to the client from the server, then inside the ThinkGeo command, it filters out which Features match the criteria and return them to the calling method.  This is a massive amount of network traffic in our situation, taking almost a minute for each layer, making our product unusable.



1.  Do you have any plans to improve the usability of this command (Only retrieve what is required from the WFS, not all features in the layer)?



2.  Can you suggest another way to get a feature?  Our search criteria will only ever return one row (all rows are unique on this column).



Hi, Christian



If you just want to return one row each time I suggest that you use ExecuteScalar method of FeatureSource to get the feature id, and then call the GetFeatureById to get the feature you want. Here is the code for your requirement:\



// if you don't have a feature id for your dbf file, please first off use the code below row to build record id.
//ShapeFileFeatureSource.BuildRecordIdColumn(MapPath("~/SampleData/world/capital.shp"), "RECID", BuildRecordIdMode.DoNotRebuild);
int featureId = Convert.ToInt32(worldLayer.FeatureSource.ExecuteScalar("select RECID from [cntry02] where CNTRY_NAME='Finland'"));
Feature feature = worldLayer.FeatureSource.GetFeatureById(featureId.ToString(), ReturningColumnsType.AllColumns);

Thanks,

Khalil


Hi, 
  
 I cannot remember the post I created, but OleDbCommands ( ExecuteQuery, ExecuteReader, ExecuteScalal ) will only work on a 32 bit environment and not 64 bit.  I used the ExecuteQuery command in the past but had to remove it from our software to make it work on a 64 bit server. 
  
 The error was something like “The ‘Microsoft.Jet.OLEDB.4.0’ provider is not registered on the local machine.”  Enabling 32 bit compatability caused issues in another part of the system.  Do you have a 64 bit friendly solution? 
  
 Thankyou

I get the following error when executing the ExecuteScalar command against the WFS : 



Executing sql queries is not supported and the user should always check the CanExecuteSqlQueries to ensure the FeatureSource support it before calling. 



“I suggest that you use ExecuteScalar method of FeatureSource” 
  
 The title of this thread says “WfsLayer”. Why would you suggest using ExecuteScalar on a WfsLayer? A WFS is a Web Feature Service. You can’t execute Sql on a WFS. 
  
 Could you please acknowledge that what we have said is correct: 
  
 That when we execute GetFeaturesByColumnValue on the WfsFeatureLayer, all features are downloaded to the client and then filtered on the client side. 
  
 If this is not correct, please let us know and please tell us how we can work around this problem.

Hi, Damian 
  
 We have metioned in our Readme.rtf file that ShapeFileFeatureSource.ExecuteQuery function isn’t supported for 64 bit system, because the Microsoft.Jet.OLEDB 4.0 isn’t supported on a 64 bit system. 
  
 Thanks, 
 Khalil

This has nothing to do with the 64 bit problem (although that is annoying) 
  
 You can’t use ExecuteQuery with a WfsFeatureLayer regardless of the platform. 
  
 Please confirm this  
  
 “when we execute GetFeaturesByColumnValue on the WfsFeatureLayer, all features are downloaded to the client and then filtered on the client side”

I will sum the problem up again: 
  
 We execute this code: 
  
             if (!string.IsNullOrEmpty(ConfigurationSettings.AppSettings[“WFSUrl”])) 
             { 
                 foreach (var WFSLayerName in ConfigurationSettings.AppSettings[“WFSTypes”].Split(new char[] { ‘,’ })) 
                 { 
                     var layer = new WfsFeatureLayer(ConfigurationSettings.AppSettings[“WFSUrl”], WFSLayerName); 
                     Layers.Add(WFSLayerName, layer); 
                 } 
             } 
  
 Then later we execute this code (layer is a WfsFeatureLayer - not a ShapeFileFeatureLayer): 
  
                         featureCollection = layer.FeatureSource.GetFeaturesByColumnValue(SearchColumn, SearchValue); 
  
 This call takes several minutes to execute and downloads over 10 meg of data even though the call only returns 1 feature. 
  
 So, our assumption is that the ThinkGeo tools are downloading the entire feature set, and then filtering the features on the client side before the call has returned. Is this correct? What is the way to fix this?

Christian, 
  
 Yes, you are right. If you use GetFeaturesByColumnValue method of FeatureSource, it does download the entire feature data and then filter it.That’s becasue WfsFeatureSource don’t override this method but it inherits from FeatureSource default. So you could override GetFeaturesByColumnValue method to implement your logic in order to satisfy your own requirements; another option is that you could use the GetFeaturesInsideBoundingBoxCore method to require features which are inside a BoundingBox, and it could improve your performance. 
  
 Sorry for inconvenience; we will keep tracking this problem; We will let you know if we have any progress. 
  
 Thanks, 
 Khalil

“If you use GetFeaturesByColumnValue method of FeatureSource, it does download the entire feature data and then filter it” 
  
 Are there plans to fix this? 
  
 “That’s becasue WfsFeatureSource don’t override this method but it inherits from FeatureSource default” 
  
 That’s not correct. There is no such thing as the FeatureSource default because there are different ways of accessing different types of GIS systems. In the case of the WfsFeatureLayer, it calls a WFS Url and passes a Query String to it. The situation is totally different for ShapeFiles. Can I confirm that the WfsFeatureLayer is not sending a Filter parameter through the Query String? The Filter parameter is what should filter the records on the server side instead of filtering on the client side. 
  
 “So you could override GetFeaturesByColumnValue method to implement your logic in order to satisfy your own requirements” 
  
 Of course we could do this ourselves, but the questions is: will the ThinkGeo tools be fixed? 
  
 “you could use the GetFeaturesInsideBoundingBoxCore method to require features which are inside a BoundingBox, and it could improve your performance” 
  
 Do you mean “GetFeaturesInsideBoundingBox”? That function does not accept filters for column values. How does this solve the problem? 


Christian, 
  
 We have somebody working on that now and try to fix the issue you mentioned. I will let you know the results as soon as possible. 
  
 Thanks, 
  
 Johnny

OK. Thanks. 
  
 The first thing for the programmer to confirm is whether or not the WfsFeatureLayer is passing a Filter parameter in the Query String to the Wfs. 
  
 Christian

Christian, 
  
 Thanks for your post and suggestions. 
  
 Now, we are trying to dig out how to improve this performance by adding the filter string when sending request to the server side. If you have any insight into it, it would be appreciated. 
  
 Besides, could you provide us the URL link for your application, on which we could do more tests against it? 
  
 Thanks. 
  
 Yale 


Yale,


Have a look at the OGC spec. On page 94 it refers to the Filters parameter. The link is here:


opengeospatial.org/standards/wfs


The first thing to do is check whether or not the GetFeaturesByColumnValue method is passing in a "FILTERS" parameter. If it's not, you will have to do some research about it.


Here are two links which may have some information:


crisisgrid.org/html/wfs_implementation_issues.html


This one is from an organisation who has built a WFS and seems to be the most useful reference on filtering:


mapserver.org/ogc/filter_encoding.html


Please let me know what you find.


Christian



Sorry, I forgot to mention that it is not possible for our customers to expose their WFS as it contains information which needs to be secured by thier organisation.

Actually, here is the WFS Filter Encoding Spec. This should give you all the information you need: 
  
 portal.opengeospatial.org/files/?artifact_id=8339

Yale, 
  
 Good news. I have come across an example. Notice this Url with this query string returns only 1 record: 
  
 bsc-eoc.org/cgi-bin/bsc_ows.asp?version=1.0.0&service=WFS&request=getfeature&typename=IBA&filter=<Filter><PropertyIsEqualTo><PropertyName>SITEID</PropertyName><Literal>NU001</Literal></PropertyIsEqualTo></Filter> 
  
 But when you remove the Filter parameter, many records are returned: 
  
 bsc-eoc.org/cgi-bin/bsc_ows.asp?version=1.0.0&service=WFS&request=getfeature&typename=IBA 
  
 Could you please let us know when you have fixed this in the GetFeaturesByColumnValue? 
  
 BTW: This highlights another issue. WFS filtering is very flexible. You can filter on one column, many columns and you can filter with many different operators such as Equals, LessThan, MoreThan etc. Are there any plans to introduce this functionality? This would make searching through layers a lot more flexible. 
  
 Christian

In post above the QueryString was stripped out. Please send me your email address or some way I can contact you so I can send you the correct query string.

Christian, 
  
 Sorry for the delay on reply, my email address is yangyong@thinkgeo.com. Via which you can contact me directly. 
  
 Thanks. 
  
 Yale 


Christian, 
  
 Thanks for your information that guide us to make it. 
  
 I have overrided GetFeaturesByColumnValueCore method and use "Filter" that the user can only request the specified feature instead of all features. The perfomance would be better than before.  
  
 And you can get this enhancement by using the version of MapSuiteCore 3.1.419 or later, you can find it at Helpdesk.thinkgeo.com 
  
 Please let me know if you have more questions. 
  
 Thanks 
  
 James