/// \addtogroup ogrlayer_editing OGR layer editing /// Here is a list of methods and properties to save changes made to OgrLayer back to datasource. /// The properties and methods described here belong to OgrLayer class.\n /// /// \dot /// digraph ogrediting { /// splines = true; /// node [shape= "polygon", fontname=Helvetica, fontsize=9, style = filled, color = palegreen, height = 0.3, width = 1.2]; /// lb [ label="OgrLayer" URL="\ref OgrLayer"]; /// node [shape = "ellipse", color = khaki, width = 0.2, height = 0.2, style = filled] /// gr [label="OGR layer editing" URL="\ref ogrlayer_editing"]; /// edge [ arrowhead="open", style = solid, arrowsize = 0.6, fontname = "Arial", fontsize = 9, fontcolor = blue, color = "#606060" ] /// lb -> gr; /// } /// \enddot /// <a href = "diagrams.html">Graph description</a>\n /// /// Editing of underlying in-memory %shapefile can be done for all types of OGR layers. \n /// /// However saving of these changes back to datasource isn't always possible because of following reasons:\n /// - it isn't supported by driver; /// - forUpdate flag parameter wasn't specified on opening the layer; /// - layer was opened from SQL query; /// - data was reprojected during adding to the map; /// - layer doesn't have feature ID column.\n /// /// Use OgrLayer.get_SupportsEditing to check if saving is possible for current layer.\n /// /// Feature ID column corresponds to primary key in database table. /// Such column will be added as first field in attribute table of %shapefile (with index 0). This field /// must not be edited by client code. The presence of feature ID column can be tested with OgrLayer.FidColumnName /// property which will return empty string if no such column exists.\n /// /// To save the changes to datasource OgrLayer.SaveChanges method should be called. /// It supports saving of the following types of changes (provided that other preconditions are met ): /// - editing of values in attribute table; /// - any editing of geometry of individual shapes; /// - adding of new shapes; /// - deleting of exiting shapes.\n /// /// \note OgrLayer doesn't support any changes in order or number of fields in attribute table. Therefore /// fields must not be added or deleted in order for OgrLayer.SaveChanges to work.\n /// /// Edited shapes must be marked with modified flag via Shapefile.set_ShapeModified. See code sample in OgrLayer.SaveChanges /// documentation.\n /// /// Errors during the saving operation are registered in the log which can be accessed using OgrLayer.get_UpdateSourceErrorMsg.\n /// /// OgrLayer.SaveChanges method may change the order of rows in the database table /// (for example PostgreSQL driver places the updated rows in the end of table). /// Therefore on reloading of layer after the SaveChanges operation indices of shapes may change. /// /// The following code demonstrates how various types of editing for OGR layer can be made /// with saving of changes back to the datasource. /// \code /// private static string CONNECTION_STRING = "PG:host=localhost dbname=london user=postgres password=1234"; /// /// var layer = new OgrLayer(); /// layer.GlobalCallback = form; /// /// bool forUpdate = true; /// if (!layer.OpenFromDatabase(CONNECTION_STRING, "buildings", forUpdate)) /// { /// Debug.Print("Failed to open layer: " + layer.get_ErrorMsg(layer.LastErrorCode)); /// return false; /// } /// /// // check if editing is supported for driver /// Debug.Print("Driver supports editing: " + layer.TestCapability(tkOgrLayerCapability.olcRandomWrite)); /// /// now check if we can actually do it, as there can be other limitations /// /// if (!layer.get_SupportsEditing(tkOgrSaveType.ostSaveAll)) /// { /// Debug.Print("Can't edit a layer: " + layer.get_ErrorMsg(layer.LastErrorCode)); /// layer.Close(); /// return false; /// } /// /// var sf = layer.GetBuffer(); /// if (sf != null) /// { /// // possible types of editing /// bool editValue = true; /// bool addShape = true; /// bool editShape = true; /// bool removeShape = true; /// /// if (editValue) /// { /// int shapeIndex = 0; /// int fieldIndex = 2; /// object val = sf.get_CellValue(fieldIndex, shapeIndex); /// sf.EditCellValue(fieldIndex, shapeIndex, "test_writing"); /// /// // this flag will notify the driver that changes should saved back to source /// sf.ShapeModified[shapeIndex] = true; /// } /// /// if (addShape) /// { /// int shapeIndex = sf.NumShapes; /// var shp = sf.get_Shape(0); /// shp = shp.Buffer(1, 50); /// /// // modified flag is set automatically in this case /// bool result = sf.EditInsertShape(shp, ref shapeIndex); /// Debug.Print("Shape was inserted: " + result); /// } /// /// if (editShape) /// { /// // since shapefile is in in-memory mode, geometry of shapes can be changed directly; /// // bear in mind that this won't work for file-based shapefiles, in that case get_Shape will /// // populate Shape object which will have no further link with parent shapefile /// var shp = sf.get_Shape(sf.NumShapes - 1); /// for (int i = 0; i < shp.NumPoints; i++) /// { /// double x = 0.0, y = 0.0; /// if (shp.get_XY(i, ref x, ref y)) /// shp.put_XY(i, x + 0.01, y + 0.01); // let's move it a little /// } /// } /// /// if (removeShape) /// { /// bool result = sf.EditDeleteShape(sf.NumShapes - 1); /// Debug.Print("Shape was deleted: " + result); /// } /// /// // saving it /// int count; /// var saveResults = layer.SaveChanges(out count); /// /// Debug.Print("Save result: " + saveResults.ToString()); /// Debug.Print("Number of shapes saved: " + count); /// /// // displaying info on errors /// for (int i = 0; i < layer.UpdateSourceErrorCount; i++) /// { /// Debug.Print(string.Format("Error for shape id {0}: {1}", /// layer.UpdateSourceErrorShapeIndex[i], layer.UpdateSourceErrorMsg[i])); /// } /// return true; /// } /// layer.Close(); /// return false; /// \endcode /// @{ /// <summary> /// Gets a value indicating whether the layer supports editing. /// </summary> /// <remarks> /// The property works like this:\n /// 1) checks whether underlying driver supports random write operation: /// OgrLayer.TestCapability(tkOgrLayerCapability::olcRandomWrite);\n /// 2) the presence of Feature Id column is verified;\n /// 3) checks if the data is still in the same projection (OgrLayer.DataIsReprojected).\n /// /// OgrLayer.SaveChanges method doesn't make the first check, thus trying to write /// the data even if functionality isn't advertised by driver. /// </remarks> /// <param name="editingType">The requested type of editing.</param> /// <returns>True in case editing is supported.</returns> public bool get_SupportsEditing(tkOgrSaveType editingType) { throw new NotImplementedException(); }
/// <summary> /// Saves local changes to the datasource. /// </summary> /// <remarks> /// To check whether the operation is supported for current layer use OgrLayer.get_SupportsEditing.\n /// /// The method works like this:\n /// /// 1) Underlying shapefile is analyzed for changes, i.e. for shapes with Shapefile.get_ShapeModified property set to true. \n /// 2) For each of such shapes UPDATE statement is generated by driver. /// Shapes are identified in source by the value of Feature ID column.\n /// 3) If update operation for particular shape fails the error is registered in: /// OgrLayer.get_UpdateSourceErrorMsg().\n /// /// The operation may fail for a particular shape because of 2 main reasons: /// - shape is invalid, while validateShapes parameter set to true; /// - new values aren't accepted by datasource, which often can maintain stricter data constraints. /// </remarks> /// <param name="savedCount">Returns number of saved changed.</param> /// <param name="saveType">Sets which part of data should be saved, geometry, attributes or both. /// Default value is tkOgrSaveType.ostSaveAll (i.e. both geometry and attributes).</param> /// <param name="validateShapes">Sets whether shapes will be validated before saving. Default value is true, /// i.e. invalid shapes won't be saved.</param> /// <returns>Result of the operation.</returns> public tkOgrSaveResult SaveChanges(out int savedCount, tkOgrSaveType saveType = tkOgrSaveType.ostSaveAll, bool validateShapes = true) { throw new NotImplementedException(); }