Take the 2-minute tour ×
Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. It's 100% free, no registration required.

I already know how to do a table join with ArcObjects, via the IDisplayTable, IMemoryRelationshipClassFactory etc. interfaces. Here are some links to resources that have example code for this:

What I need to know is, how do I undo, i.e. remove such a join?


Once I've joined a standalone table to a feature layer, I end up with references to:

  • an IRelationshipClass (resulting from the join operation);

  • an ITable/IStandaloneTable/IDisplayTable (the table that was joined to the feature layer); and

  • an IFeatureLayer (the feature layer to which the table was joined).

Do these interfaces, or rather the objects behind them, allow unjoining at all? I've seen that IRelationshipClass has various DeleteRelationship… methods, but I can't see how they could work towards that end.

share|improve this question

6 Answers 6

up vote 5 down vote accepted

Code below works for me for a featurelayer. Similar logic could be used for a standalone table.

private void RemoveAllJoins(IFeatureLayer fLayer)
{
    var dispTable = fLayer as IDisplayTable;
    var rqt = dispTable.DisplayTable as IRelQueryTable;
    if (rqt != null)
    {
        Debug.Print("source: {0}", ((IDataset)rqt.DestinationTable).Name);
        Debug.Print("dest: {0}", ((IDataset)rqt.SourceTable).Name);
        fLayer.FeatureClass = (IFeatureClass)rqt.DestinationTable;
    }
    else
        Debug.Print("there are no joins");
}

The documentation for IRelQueryTable at 10 seems to be missing this important graphic, that appears in 8.3 help doc:

enter image description here

share|improve this answer
    
Is it really that simple!? Do you think that the assignment featureLayer.FeatureClass = destinationTable will also trigger the disposal of the MemoryRelationshipClass? That is, a memory relationship class doesn't have to be "undone" explicitly? –  stakx Jun 16 '11 at 12:22
    
I think a memoryrelationshipclass is used behind the scenes to create the relquerytable. The complications I see are handling cases where the renderer might be using related fields, or refreshing the tableview (if it is open). –  Kirk Kuykendall Jun 16 '11 at 13:46
    
thanks for your answer and the comment, which both provided me with the right clues. I ended up doing a different join than I thought (two IStandaloneTable via IMemoryRelationshipClass, then feeding that into a RelQueryTableFactory). Turns out the IMemoryRelationshipClass isn't all that important, as you said. –  stakx Jun 16 '11 at 21:39
    
+1 Perfect answer Kirk! –  Petr Krebs Jul 26 '11 at 20:49

It depends on your workflow, but you can always remove joins using built in geoprocessing. You just need the layer or table view and the name of your join.

Alternatively, like you were exploring, you can operate on the IRelationshipClass and call DeleteRelationshipsForObject. This requires you to be in an edit session and assumes you don't require any other joins to remain on the object you're working with.

share|improve this answer

The code above did not work for me with ArcGIS 10. It needs a little improvement:

IFeatureLayer2 actFeatLyr = focMap.get_Layer(i) as IFeatureLayer2;
ITable actLyr = focMap.get_Layer(i) as ITable;
IDisplayTable actDispTable = actFeatLyr as IDisplayTable;
IRelQueryTable actQueryTable = actDispTable.DisplayTable as IRelQueryTable;
IDisplayRelationshipClass actDispRelClass = actFeatLyr as IDisplayRelationshipClass;

actDispRelClass.DisplayRelationshipClass(null, esriJoinType.esriLeftInnerJoin);

I found the solution in the ArcGis 10 documentation, under the VBA-section, after hours of searching and trying with IRelationshipClass.

share|improve this answer
    
Thank you for sharing your experience with us. Welcome to our community! –  whuber Jul 26 '11 at 14:04
    
Just curious - what did the code I posted do when you ran it? What happens if you run it twice? –  Kirk Kuykendall Jul 26 '11 at 16:55

I know this is years late, but I struggled with this as well and, for me, Kirk's answer working successfully depended on how the join was created. I don't have enough rep to comment on Kirk's answer, but it threw an exception until I changed it to what's below. Namely, I switched sourceTable and destinationTable. I also had to add the ComReleaser for the lock file to be removed from the standalone table, which in my case was a DBF.

private void RemoveAllJoins2(ESRI.ArcGIS.Carto.IFeatureLayer joinedLayer)
{
    using (ESRI.ArcGIS.ADF.ComReleaser comReleaser = new ESRI.ArcGIS.ADF.ComReleaser())
    {
        var dispTable = joinedLayer as ESRI.ArcGIS.Carto.IDisplayTable;
        comReleaser.ManageLifetime(dispTable);
        var rqt = dispTable.DisplayTable as ESRI.ArcGIS.Geodatabase.IRelQueryTable;
        if (rqt != null)
        {
            comReleaser.ManageLifetime(rqt);
            var sourceTable = rqt.SourceTable as ESRI.ArcGIS.Geodatabase.IDataset;
            var destTable = rqt.DestinationTable as ESRI.ArcGIS.Geodatabase.IDataset;
            comReleaser.ManageLifetime(destTable);
            System.Diagnostics.Debug.Print("source: {0}", sourceTable.Name);
            System.Diagnostics.Debug.Print("dest: {0}", destTable.Name);
            joinedLayer.FeatureClass = (ESRI.ArcGIS.Geodatabase.IFeatureClass)sourceTable;
        }
        else
            System.Diagnostics.Debug.Print("there are no joins");
    }            
}

