Is it possible to use the .NET runtime SDK to query multiple layers of a feature service at once?

3614
2
04-16-2015 08:24 AM
meme2
by
New Contributor II

I'm looking to use the Feature Service Query API, and query multiple layers at once.

So, building off the example on the query API page, I want the query to look something like this:

http://<featureservice-url>/query?layerDefs=[{"layerId":<layerDef1>},{"layerId":<layerDef2>}]&geometry=<geometry>&f=json

And I can't seem to be able to figure out how to get that through the .NET runtime SDK (without resorting to using an ArcGISHttpClient).  Any suggestions?

0 Kudos
2 Replies
MichaelBranscomb
Esri Frequent Contributor

Hi,

The QueryTask class works against a single layer in a service, whereas the IdentifyTask and FindTask work against multiple layers in a service. It sounds like you might be able to use the IdentifyTask in your case, to provide a geometry filter which will return all features in layers from the service which intersect the geometry?

- Samples for the query task classes (Find / Identify / Query): arcgis-runtime-samples-dotnet/src/Desktop/ArcGISRuntimeSDKDotNet_DesktopSamples/Samples/QueryTasks a...​​

- API ref for the Tasks.Query namespace (Esri.ArcGISRuntime.Tasks.Query Namespace).

Depending on your exact workflow, you might also like to look at the ServiceFeatureTable Query method: ArcGISFeatureTable.QueryAsync Method (QueryFilter)

Cheers

Mike

0 Kudos
meme2
by
New Contributor II

Thanks Michael!

With the IdentifyTask, can I return certain fields along with the feature (like the outFields query parameter)?  I'm looking to pull in a bunch of data from a feature service as quickly as possible.  So, I'd rather not query every layer individually.  Plus, I need certain fields on the features returned.

I did write a quick wrapper around the feature service query:

    public class QueryEntry
    {
        private readonly int _layerId;
        private readonly string _whereClause;
        private readonly string _outFields;

        public QueryEntry(int layerId, string whereClause, string outFields)
        {
            _layerId = layerId;
            _whereClause = whereClause;
            _outFields = outFields;
        }

        [JsonProperty("layerId")]
        public int LayerId { get { return _layerId; } }

        [JsonProperty("where")]
        public string WhereClause { get { return _whereClause; } }

        [JsonProperty("outFields")]
        public string OutFields { get { return _outFields; } }
    }

    public class QueryOperation
    {
        private readonly IEnumerable<QueryEntry> _queries;
        private readonly Esri.ArcGISRuntime.Geometry.Geometry _geometry;
        private readonly SpatialReference _inSpatialReference;
        private readonly SpatialReference _outSpatialReference;

        public QueryOperation(IEnumerable<QueryEntry> queries,
            Esri.ArcGISRuntime.Geometry.Geometry geometry = null,
            SpatialReference inSpatialReference = null,
            SpatialReference outSpatialReference = null)
        {
            _queries = queries;
            _geometry = geometry;
            _inSpatialReference = inSpatialReference;
            _outSpatialReference = outSpatialReference;
        }

        public override string ToString()
        {
            var edits = JsonConvert.SerializeObject(_queries);
            var options = new StringBuilder();
            if (_geometry != null) { options.Append(String.Format("&geometry={0}&geometryType=esriGeometry{1}", _geometry.ToJson(), _geometry.GeometryType)); }
            if (_inSpatialReference != null) { options.Append(String.Format("&inSR={0}", _inSpatialReference.ToJson())); }
            if (_outSpatialReference != null) { options.Append(String.Format("&outSR={0}", _outSpatialReference.ToJson())); }
            return String.Format("layerDefs={0}{1}&f=pjson", edits, options);
        }
    }

And then it can be used like this:

var client = new ArcGISHttpClient();
var queryEntries = new List<QueryEntry>();
// Generate QueryEntries
var queryOp = new QueryOperation(queryEntries, geometry);
var content = new StringContent(queryOp.ToString());
content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
var result = await client.PostAsync(service.Uri + "/query", content);
var json = await result.Content.ReadAsStringAsync();

That seems to give me what I want, but it feels like I'm rewriting something that already exists in the .NET runtime SDK.