Select to view content in your preferred language

Running geoprocessing tool using memory feature class works the first time, but fails the next time

1405
5
Jump to solution
12-19-2022 01:11 PM
KenBuja
MVP Esteemed Contributor

In my add-in, I'm creating random points using a constraining feature class with the Create Random Points tool. However, since the tool creates the number of points for each feature in the constraining feature class, I first dissolve the feature class and use that as the constraining feature class. I use a temporary file name for the dissolved feature class and delete it after creating the points.

private Geodatabase MemoryGeodatabase; //set elsewhere
private SchemaBuilder MemorySchemaBuilder; //set elsewhere

MemoryConnectionProperties memoryConnectionProperties = new();
string tempFileName = Path.GetFileNameWithoutExtension(Path.GetTempFileName());
using (MemoryGeodatabase ??= SchemaBuilder.CreateGeodatabase(memoryConnectionProperties))
{
  MemorySchemaBuilder ??= new(MemoryGeodatabase);
  StatusMessage = $"Dissolving {SelectedFrameFeatureLayer.Name}...";
  IGPResult dissolveResult = await DissolveFeatures(frameFeatureClass, "", "", $"memory\\{tempFileName}", GPExecuteToolFlags.AddToHistory);
  if (dissolveResult.IsFailed)
  {
    Show_Status_Bar = false;
    StatusMessage = "";
    MessageBox.Show("Dissolving feature class failed");
    return;
  }
  using (FeatureClass dissolveFC = MemoryGeodatabase.OpenDataset<FeatureClass>(tempFileName))
  {
    string Distance = "";
    if (Use_Minimum_Distance && Minimum_Distance > 0) Distance = $"{Minimum_Distance} {SR.Unit.ToString().ToLower()}";
    StatusMessage = "Generating points...";
    IGPResult CreateRandomPointsResult = await CreateRandomPoints($"memory\\{tempFileName}", Path.GetDirectoryName(outputFileName), Path.GetFileName(outputFileName), SimpleRandomCount, Distance, GPExecuteToolFlags.AddOutputsToMap);

    FeatureClassDescription DissolveFCDescription = new(dissolveFC.GetDefinition());
    MemorySchemaBuilder.Delete(DissolveFCDescription);
    MemorySchemaBuilder.Build();
  }
}

This runs properly the first time, but if I run it again, it throws an error on line 16 when it gets the temporary layer. The layer is created according to the history, but I get the error

 "Could not open the dataset 'tmp5EB3' of type FeatureClass. Please make sure a valid geodatabase or data store has been opened first."

dissolve.png

Why isn't this working on the second attempt?

0 Kudos
1 Solution

Accepted Solutions
Aashis
by Esri Contributor
Esri Contributor

Hi @KenBuja 

I cannot replicate the issue on my machine, and the following code snippets work for me. See if it works for you.

 

    protected override void OnClick()
    {
      QueuedTask.Run(async () =>
      {
        MemoryConnectionProperties memoryConnectionProperties = new MemoryConnectionProperties();
        using (Geodatabase memoryGeodatabase = new Geodatabase(memoryConnectionProperties))
        {
          SchemaBuilder schemaBuilder = new SchemaBuilder(memoryGeodatabase);

          IReadOnlyList<string> dissolveParamsValueArray = Geoprocessing.MakeValueArray(@"C:\Default.gdb\FrameFeatureClass", @"memory\FrameFeatureClass_Dissolved", null, null, "MULTI_PART", "DISSOLVE_LINES", null);
          IGPResult dissolveResult = await Geoprocessing.ExecuteToolAsync("management.Dissolve", dissolveParamsValueArray, null, CancelableProgressor.None, GPExecuteToolFlags.AddToHistory);

          if (dissolveResult.IsFailed)
          {
            System.Diagnostics.Debug.WriteLine("Dissolve errors");
          }

          using (FeatureClass dissolveFc = memoryGeodatabase.OpenDataset<FeatureClass>("FrameFeatureClass_Dissolved"))
          using (FeatureClassDefinition dissolveDefn = dissolveFc.GetDefinition())
          {
            IReadOnlyList<string> createPointsParamsValueArray = Geoprocessing.MakeValueArray(@"memory", "RandomPointsFC", @"memory\FrameFeatureClass_Dissolved", new List<dynamic>() { 0, 0, 250, 250 }, 100, "5 Meters", "POINT", 10);
            IGPResult createRandomPointsMessage = await Geoprocessing.ExecuteToolAsync("management.CreateRandomPoints", createPointsParamsValueArray, null, CancelableProgressor.None, GPExecuteToolFlags.AddOutputsToMap);

            if (createRandomPointsMessage.IsFailed)
            {
              System.Diagnostics.Debug.WriteLine("Create random points errors");
            }

            schemaBuilder.Delete(new FeatureClassDescription(dissolveDefn));
            bool deleteStatus = schemaBuilder.Build();
            if (!deleteStatus)
            {
              System.Diagnostics.Debug.WriteLine("Delete feature class failed");
            }
          }
        }
      });
    }

 

 

 

