Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I have inherited a truly awful and very large ArcObjects project that was originally written in VB and then ported to C#. Apparently the source code I have been given is not the latest version and I am chasing down errors everywhere. The most challenging problem goes like this...

A number of tables are being joined (one after the other) to a Feature Layer via IDisplayRelationshipClass.DisplayRelationshipClass. Let's call these tables A and B (there are more than 2). Each of these tables has fields 1 and 2. The ITable objects are created by using IFeatureWorkspace.OpenTable with a DBF file.

After the first join if I check the fields in my Feature Layer and at the end I can see A.1 and A.2 (field name prefixed with the name of the DBF file the table came from) - Great! However, after the second join A.1 and A.2 are gone, and in their place I have B.1, B.2 - not so great...

Do I need to do anything to persist the additional fields across these joins, so that I end up with A.1, A.2, B.1, B.2 etc. ? If I do, either this behaviour has changed since the code was first written, or the code never worked. Given that the fields are properly prefixed they shouldn't be overwriting each other.

The joins are happening like this:

IMemoryRelationshipClassFactory pMemRelFact = new MemoryRelationshipClassFactoryClass();
IRelationshipClass pRelClass = pMemRelFact.Open("TabletoLayer", (IObjectClass)pTTable, dbfJnField, (IObjectClass)pFeatLayer.FeatureClass, layerJnField, "forward", "backward", esriRelCardinality.esriRelCardinalityOneToMany);

IDisplayRelationshipClass pDispRC = (IDisplayRelationshipClass) pFeatLayer;
pDispRC.DisplayRelationshipClass(pRelClass, esriJoinType.esriLeftInnerJoin);

Any assistance with this issue would be hugely appreciated.

EDIT: If this helps, I have observed something quite strange. After the join, pFeatLayer.FeatureClass.Fields.FieldsCount gives the original number of fields before the join, but ((ITable)pFeatLayer.Fields.FieldsCount gives the expected number (with joined fields). Unfortunately the pFeatLayer variable is then being passed back in to the join function, so it appears that tables are repeatedly being joined against the feature layer's initial state, hence only the last join making a difference.

Any suggestions for why an ITable cast would give a different field count to the FeatureClass? Is this a bug or just silly design??

share|improve this question
up vote 5 down vote accepted

This topic in the help deals with joining data and may offer a better workflow for your situation although I am not familiar enough with it to say for certain.

In your response to your edit, ITable respects joined fields but IFeatureClass does not. This is hinted at in the ISelectionSet help:

If you want to obtain a selection set on a feature layer it is good practice to cast the layer to the ITable interface then use the ITable::Select method. The table that you will obtain this way will mirror the content of the layer even if it has a definition query or a join.

share|improve this answer
1  
thanks for your input blah238, if the IFeatureClass property of the feature layer doesn't respect joins this would suggest that the code has never done what it's supposed to. – tomfumb Oct 25 '11 at 22:38

The question is old but since I had a hard time finding the answer to this and ended up on this page several times, I thought I would supplement the acccepted answer a bit.

I found the solution from ESRIs GeoNet:

"When you create a join in ArcMap, the join results in a table that is a combination of the two tables you've joined together. This table is used as the display source for the layer. If you want to add another join, then you need to join the table to the result of the first join. This will result in a table that is the combination of all 3 tables. You can do this by modifying your code to use the layer's display feature class instead of its feature class (IGeoFeatureLayer.DisplayFeatureClass)."

So, in this case a working code would be

Type memRelClassFactoryType = Type.GetTypeFromProgID("esriGeodatabase.MemoryRelationshipClassFactory");
IMemoryRelationshipClassFactory memRelClassFactory = (IMemoryRelationshipClassFactory)Activator.CreateInstance(memRelClassFactoryType);
IGeoFeatureLayer gfLayer = pFeatLayer as IGeoFeatureLayer;
IRelationshipClass pRelClass = pMemRelFact.Open("TabletoLayer", (IObjectClass)pTTable, dbfJnField, (IObjectClass)gfLayer.DisplayFeatureClass, layerJnField, "forward", "backward", esriRelCardinality.esriRelCardinalityOneToMany);

IDisplayRelationshipClass pDispRC = (IDisplayRelationshipClass)gfLayer;
pDispRC.DisplayRelationshipClass(pRelClass, esriJoinType.esriLeftInnerJoin);

In the above, I also replaced the original first line

IMemoryRelationshipClassFactory pMemRelFact = new MemoryRelationshipClassFactoryClass();

with a different way of creating IMemoryRelationshipClassFactory, this seemed to work for me. So, thanks to Neil Clemmons!

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.