ccposton

Joining an external table to a geo-feature layer

Discussion created by ccposton on Oct 10, 2012
Latest reply on Oct 10, 2012 by richwawr
I'm trying to join an external table to a IGeoFeatureLayer, and it works well. The problem is when I save this map and then reload the .mxd, the FeatureClass of the layer is null, and the Table of Contents shows a warning symbol next to the layer. Is it failing to serialize/deserialize the joined feature class? What is the correct approach to solve this problem?

Here's the code I'm using:

  string externalFields = GetExternalFields(joinFields);

  ITable table = GetExternalTable(externalFields);

  geoFeatureLayer.FeatureClass = CreateFeatureClass(table, externalFields);

// ...

  private ITable GetExternalTable(string externalFields)
  {
   IWorkspaceFactory2 workspaceFactory2;
   IWorkspace workspace;
   ISqlWorkspace sqlWorkspace;
   ITable table;

   using (var comReleaser = new ComReleaser())
   {
    var query = string.Format(
     QUERY_BASE, externalFields, synchronizer.LayerManager.ParcelLayer.GetParcelYear()
    );
    var factoryType = Type.GetTypeFromProgID("esriDataSourcesGDB.SqlWorkspaceFactory");

    workspaceFactory2 = Activator.CreateInstance(factoryType) as IWorkspaceFactory2;
    workspace = workspaceFactory2.OpenFromString(this.connection, 0);
    sqlWorkspace = workspace as ISqlWorkspace;

    comReleaser.ManageLifetime(workspaceFactory2);
    comReleaser.ManageLifetime(sqlWorkspace);

    var queryDescription = sqlWorkspace.GetQueryDescription(query);
    queryDescription.OIDFields = EXTERNAL_KEY;

    var datasetName = "S";
    sqlWorkspace.CheckDatasetName("S", queryDescription, out datasetName);

    table = sqlWorkspace.OpenQueryClass(datasetName, queryDescription);
   }

   return table;
  }

  private IFeatureClass CreateFeatureClass(ITable externalTable, string externalFields)
  {
   IGeoFeatureLayer geoFeatureLayer = synchronizer.LayerManager.ParcelLayer as IGeoFeatureLayer;
   IMemoryRelationshipClassFactory memoryRelationshipFactory = null;
   IRelQueryTableFactory relQueryTableFactory = null;
   IRelQueryTable relQueryTable = null;

   try
   {
    var memoryRelationshipClassFactory = Type.GetTypeFromProgID("esriGeodatabase.MemoryRelationshipClassFactory");
    memoryRelationshipFactory = Activator.CreateInstance(memoryRelationshipClassFactory) as IMemoryRelationshipClassFactory;

    var relationshipClass = memoryRelationshipFactory.Open(
     "Join",
     geoFeatureLayer.DisplayFeatureClass as IObjectClass,
     FEATURE_KEY, externalTable as IObjectClass, EXTERNAL_KEY,
     "forward", "backward", esriRelCardinality.esriRelCardinalityOneToOne
    );

    var relQueryTableFactoryType = Type.GetTypeFromProgID("esriGeodatabase.RelQueryTableFactory");
    relQueryTableFactory = Activator.CreateInstance(relQueryTableFactoryType) as IRelQueryTableFactory;

    relQueryTable = relQueryTableFactory.Open(
     relationshipClass, true, null, null, externalFields, true, true
    ) as IRelQueryTable;
   }
   finally
   {
    Marshal.FinalReleaseComObject(memoryRelationshipFactory);
    Marshal.FinalReleaseComObject(relQueryTableFactory);
   }

   return relQueryTable as IFeatureClass;
  }
 }

Outcomes