How do I use a local server to access the feature tables in a local File Geodatabase so that I can query and instantiate Feature objects?

1291
4
02-01-2019 08:25 AM
OrestHalustchak
New Contributor

I'm trying to determine how to access a File Geodatabase using the C++ Qt Runtime API. According to the information on this page, https://developers.arcgis.com/qt/latest/cpp/guide/supported-geodatabase-formats.htm, that should be possible if I use a local server.

What I need to be able to do is access the feature tables in the FGDB. If I can get to the point where I can instantiate an ArcGISFeatureTable class, then I know from there how to use queryFeatures() to get Feature objects, which is what I'm ultimately trying to do. I also am interested in editing those objects. The ArcGISFeatureTable class allow me to add, update, or delete features.

 

I know how to get the local server started. But, from that point, it's not clear from the documentation how actually to get the feature tables. I looked at the example called DynamicWorkspaceShapefile (https://github.com/Esri/arcgis-runtime-samples-qt/tree/master/ArcGISRuntimeSDKQt_CppSamples/LocalSer...) thinking that it would do something similar except with shp files. However, the example does not actually access the feature classes directly. It creates a map service and generates an image. I looked at the pattern of defining a FileGeodatabaseWorkspace (instead of a ShapefileWorkspace) and then a TableSubLayerSource, but it didn't seem to help me get to ArcGISFeatureTables.

 

An immediate issue is that this approach requires  a LocalFeatureService to be created which needs a map package (.mpk) file. In my case, I don't have a map and don't need a map. However, to try that approach I did get as far as using ArcMap to create a map package (.mpk) file from a map created from file gdb tables. I figured that from the local feature service, I could get a url that I could use for creating a ServiceFeatureTable.  Unfortunately, when I tried to load a local feature service defined from that mpk file, I got a load failed (not sure why yet, the errorOccurred signal wasn't triggered). Even if that had worked, it still would have been a round about way that accessed a packaged copy of the data and not a direct way to access the original fgdb.

So, my question is how do I use the local server to access the feature tables in a local fgdb so that I can instantiate Feature objects?

Regards.

0 Kudos
4 Replies
LucasDanzinger
Esri Frequent Contributor

The general workflow in the shapefile dynamic workspace sample should be what you follow for the file geodatabase - arcgis-runtime-samples-qt/DynamicWorkspaceShapefile.cpp at master · Esri/arcgis-runtime-samples-qt ·... 

The general workflow is:

  • create LocalMapService from blank MPK. You can use the one provided in the sample (https://www.arcgis.com/home/item.html?id=ea619b4f0f8f4d108c5b87e90c1b5be0 ). This doesn't mean you will need a map, it is just an intermediate step needed to start up a local map service.
  • Create a FileGeodatabaseWorkspace FileGeodatabaseWorkspace Class | ArcGIS for Developers 
  • Create TableSublayerSource
  • Set the dynamic workspace on the LocalMapService
  • Start the service
  • Once the service starts, you should see REST endpoints to Map Services that are spun up 
  • Create a ServiceFeatureTable by pointing to these REST endpoint URLs
  • You can then query the ServiceFeatureTable
0 Kudos
OrestHalustchak
New Contributor

Thanks Lucas.

When I tried those steps, I got a map service started but only the simple point layer from the mpk seems to be there. I think I'm missing a step of what to do with the TableSubLayerSource that I created.

Here is the code that I'm using.

    char* path = "E:/WaterNetwork/UtilityNetworkEditingAndAnalysisA4W/MapsandGeodatabase/WaterUtilities.gdb";
    pkgPath = QDir::homePath() + "/ArcGIS/Runtime/Data/mpk/mpk_blank.mpk";

    FileGeodatabaseWorkspace* fgdbWorkspace = new FileGeodatabaseWorkspace("fgdb_wkspc", path, this);
    TableSublayerSource* source = new TableSublayerSource(fgdbWorkspace->id(), path, this);

    LocalMapService* localMapServ = new LocalMapService(pkgPath, this);

    QList<DynamicWorkspace*> dynamicWorkspaces;
    dynamicWorkspaces.append(fgdbWorkspace);
    localMapServ->setDynamicWorkspaces(dynamicWorkspaces);

    connect(localMapServ, &LocalMapService::statusChanged, this, [&]()
    {
        if (localMapServ->status() == LocalServerStatus::Started)
        {
            qDebug() << "Local map service started, url =" << localMapServ->url();

            // Add code here to create a ServiceFeatureTable by pointing to these REST endpoint URLs

            emit localMapServLoadDone();
        }
        else if (localMapServ->status() == LocalServerStatus::Failed)
        {
            qDebug() << "Local map service failed";
            emit localMapServLoadDone();
        }

    });

    connect(localMapServ, &LocalMapService::errorOccurred, this, [&](Esri::ArcGISRuntime::Error error)
    {
        if (!error.isEmpty())
        {
            qDebug() << "Error on Local Map Service Start:" << error.message();
            showArcGISErrorMsg(error);
        }
    });

    localMapServ->start();

What do I need to do at the point where I have the comment about create ServiceFeatureTable? It seems that somewhere I need to do more with the TableSubLayerSource object.

From the above code, the map service url is http://127.0.0.1:50000/qpDB90/arcgis/rest/services/mpk_blank.mpk/MapServer .

Thanks,

Orest.

0 Kudos
JessicaTalbot1
New Contributor II

A TableSubLayerSource represents a single table or feature class, correct? If the file gdb contains multiple tables/feature classes, how do you interrogate the gdb to see what’s inside? Do you need to create a TableSubLayerSource for each feature class? 

0 Kudos
JessicaTalbot1
New Contributor II

This is where you would create an ArcGISMapImageLayer from the LocalMapService url, an ArcGISMapImageSublayer from the TableSublayerSource, and append ArcGISMapImageSublayer to ArcGISMapImageLayer::mapImageSublayers().  However, the TableSubLayerSource represents a single table or feature class, correct? If the file gdb contains multiple tables, how do you iterate through them??

0 Kudos