Retrieving data from a CIMFeatureLayer (no Desktop namespace)

1117
3
Jump to solution
12-30-2020 01:45 PM
DavidLaMartina
New Contributor III

My team is working on removing Desktop namespace references throughout our code in order to create a standalone application that doesn't rely on the Arc Pro GUI. One of the things we need to do is get data from map layers.

We can pull in the CIMMap and associated CIMFeatureLayers from a CIMLayoutDocument that describes the layout we want to render. Since we're not using the Desktop namespace, however (and since our starting point is a CIMLayoutDocument, not a Map), we can't use the FeatureLayer class's search functions.

I know Core.Data contains the Database class (along with Geodatabase and other children of Datastore). These classes seem to offer some of the functionality that we need, but we also have a home-grown class that reads through a Geodatabase given a path - either .gdb or .sde. For a layer added via a geodatabase, this makes things simple - just get the gdb path from the CIMFeatureLayer's FeatureTable's DataConnection, and use it to instantiate said home-grown class.

However, I'm wondering what to do when features from a SQL or Oracle database have been added to the map. Creating that connection in the Arc Pro Catalog automatically creates an SDE file, but when I look at the corresponding CIMFeatureLayer object in the corresponding CIMLayoutDocument, I don't see a direct reference to that .sde. Instead I see the WorkspaceConnectionString, which contains what appear to be all the necessary connection properties to instantiate a Core.Data Database object.

Let's say I just wanted to grab the .sde path associated with the enterprise database used to add that feature layer to the map....Would I need to create a Database object with the constructor that calls for a DatabaseConnectionProperties object? If so, is there a built-in way to parse the WorkspaceConnectionString into a set of DB connection properties? It seems rather roundabout, but what I would be doing is:

-parse the WorkspaceConnectionString for the Oracle / SQL (SDE) connection into its constituent properties

-create a DatabaseConnectionProperties object using those parsed properties

-Instantiate a Database object using that DatabaseConnectionProperties object

-Call GetPath() on the newly instantiated Database, which hopefully would give me some path to the .sde I need.

Is there a simpler way to do this?

1 Solution

Accepted Solutions
KirkKuykendall1
Occasional Contributor III

Featurelayers based on shapefiles use a CIMStandardDataConnection, whose JSON can be parsed to get the info needed to open via a FileSystemDatastore:

public static void OpenShapefile()
{
    var folder = @"D:\tests\myfolder";
    var shpName = "myshapefile";
    var connPath = new FileSystemConnectionPath(
        new Uri(folder), FileSystemDatastoreType.Shapefile);
    using (var store = new FileSystemDatastore(connPath))
    {
        using (var fc = store.OpenDataset<FeatureClass>(shpName))
        {
            Debug.Print($"{fc.GetCount()}");
        };
    }
}

 

 

 

View solution in original post

3 Replies
KirkKuykendall1
Occasional Contributor III

When you add a featurelayer that references an sde featureclass, it copies the properties from the .sde file into the featurelayer's definition - it does not retain the path to the original .sde file. 

When connecting via DatabaseConnectionProperties, calling GetPath() on the resulting Geodatabase returns a path to a scratch .sde file (i.e. C:\Users\username\AppData\Local\Temp\34f33d39a4b968aa75a6079324b8ebce.sde)

To be able to parse the connection string, you'll need to use OS Auth connections - you (hopefully) won't be able to decrypt the password found in the connection string that's there when using DBMS auth.

If you really need to keep track of sde file paths, you might consider storing it in the layer's description.

DavidLaMartina
New Contributor III

@KirkKuykendall1 thanks so much for the help. Do you know what you'd do in the case of a FeatureLayer based on a Shapefile?

0 Kudos
KirkKuykendall1
Occasional Contributor III

Featurelayers based on shapefiles use a CIMStandardDataConnection, whose JSON can be parsed to get the info needed to open via a FileSystemDatastore:

public static void OpenShapefile()
{
    var folder = @"D:\tests\myfolder";
    var shpName = "myshapefile";
    var connPath = new FileSystemConnectionPath(
        new Uri(folder), FileSystemDatastoreType.Shapefile);
    using (var store = new FileSystemDatastore(connPath))
    {
        using (var fc = store.OpenDataset<FeatureClass>(shpName))
        {
            Debug.Print($"{fc.GetCount()}");
        };
    }
}