Select to view content in your preferred language

Joined tables raise exceptions when GetDatasource(), GetDefinition() are called

617
8
02-08-2024 12:47 PM
TimSexton1
Occasional Contributor

When attempting to get a data store reference from a Table or Feature Class object, if that table or feature class has a join specified on it, then the GetDatastore() call fails with an exception.  I don't understand why this happens.  The Table or Feature Class with the join on it is not the actual Join object because you have to call GetJoin() to get that. So why not continue to treat the original table or feature class as the original dataset object and if you want to check for a join or get a Join object you can, but let the original table or feature class work like normal without these exceptions.

Below is what I have to do to get around this issue (everywhere).  The "table" object is a Table class that has a spatial join assigned to it in the map.  But to get the data store off that table without an exception I have to do this (see below).  My question is why and is there a better way to avoid this?  It feels like I'm just having to get the table from itself and that seems foolish.

                // Must check this because joined tables are virtual
                // and fail when GetDatastore() is called on them.
                if (table.IsJoinedTable())
                {
                    // The origin table is the original table
                    table = table.GetJoin().GetOriginTable();
                }

 

8 Replies
Aashis
by Esri Contributor
Esri Contributor

Please refer to the Joins conceptual doc.

Aashis_0-1707430248049.png

 

0 Kudos
TimSexton1
Occasional Contributor

Aashis,

Thank you for your response and for providing the documentation on joins.  Unfortunately this is not what I'm looking for and I believe you missed my point as I do not want to create or work with a join, I'm having to work around one.  I will try to explain the issue a little better and in more detail below.

Below is what we are trying to do
Using the ArcGIS Pro SDK, we are getting a reference to a MapMember in the table of contents of a Map in an ArcGIS Pro project.  From that MapMember, which in this case is a FeatureLayer, we get a reference to it's Dataset which is a FeatureClass.  From that feature class object, we want to get a reference to it's data store, a Geodatabase, by calling GetDatastore().

The problem we are running into
If the end user has created a Join on that particular MapMember/Layer/FeatureLayer in the map, the underlying FeatureClass object is getting changed after the join is created.  This means that where before the end user did the join I could call FeatureClass.GetDatastore() without issue, now I get an exception making the exact same call on what appears to be the exact same object.

So fundamentally, the Dataset object (Table or FeatureClass) that is returned from the MapMember is not reliable.  Without constantly checking to see if the end user performed a join, how are we supposed to rely on these objects and their methods?

Primary goal we are trying to achieve
To clarify, I am not performing the Join in code nor do I care if a Join has been created, all I want is a reference to the MapMember/FeatureLayer/FeatureClasses Datastore without having to jump through hoops every time because the end user may have performed a join in the ArcGIS Pro UI.  A Dataset/Table/FeatureClass should always be a Dataset/Table/FeatureClass at all times without changing how it's methods and properties work based on what a user has done in the map.

I hope this helps explain what I'm seeing.  If you can help me understand a better, more reliable way to get a reference to a Datastore from a MapMember (no matter if a join exists or not) that would be great.  Maybe I've been going about that the wrong way.

Aashis
by Esri Contributor
Esri Contributor

@TimSexton1  What version of the Pro and Geodatabase are you using? I could not repro the issue on my end. 

0 Kudos
TimSexton1
Occasional Contributor

We are using ArcGIS Pro 3.2.2 with a file geodatabase version 10.0.  See images below for confirmation.

versionInfo.png

 

TimSexton1
Occasional Contributor

I created and attached a sample ArcGIS Pro project and sample Addin to demonstrate the issue so you can reproduce this exactly the way we are seeing it.  See attached.

Aashis
by Esri Contributor
Esri Contributor

Hi @TimSexton1 
The joined table doesn't have a data store; by design, part of it can be from two different data stores.

There are two ways to get the data store info from a map member: first, directly from the feature layer using the CIM connection, featurelayer.GetDataConnection(), and second, from the feature class, as you have written. However, in both cases, you need to check for any existing joins on a member and tell SDK explicitly which data store you are referring, origin or destination. If no joins exist, it always points to the source.

Using feature class:

 

// GetDefinitionFromLayer - This code works even if the layer has a join to another table
private TableDefinition GetDefinitionFromLayer(FeatureLayer featureLayer)
{
  // Get feature class from the layer
  FeatureClass featureClass = featureLayer.GetFeatureClass();

  // Determine if feature class is a join
  if (featureClass.IsJoinedTable())
  {
    // Get join from feature class
    Join join = featureClass.GetJoin();

    // Get origin table from join
    Table originTable = join.GetOriginTable();

    // Return feature class definition from the join's origin table
    return originTable.GetDefinition();
  }
  else
  {
    return featureClass.GetDefinition();
  }
}

 

Using feature layer:

 

CIMRelQueryTableDataConnection cim = featureLayer.GetDataConnection() as CIMRelQueryTableDataConnection;
CIMStandardDataConnection sourceTable = cim.SourceTable as CIMStandardDataConnection ;

WorkspaceFactory wsFactory = sourceTable.WorkspaceFactory;
string path = sourceTable.WorkspaceConnectionString;
path = path.Replace("DATABASE=", "");

string datasetSetName = sourceTable.Dataset;

if (wsFactory == WorkspaceFactory.FileGDB)
{
	Geodatabase geodatabase = new Geodatabase(new FileGeodatabaseConnectionPath(new Uri(path, UriKind.Absolute)));
	FeatureClass featureClass = geodatabase.OpenDataset<FeatureClass>(datasetSetName);
	FeatureClassDefinition featureClassDefinition = featureClass.GetDefinition();
}

 

 

0 Kudos
TimSexton1
Occasional Contributor

Thank you for that additional information and code sample.  So basically anywhere GetDatastore() or GetDefinition() needs to be called we must first check with IsJoinedTable() to prevent an exception when not opening a feature class directly from the geodatabase?  We cannot trust that the user didn't performed a temporary join on a layer in the map at any given time.

Aashis
by Esri Contributor
Esri Contributor

Yes.

0 Kudos