Select to view content in your preferred language

SchemaBuilder Error

926
5
07-05-2023 03:59 PM
tzz_12
by
Emerging Contributor

Hi Everyone, 

I am trying to use a feature layer description to create an identical new feature class with different fields. I know there are several ways to do this. I tried doing it on DLL. The feature class and fields I want is created correctly, but when I import it into the map, the feature layer does not show, because the shape area, length and polygon fields were not transferred to the new feature class. How can I fix this? 

 QueuedTask.Run(() =>
            {
                var LayerDef = Layer.GetFeatureClass().GetDefinition();
                using (Geodatabase geodatabase = new Geodatabase(new FileGeodatabaseConnectionPath(new Uri(gdb))))
                {
                    // Creating the attribute fields
                    FieldDescription objectIDFieldDescription = FieldDescription.CreateObjectIDField();
                    FieldDescription field1 = new FieldDescription("field1", FieldType.Double);
                    FieldDescription field2 = new FieldDescription("field2", FieldType.Double);
                    List<FieldDescription> fieldDescriptions = new List<FieldDescription>()
                    {objectIDFieldDescription, field1, field2
                    };
                    ShapeDescription shapeDescription = new ShapeDescription(IntersectSort.GetFeatureClass().GetDefinition());
                    FeatureClassDescription LayerDescription = new FeatureClassDescription("Layer_Name", fieldDescriptions, shapeDescription);
                    SchemaBuilder schemaBuilder = new SchemaBuilder(geodatabase);
                    schemaBuilder.Create(LayerDescription);
                    bool success = schemaBuilder.Build();
});
             
                  
0 Kudos
5 Replies
Wolf
by Esri Regular Contributor
Esri Regular Contributor

i haven't tried this but i think these lines have an issue:

ShapeDescription shapeDescription = new ShapeDescription(IntersectSort.GetFeatureClass().GetDefinition());FeatureClassDescription LayerDescription = new FeatureClassDescription("Layer_Name", fieldDescriptions, shapeDescription);

maybe try this instead:

 

FeatureClassDefinition originalFeatureClassDefinition = IntersectSort.GetFeatureClass().GetDefinition();
FeatureClassDescription originalFeatureClassDescription = new FeatureClassDescription(originalFeatureClassDefinition);
FeatureClassDescription LayerDescription = new FeatureClassDescription("Layer_Name", fieldDescriptions, originalFeatureClassDescription.ShapeDescription);

 

 

0 Kudos
tzz_12
by
Emerging Contributor

Thanks Wolf for your help. I tried your method, and it has the same result. For some reason, the feature layer is not showing on the map. 

0 Kudos
Wolf
by Esri Regular Contributor
Esri Regular Contributor

It is working for me.  The following snippet will create a new FeatureClass class "NewLayer" from an existing "TestPolygons" feature layer using the same shape definition but with two new fields.  Then it adds the new FeatureClass to the map as "New: NewLayer" and finally copies all existing features from "TestPolygons" to "New: NewLayer".

 

Wolf_0-1688658084610.png

 

 

protected override async void OnClick()
    {
      var originalLayerName = "TestPolygons";
      var newLayerName = "NewLayer";
      var originalLayer = MapView.Active.Map.GetLayersAsFlattenedList().OfType<FeatureLayer>().Where(fl => fl.Name.Contains(originalLayerName)).FirstOrDefault();
      var isOk = await QueuedTask.Run<bool>(() =>
      {
        var LayerDef = originalLayer.GetFeatureClass().GetDefinition();
        using Geodatabase geodatabase = new(new FileGeodatabaseConnectionPath(new Uri(Project.Current.DefaultGeodatabasePath)));
        // Creating the attribute fields
        FieldDescription objectIDFieldDescription = FieldDescription.CreateObjectIDField();
        FieldDescription field1 = new("field1", FieldType.Double);
        FieldDescription field2 = new("field2", FieldType.Double);
        List<FieldDescription> fieldDescriptions = new()
        {
          objectIDFieldDescription, field1, field2
        };
        FeatureClassDefinition originalFeatureClassDefinition = originalLayer.GetFeatureClass().GetDefinition();
        FeatureClassDescription originalFeatureClassDescription = new(originalFeatureClassDefinition);
        FeatureClassDescription LayerDescription = new(newLayerName, fieldDescriptions, originalFeatureClassDescription.ShapeDescription);
        SchemaBuilder schemaBuilder = new(geodatabase);
        schemaBuilder.Create(LayerDescription);
        bool success = schemaBuilder.Build();
        return success;
      });
      if (!isOk)
      {
        MessageBox.Show($@"Failed to create {newLayerName}");
        return;
      }
      // add the new FeatureClass to the map
      var newLyr = await QueuedTask.Run(() =>
      {
        using Geodatabase geodatabase = new(new FileGeodatabaseConnectionPath(new Uri(Project.Current.DefaultGeodatabasePath)));
        var newFc = geodatabase.OpenDataset<FeatureClass>(newLayerName);
        return LayerFactory.Instance.CreateLayer<FeatureLayer>(new FeatureLayerCreationParams(newFc) { Name = $@"New: {newLayerName}" }, MapView.Active.Map);
      });

      // copy some data
      await QueuedTask.Run(() =>
      {
        // create an edit operation
        EditOperation copyOperation = new EditOperation()
        {
          Name = "Copy Data",
          ProgressMessage = "Working...",
          CancelMessage = "Operation canceled.",
          ErrorMessage = "Error copying polygons",
          SelectModifiedFeatures = false,
          SelectNewFeatures = false
        };
        using var rowCursor = originalLayer.Search();
        while (rowCursor.MoveNext())
        {
          using (var row = rowCursor.Current as Feature)
          {
            var geom = row.GetShape().Clone();
            if (geom == null)
              continue;
            var newAttributes = new Dictionary<string, object>();
            newAttributes.Add("field1", 1.0);
            newAttributes.Add("field2", 2.0);
            copyOperation.Create(newLyr, geom, newAttributes);
          }
        }
        // execute the operation
        if (!copyOperation.Execute())
        {
          MessageBox.Show($@"Copy operation failed {copyOperation.ErrorMessage}");
          return;
        }
      });
    }

 

0 Kudos
tzz_12
by
Emerging Contributor

It works after some minor modification to the code, but when I kept the newAttributes in "copyOperation.Create(newLyr, geom, newAttributes)," it would show this error message, "Cannot convert from System.Collection.Generic.Dictionary<string,object> to System.Action<long>".  It works fine if I delete the newAttributes from the line tho. On a related note, how do I save the edits operations within the script to avoid doing it manually after the script runs? Thanks for your help Wolf!

0 Kudos
Wolf
by Esri Regular Contributor
Esri Regular Contributor

My sample code above is for release 3.0 and newer, if you are using ArcGIS Pro 2.x then the API is bit different.   Below is the snippet that works with 2.9, note the change in the copyOperation.Create line required by the 2.x API (the parameters are different):

protected override async void OnClick()
{
    var originalLayerName = "TestPolygons";
    var newLayerName = "NewLayer";
    var originalLayer = MapView.Active.Map.GetLayersAsFlattenedList().OfType<FeatureLayer>().Where(fl => fl.Name.Contains(originalLayerName)).FirstOrDefault();
    var isOk = await QueuedTask.Run<bool>(() =>
    {
        var LayerDef = originalLayer.GetFeatureClass().GetDefinition();
        bool success = false;
        using (Geodatabase geodatabase = new Geodatabase(new FileGeodatabaseConnectionPath(new Uri(Project.Current.DefaultGeodatabasePath))))
        {
            // Creating the attribute fields
            ArcGIS.Core.Data.DDL.FieldDescription objectIDFieldDescription = ArcGIS.Core.Data.DDL.FieldDescription.CreateObjectIDField();
            ArcGIS.Core.Data.DDL.FieldDescription field1 = new ArcGIS.Core.Data.DDL.FieldDescription("field1", FieldType.Double);
            ArcGIS.Core.Data.DDL.FieldDescription field2 = new ArcGIS.Core.Data.DDL.FieldDescription("field2", FieldType.Double);
            List<ArcGIS.Core.Data.DDL.FieldDescription> fieldDescriptions = new List<ArcGIS.Core.Data.DDL.FieldDescription>()
            {
                objectIDFieldDescription,
                field1,
                field2
            };
            FeatureClassDefinition originalFeatureClassDefinition = originalLayer.GetFeatureClass().GetDefinition();
            FeatureClassDescription originalFeatureClassDescription = new FeatureClassDescription(originalFeatureClassDefinition);
            FeatureClassDescription LayerDescription = new FeatureClassDescription(newLayerName, fieldDescriptions, originalFeatureClassDescription.ShapeDescription);
            SchemaBuilder schemaBuilder = new SchemaBuilder(geodatabase);
            schemaBuilder.Create(LayerDescription);
            success = schemaBuilder.Build();
        }

        return success;
    });
    if (!isOk)
    {
        MessageBox.Show($@"Failed to create {newLayerName}");
        return;
    }
    // add the new FeatureClass to the map
    var newLyr = await QueuedTask.Run(() =>
    {
        using (Geodatabase geodatabase = new Geodatabase(new FileGeodatabaseConnectionPath(new Uri(Project.Current.DefaultGeodatabasePath))))
        {
            var newFc = geodatabase.OpenDataset<FeatureClass>(newLayerName);
            return LayerFactory.Instance.CreateLayer<FeatureLayer>(new FeatureLayerCreationParams(newFc) { Name = $@"New: {newLayerName}" }, MapView.Active.Map);
        }
    });

    // copy some data
    await QueuedTask.Run(() =>
    {
        // create an edit operation
        EditOperation copyOperation = new EditOperation()
        {
            Name = "Copy Data",
            ProgressMessage = "Working...",
            CancelMessage = "Operation canceled.",
            ErrorMessage = "Error copying polygons",
            SelectModifiedFeatures = false,
            SelectNewFeatures = false
        };
        using (var rowCursor = originalLayer.Search())
        {
            while (rowCursor.MoveNext())
            {
                using (var row = rowCursor.Current as Feature)
                {
                    var geom = row.GetShape().Clone();
                    if (geom == null)
                        continue;
                    var newAttributes = new Dictionary<string, object>
                    {
                        { newLyr.GetFeatureClass().GetDefinition().GetShapeField(), geom },
                        { "field1", 1.0 },
                        { "field2", 2.0 }
                    };
                    copyOperation.Create(newLyr, newAttributes);
                }
            }
        }

        // execute the operation
        if (!copyOperation.Execute())
        {
            MessageBox.Show($@"Copy operation failed {copyOperation.ErrorMessage}");
            return;
        }
    });
}

 

In order to save all edits you can use:


_ = Project.Current.SaveEditsAsync();

 

0 Kudos