Finally, the above method (RemoveAllJoins2) only worked for joins that were created with a RelQueryTable. It did not remove joins that were created in ArcMap with the Join tool in ArcToolbox, or by the join tool accessed via the Join and Relates menu item in the context menu of a layer. It also did not remove joins that were created with IDisplayRelationshipClass in ArcObjects. The sample below (AddJoins2) is the only type of join I could create that was removed with the RemoveAllJoins2. Additionally, I could not remove the join created by AddJoins2 via the Remove Join tool in ArcToolbox, or with the Join and Relates menu item, or by setting the IDisplayRelationshipClass.DisplayRelationshipClass to null.

private void AddJoins2(ESRI.ArcGIS.Carto.IFeatureLayer inputLayer, string inputJoinField, ITable joinTable, string outputJoinField)
{
    // Build a memory relationship class. 
    Type memRelClassFactoryType = Type.GetTypeFromProgID("esriGeodatabase.MemoryRelationshipClassFactory");
    IMemoryRelationshipClassFactory relationshipFactory = (IMemoryRelationshipClassFactory)Activator.CreateInstance(memRelClassFactoryType);
    string joinName = inputLayer.Name + "_" + ((IDataset)joinTable).Name;
    using (ESRI.ArcGIS.ADF.ComReleaser comReleaser = new ESRI.ArcGIS.ADF.ComReleaser())
    {
        IRelationshipClass rClass = relationshipFactory.Open(joinName, inputLayer.FeatureClass, inputJoinField, (IObjectClass)joinTable, outputJoinField, "ForwardPath", "BackwardPath", esriRelCardinality.esriRelCardinalityOneToOne);
        comReleaser.ManageLifetime(rClass);
        // Open the RelQueryTable as a feature class. 
        Type rqtFactoryType = Type.GetTypeFromProgID("esriGeodatabase.RelQueryTableFactory");
        IRelQueryTableFactory rqtFactory = (IRelQueryTableFactory)Activator.CreateInstance(rqtFactoryType);
        IRelQueryTable relQueryTable = rqtFactory.Open(rClass, true, null, null, String.Empty, false, true);
        // Set the feature layer's feature class to the RelQueryTable feature class
        inputLayer.FeatureClass = (IFeatureClass)relQueryTable;
    }
}
share|improve this answer

One additional answer that successfully removes joins created with the Join tool in ArcToolbox, or with the Joins and Relates menu item on the context menu of a layer, or with a Join that is created with an IDisplayRelationshipClass. This method is considerably slower than the RemoveAllJoins3 method I also posted.

private void RemoveAllJoins4(ESRI.ArcGIS.Carto.IFeatureLayer joinedLayer, string joinToRemove = null)
{
    ESRI.ArcGIS.Geoprocessor.Geoprocessor gp = new ESRI.ArcGIS.Geoprocessor.Geoprocessor();
    ESRI.ArcGIS.DataManagementTools.RemoveJoin removeJoinTool = new ESRI.ArcGIS.DataManagementTools.RemoveJoin();
    removeJoinTool.in_layer_or_view = joinedLayer;
    removeJoinTool.join_name = joinToRemove;
    try { gp.Execute(removeJoinTool, null); }
    catch (Exception ex) { System.Diagnostics.Debug.Print(ex.Message); }
}
share|improve this answer

I know I posted one answer, but I have a few alternatives to removing the joins that don't have code samples posted. This method successfully removes joins that are created with the Join tool in ArcToolbox, or with the Joins and Relates menu item on the context menu of a layer, or with a Join that is created with an IDisplayRelationshipClass. As in my answer above, I had to use the ComReleaser to release the lock on the standalone table, even though the join was successfully removed without it.

private void RemoveAllJoins3(ESRI.ArcGIS.Carto.IFeatureLayer joinedLayer)
{
    using (ESRI.ArcGIS.ADF.ComReleaser comReleaser = new ESRI.ArcGIS.ADF.ComReleaser())
    {
        ESRI.ArcGIS.Carto.IDisplayRelationshipClass drClass = (ESRI.ArcGIS.Carto.IDisplayRelationshipClass)joinedLayer;
        ESRI.ArcGIS.Geodatabase.IRelationshipClass rClass = drClass.RelationshipClass;
        comReleaser.ManageLifetime(rClass);
        IObjectClass originClass = rClass.OriginClass;
        comReleaser.ManageLifetime(originClass);
        IObjectClass destinationClass = rClass.DestinationClass;
        comReleaser.ManageLifetime(destinationClass);
        drClass.DisplayRelationshipClass(null, esriJoinType.esriLeftInnerJoin);                
    }
}

An example of a join created with ArcObjects that RemoveAllJoins3 will work successfully with is AddJoin3 below.

private void AddJoins3(ESRI.ArcGIS.Carto.IFeatureLayer inputLayer, string inputJoinField, ITable joinTable, string outputJoinField)
{
    // Build a memory relationship class. 
    Type memRelClassFactoryType = Type.GetTypeFromProgID("esriGeodatabase.MemoryRelationshipClassFactory");
    IMemoryRelationshipClassFactory relationshipFactory = (IMemoryRelationshipClassFactory)Activator.CreateInstance(memRelClassFactoryType);
    string joinName = inputLayer.Name + "_join";
    using (ESRI.ArcGIS.ADF.ComReleaser comReleaser = new ESRI.ArcGIS.ADF.ComReleaser())
    {
        IRelationshipClass rClass = relationshipFactory.Open(joinName, inputLayer.FeatureClass, inputJoinField, (IObjectClass)joinTable, outputJoinField, "ForwardPath", "BackwardPath", esriRelCardinality.esriRelCardinalityOneToOne);
        comReleaser.ManageLifetime(rClass);
        ESRI.ArcGIS.Carto.IDisplayRelationshipClass drClass = ((ESRI.ArcGIS.Carto.IDisplayRelationshipClass)inputLayer);
        drClass.DisplayRelationshipClass(rClass, esriJoinType.esriLeftOuterJoin);
    }
}
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.