View solution in original post

0 Kudos
5 Replies
Aashis
by Esri Contributor
Esri Contributor

Hi @KenBuja 

I cannot replicate the issue on my machine, and the following code snippets work for me. See if it works for you.

 

    protected override void OnClick()
    {
      QueuedTask.Run(async () =>
      {
        MemoryConnectionProperties memoryConnectionProperties = new MemoryConnectionProperties();
        using (Geodatabase memoryGeodatabase = new Geodatabase(memoryConnectionProperties))
        {
          SchemaBuilder schemaBuilder = new SchemaBuilder(memoryGeodatabase);

          IReadOnlyList<string> dissolveParamsValueArray = Geoprocessing.MakeValueArray(@"C:\Default.gdb\FrameFeatureClass", @"memory\FrameFeatureClass_Dissolved", null, null, "MULTI_PART", "DISSOLVE_LINES", null);
          IGPResult dissolveResult = await Geoprocessing.ExecuteToolAsync("management.Dissolve", dissolveParamsValueArray, null, CancelableProgressor.None, GPExecuteToolFlags.AddToHistory);

          if (dissolveResult.IsFailed)
          {
            System.Diagnostics.Debug.WriteLine("Dissolve errors");
          }

          using (FeatureClass dissolveFc = memoryGeodatabase.OpenDataset<FeatureClass>("FrameFeatureClass_Dissolved"))
          using (FeatureClassDefinition dissolveDefn = dissolveFc.GetDefinition())
          {
            IReadOnlyList<string> createPointsParamsValueArray = Geoprocessing.MakeValueArray(@"memory", "RandomPointsFC", @"memory\FrameFeatureClass_Dissolved", new List<dynamic>() { 0, 0, 250, 250 }, 100, "5 Meters", "POINT", 10);
            IGPResult createRandomPointsMessage = await Geoprocessing.ExecuteToolAsync("management.CreateRandomPoints", createPointsParamsValueArray, null, CancelableProgressor.None, GPExecuteToolFlags.AddOutputsToMap);

            if (createRandomPointsMessage.IsFailed)
            {
              System.Diagnostics.Debug.WriteLine("Create random points errors");
            }

            schemaBuilder.Delete(new FeatureClassDescription(dissolveDefn));
            bool deleteStatus = schemaBuilder.Build();
            if (!deleteStatus)
            {
              System.Diagnostics.Debug.WriteLine("Delete feature class failed");
            }
          }
        }
      });
    }

 

 

 

0 Kudos
KenBuja
MVP Esteemed Contributor

I tried using this code in my add-in, but could not use it as-is. I would get this error on line 6 of your snippet.

error.png

In order to make this work, I had to add in a line (line 2) from my code to create another MemoryGeodatabase:

MemoryConnectionProperties memoryConnectionProperties = new MemoryConnectionProperties();
using (MemoryGeodatabase ??= SchemaBuilder.CreateGeodatabase(memoryConnectionProperties))
using (Geodatabase memoryGeodatabase = new Geodatabase(memoryConnectionProperties))
{
  SchemaBuilder schemaBuilder = new SchemaBuilder(memoryGeodatabase);

I'm curious about how you were able to get this to work in your application and why I have to add in the additional line.

0 Kudos
Aashis
by Esri Contributor
Esri Contributor

Good catch; that was the enhancement in 3.1. I was testing on the 3.1 beta and forgot to revert the code.

BTW, did the GP workflow run successfully after your change? 

0 Kudos
KenBuja
MVP Esteemed Contributor

Yes it did. I was waiting to accept the answer before getting clarification on this. What would be the proper code for 3.0.x?

0 Kudos
Aashis
by Esri Contributor
Esri Contributor

Creating a memory geodatabase and connecting to it in two steps, as you did, is the preferred way for 3.0.x. 

0 Kudos