描述
通过 Editor 类可以使用编辑会话和编辑操作来管理数据库事务。
在保存并永久应用于数据之前,编辑内容始终属于临时数据。您也可以退出编辑会话而不保存所做的更改。
讨论
编辑会话和编辑操作具有以下优点:
- 将编辑内容细分为原子事务。如果在完成所有编辑内容之前发生了错误,该事务可以回滚。
- 由地理数据库维护的可选编辑操作可撤消和重做堆栈。编辑操作停止后,将停留在撤消堆栈上。可以通过调用 undoOperation 和 redoOperation 方法来遍历撤消/重做堆栈。
- 编辑会话和编辑操作都可实现分批更新,因此在编辑企业级地理数据库时可发挥巨大的性能优势。
- 在允许多用户同时编辑的地理数据库中,编辑会话中的应用程序在会话完成前将无法识别其他应用程序所做的更改。
Editor 类可用于启动和停止文件地理数据库、个人地理数据库、企业级地理数据库和 shapefile 的编辑会话和编辑操作。Editor 类还可用于启动版本化或未版本化数据集的编辑会话。
启动编辑会话之前,请确保所有需要编辑的数据集都已打开。
startEditing 方法用于启动编辑会话,startOperation 方法用于启动编辑操作。要提交编辑操作,请调用 stopOperation。要取消编辑操作,请调用 abortOperation。要完成编辑会话,请调用 stopEditing,该方法接受一个布尔型参数,用于指示提交还是放弃会话内所做的更改。
注:
背离此模式会导致异常的结果。例如,正在进行编辑操作时不应该调用 stopEditing。而应该中止编辑操作,并停止编辑会话。
编辑操作必须控制在编辑会话的上下文中,而且编辑操作不能嵌套到其他编辑操作中。
编辑会话和 with 语句
编辑会话和编辑操作还可以与 Python 的 with 语句结合使用。with 语句充当上下文管理器并负责处理相应的启动、停止和中止调用。以下示例突出了 Editor 类与 with 语句结合使用的基本结构。
import arcpy
# Open an edit session and start an edit operation
with arcpy.da.Editor(workspace) as edit:
# <your edits>
# If an exception is raised, the operation will be aborted, and
# the edit session is closed without saving
# If no exceptions are raised, stop the operation and save
# and close the edit session
使用撤消和重做堆栈
撤消和重做堆栈在编辑会话中是否启用,具体取决于 startEditing 方法的布尔型参数。如果编辑会话将包含多个可能依相应的条件回滚(和重做)的操作,应启用撤消和重做堆栈。否则可以通过将参数设置为 False 来禁用撤消和重做堆栈,以提升系统性能(例如,编辑会话仅包含一个操作)。
注:
在企业级地理数据库中启动版本化的编辑会话时,将始终启用撤消和重做堆栈。未版本化的编辑会话不支持撤消和重做操作。
用于控制撤消和重做堆栈的两种方法是 undoOperation 和 redoOperation。undoOperation 将编辑会话的状态回滚到上一编辑操作,并将编辑操作移至重做堆栈。redoOperation 方法将编辑操作从最近的重做堆栈移回撤消堆栈,并将编辑会话状态向前滚动至执行编辑操作后所处的状态。提交编辑操作时,将清除重做堆栈,之后将无法重做任何曾位于重做堆栈中的操作。
需要编辑会话的情况
以下列出了只能在编辑会话中编辑的一些数据集类型:
- 参与拓扑的要素类
- 参与几何网络的要素类
- 参与网络数据集的要素类
- 企业级地理数据库中的版本化数据集
- 一些带有类扩展的对象和要素类
编辑会话和游标
游标应限制在单个编辑操作中。这意味着,对于每个操作都应实例化并释放一个新的游标。在编辑由某一游标返回的行时这一点非常重要,因为行与地理数据库的特定状态紧密相关。应避免在多个编辑操作中使用同一游标。这样做会导致意外情况以及数据损失。
语法
Editor (workspace)
参数 | 说明 | 数据类型 |
workspace | 要进行编辑的工作空间的路径。编辑器一次只能编辑一个工作空间。 | String |
属性
属性 | 说明 | 数据类型 |
isEditing (只读) | Editor 在编辑会话中时为真。 | Boolean |
方法概述
方法 | 说明 |
__enter__ () | 启动编辑会话。 |
__exit__ () | 如果成功,则停止编辑并保存编辑会话。如果发生异常,则停止编辑但不进行保存。 |
startEditing ({with_undo}, {multiuser_mode}) | 启动编辑会话。 |
stopEditing (save_changes) | 停止编辑会话。 |
startOperation () | 启动编辑操作。 |
stopOperation () | 停止编辑操作。 |
abortOperation () | 中止编辑操作。 |
undoOperation () | 撤消编辑操作(回滚修改内容)。 |
redoOperation () | 恢复编辑操作。 |
方法
__enter__ ()
__exit__ ()
startEditing ({with_undo}, {multiuser_mode})
参数 | 说明 | 数据类型 |
with_undo | 设置在编辑会话中启用或禁用撤消和重做堆栈。 如果编辑会话将包含多个可能依相应的条件回滚(和重做)的操作,应启用撤消和重做堆栈。否则可以通过将参数设置为 False 来禁用撤消和重做堆栈,以提升系统性能(例如,编辑会话仅包含一个操作)。 在 ArcSDE 中启动版本化的编辑会话时,将始终启用撤消和重做堆栈。未版本化的编辑会话不支持撤消和重做操作。 (默认值为 True) | Boolean |
multiuser_mode | 如果设置为 False,将对编辑非版本化或版本化数据集拥有完全控制权限。如果数据集为非版本化数据集并且使用 stopEditing(False),则您的编辑将不会提交(否则,如果设置为 True,则您的编辑将会提交)。 (默认值为 True) | Boolean |
stopEditing (save_changes)
参数 | 说明 | 数据类型 |
save_changes | 如果设置为 True 将保存更改;如果设置为 False 将放弃更改。 (默认值为 True) | Boolean |
startOperation ()
stopOperation ()
abortOperation ()
undoOperation ()
redoOperation ()
代码示例
以下代码使用 with 语句,此语句用于开启编辑操作并在表的一组所选行中执行 CalculateField。并将处理和打印出现的任何工具错误。
由于在 with 语句中执行 CalculateField,如果出现任何异常,将不会保存更改。如果成功完成 CalculateField,将保存更新。
import arcpy
fc = 'C:/Portland/Portland.gdb/Land/Parks'
workspace = 'C:/Portland/Portland.gdb'
layer_name = 'Parks'
try:
arcpy.MakeFeatureLayer_management(fc, layer_name)
arcpy.SelectLayerByAttribute_management(
layer_name, 'NEW_SELECTION',
"""CUSTODIAN = 'City of Portland'""")
with arcpy.da.Editor(workspace) as edit:
arcpy.CalculateField_management(
layer_name, 'Usage', '"PUBLIC"', 'PYTHON')
except arcpy.ExecuteError:
print(arcpy.GetMessages(2))
以下为开启编辑会话和编辑操作、在表中创建行、停止编辑操作以及提交编辑会话的示例。
import arcpy
import os
fc = 'Database Connections/Portland.sde/portland.jgp.schools'
workspace = os.path.dirname(fc)
# Start an edit session. Must provide the workspace.
edit = arcpy.da.Editor(workspace)
# Edit session is started without an undo/redo stack for versioned data
# (for second argument, use False for unversioned data)
edit.startEditing(False, True)
# Start an edit operation
edit.startOperation()
# Insert a row into the table.
with arcpy.da.InsertCursor(fc, ('SHAPE@', 'Name')) as icur:
icur.insertRow([(7642471.100, 686465.725), 'New School'])
# Stop the edit operation.
edit.stopOperation()
# Stop the edit session and save the changes
edit.stopEditing(True)