Select to view content in your preferred language

Getting table from MakeQueryTable Geoprocessing result

1271
12
Jump to solution
09-02-2023 09:56 AM
AndreasMarth
Emerging Contributor

I am creating a table using the following code.

public async Task MakeQueryTable() {

    var created = await QueuedTask.Run(() => {
        
        bool tableCreated = false;
        string featureClassPath = @"c:\temp\test.gdb\in_featureclass";
        string tablePath = @"c:\temp\test.gdb\in_datatable";

        var valueArray = Geoprocessing.MakeValueArray(featureClassPath + ";" + tablePath, "queryTable", "USE_KEY_FIELDS", null,
            "in_featureclass.OBJECTID #; in_featureclass.ID #; in_featureclass.NAME #; in_datatable.ID #; in_datatable.NAME",
            "in_featureclass.ID = in_datatable.ID And in_featureclass.NAME = in_datatable.NAME");
        
        // Execute the task and DO NOT add the table to the current map!
        Task<IGPResult> gp_result = Geoprocessing.ExecuteToolAsync("management.MakeQueryTable", valueArray, flags: GPExecuteToolFlags.None);

        IGPResult makeTableResult = gp_result.Result;
        // makeTableResult now contains the name "queryTable"

        // Trying to open the table via 
        string newTablePath = @"c:\temp\test.gdb\" + makeTableResult.ReturnValue;

        // Opening this table leads to an error not able to open this table, because it dous not exist in Filegeodatabase

        // If you use GPExecuteToolFlags.AddOutputsToMap in ExecuteToolAsync then you can reference the table in the map
        var newStandaloneTable = MapView.Active.Map.GetStandaloneTablesAsFlattenedList().Where((l) => l.Name == "queryTable").FirstOrDefault() as StandaloneTable;

        return tableCreated;
    });
}

I used the option GPExecuteToolFlags.None, because the result is just a temporary table.

After executing the code, I found no way to get the table object from the GP-Result.

There is a workaround. When you add the table to the active map, the you can find the table there.

var newStandaloneTable = MapView.Active.Map.GetStandaloneTablesAsFlattenedList().Where((l) => l.Name == "queryTable").FirstOrDefault() as StandaloneTable;

 

Is there a way to get the table object without adding the result to the active map?

 

 

 

 

0 Kudos
1 Solution

Accepted Solutions
KenBuja
MVP Esteemed Contributor

Instead of using the geoprocessor to make the query table, can you use a query definition to make the query table from the geodatabase using the OpenQueryTable method?

View solution in original post

0 Kudos
12 Replies
GKmieliauskas
Esri Regular Contributor

Hi,

For the output path you can use the "memory" workspace (as noted here).

Look at this thread too:

Solved: How to copy feature class to in memory geodatabase - Esri Community

0 Kudos
AndreasMarth
Emerging Contributor

Hi,

thanks for your answer, but it seems that using a Memory Workspace does not work either. Same behaviour when I use the following code.

...
Geodatabase memGDB = new Geodatabase(memoryConnectionProperties);
var valueArray = Geoprocessing.MakeValueArray(featureClassPath + ";" + tablePath, @"memory\queryTable", "USE_KEY_FIELDS", ...

Task < IGPResult > gp_result = Geoprocessing.ExecuteToolAsync("management.MakeQueryTable", valueArray, flags: GPExecuteToolFlags.None);
...
// Leads to an error which says "Table does not exists"
Table resultTable = memGDB.OpenDataset<Table>("queryTable");

The task will be executed without any errors when using a memory GDB and returns a value containing "memory\queryTable", but I cant open/reference  the result table. Try to open the table leads to the error "Table does not exist". Any ideas?

By the way, I am using version SDK version 3.1

 

0 Kudos
GKmieliauskas
Esri Regular Contributor

Link, I suggested you, contains different geodatabase access code:

MemoryConnectionProperties memoryConnectionProperties = new MemoryConnectionProperties();
Geodatabase geodatabase = SchemaBuilder.CreateGeodatabase(memoryConnectionProperties);
0 Kudos
AndreasMarth
Emerging Contributor

Hi Gintautas, 

thank you for your reply, but using SchemaBuilder doesn't change anything, same result. 

By the way, I am not sure, if a Memory GeoDB can be used at all with "MakeQueryTable", because the result table is just a table name and not a full dataset name, and therefor the table should be always created  somewhere in the source database. 

If I add the result table to active map, the properties of the table contain the path of the input source datasets. But you cannot see the table when you try to open the table with standard functions, is must be some kind of temporary table, which is not displayed in the open dataset window.  

0 Kudos
GKmieliauskas
Esri Regular Contributor

Hi,

I have tried to make sample with output "memory\QueryTable". I have added parameter to geoprocessing tool to add result to map.  Geoprocessing created query table in my enterprise database where input data was located.

0 Kudos
AndreasMarth
Emerging Contributor

Hi,

there is no problem when you use a Memory database, when input data is located in this database,  and also no problem when you use the option "add result to map" (you can then locate the result table in the active view).

The main question was: How to get the table object from the GPResult created by "MakeQueryTable" when you do NOT add the result to the current map view.  I guess there is no difference when you use a MemoryDatabase or a FGDB on disk.

0 Kudos
GKmieliauskas
Esri Regular Contributor

I have added result to map to check result source path only. At it shows what the result was created inside inputs database.

So If you want to have result in memory workspace, your inputs must be in memory workspace too.

0 Kudos
raven403
New Contributor

This but there’s a lot of wonky things it doesn’t like. Basically any calculations or nests. We make views and publish them as a referenced feature layers. There’s virtually no documentation about the quirks with sql and feature layers https://mobdro.bio/ .

0 Kudos
KenBuja
MVP Esteemed Contributor

This is how I access the result of a geoprocessing tool when I don't add it to a map. This uses a memory geodatabase, but I have also done it using a regular geodatabase.

bool results = await QueuedTask.Run(async () =>
{
  MemoryConnectionProperties memoryConnectionProperties = new();
  using Geodatabase geodatabase = SchemaBuilder.CreateGeodatabase(memoryConnectionProperties);
  string path = "memory";

  //when I tested this using the geodatabase where the Featurelayer was stored, I used this code:
  //  using Geodatabase geodatabase = (Geodatabase)SelectedFrameFeatureLayer.GetFeatureClass().GetDatastore();
  //  string path = geodatabase.GetPath().AbsolutePath;

  IGPResult copyResult = await CopyFeatureClass(SelectedFrameFeatureLayer.GetFeatureClass(), path, "VirtualInputLayer", GPExecuteToolFlags.None);
  if (copyResult.IsFailed) return false;
  using FeatureClass virtualFC = geodatabase.OpenDataset<FeatureClass>("VirtualInputLayer");
  //
  // make calculations on the copied FC
  //
  return true;
});

    public static async Task<IGPResult> CopyFeatureClass(FeatureClass InFC, string OutputPath, string OutputName, GPExecuteToolFlags flags, string SQLExpression = null, string FieldMap = null, string ConfigurationKeyword = null)
    {
      List<object> arguments = new()
      {
        InFC, //Input features
        OutputPath, //Output location
        OutputName, //Output Name 
        SQLExpression, //Expression (optional)
        FieldMap, //Field Map optional)
        ConfigurationKeyword //Configuration Keyword (optional)
      };
      IGPResult result = await Geoprocessing.ExecuteToolAsync("conversion.FeatureClassToFeatureClass", Geoprocessing.MakeValueArray(arguments.ToArray()), null, null, null, flags);
      return result;
    }

 

0 Kudos