/// <summary> /// Executes a procedure in an edit operation /// </summary> /// <param name="workspace">The workspace in which the operation is executed</param> /// <param name="procedure">The operation.</param> /// <param name="state">The state.</param> /// <param name="description">The description for the edit operation.</param> /// <returns><c>true</c> if the operation succeeded, <c>false</c> if it was aborted.</returns> public bool Execute(IWorkspace workspace, Action procedure, EditStateInfo state, string description) { return(Execute(workspace, delegate { procedure(); }, state, description, null)); }
/// <summary> /// Executes a procedure in an edit operation /// </summary> /// <param name="workspace">The workspace in which the operation is executed</param> /// <param name="procedure">The operation.</param> /// <param name="state">The state.</param> /// <param name="description">The description for the edit operation.</param> /// <param name="trackCancel">The cancel tracker (optional).</param> /// <returns> /// <c>true</c> if the operation succeeded, <c>false</c> if it was aborted. /// </returns> public bool Execute(IWorkspace workspace, Action <ITrackCancel> procedure, EditStateInfo state, string description, ITrackCancel trackCancel) { Assert.ArgumentNotNull(workspace, nameof(workspace)); Assert.ArgumentNotNull(procedure, nameof(procedure)); Assert.ArgumentNotNullOrEmpty(description, nameof(description)); if (trackCancel != null) { Assert.True(trackCancel.Continue(), "Cancel tracker already cancelled"); } using (EditWorkspace(workspace)) { var editWs = (IWorkspaceEdit)workspace; var editWs2 = workspace as IWorkspaceEdit2; // not implemented for shapefiles bool isBeingEdited = editWs.IsBeingEdited(); bool isInEditOperation = (editWs2 != null && editWs2.IsInEditOperation); if ((state & EditStateInfo.MustNotBeEditing) != 0) { Assert.False(isBeingEdited, "Edit Session already open"); } if ((state & EditStateInfo.MustBeEditing) != 0) { Assert.True(isBeingEdited, "Edit Session not open"); } if ((state & EditStateInfo.MustNotBeInOperation) != 0) { if (isInEditOperation) { AbortEditOperation(); _msg.Warn("Rolled back unexpected existing edit operation"); } isInEditOperation = false; } if ((state & EditStateInfo.MustBeInOperation) != 0) { Assert.True(isInEditOperation, "Edit Session not in Operation"); } _aborted = false; IWorkspaceEditEvents_Event workspaceEditEvents = null; try { #region check reset current state if (isInEditOperation) { if ((state & EditStateInfo.AbortExistingOperation) != 0) { Assert.True( (state & EditStateInfo.StopExistingOperation) == 0, "Cannot specify both " + EditStateInfo.AbortExistingOperation + " and " + EditStateInfo.StopExistingOperation); AbortEditOperation(); isInEditOperation = false; } else if ((state & EditStateInfo.StopExistingOperation) != 0) { StopEditOperation(description); isInEditOperation = false; } } if (isBeingEdited) { if ((state & EditStateInfo.AbortExistingEditing) != 0) { Assert.True((state & EditStateInfo.StopExistingEditing) == 0, "Cannot specify both " + EditStateInfo.AbortExistingEditing + " and " + EditStateInfo.StopExistingEditing); StopEditing(false); isBeingEdited = false; } else if ((state & EditStateInfo.StopExistingEditing) != 0) { StopEditing(true); isBeingEdited = false; } } #endregion if (!isBeingEdited) { StartEditing(); } if (!isInEditOperation && (state & EditStateInfo.DontStartOperation) == 0) { StartEditOperation(); } // this may fail (COM object that has been separated from its underlying RCW cannot be used) workspaceEditEvents = (IWorkspaceEditEvents_Event)workspace; workspaceEditEvents.OnAbortEditOperation += editEvents_OnAbortEditOperation; procedure(trackCancel); if (trackCancel != null && !trackCancel.Continue()) { _msg.WarnFormat("Operation cancelled: {0}", description); // cancel was called in procedure if (!_aborted) { // The operation is not yet aborted. Abort it now. AbortEditOperation(); } } if (!_aborted && (!isInEditOperation && (state & EditStateInfo.KeepOperation) == 0) || (state & EditStateInfo.StopOperation) != 0) { // if the edit operation violates rule engine rules, the edit operation won't succeed. However // no exception is reported when calling StopEditOperation --> the OnAbort handler is mandatory // to detect this situation. StopEditOperation(description); } if ((!isBeingEdited && (state & EditStateInfo.KeepEditing) == 0) || (state & EditStateInfo.StopEditing) != 0) { StopEditing(true); } return(!_aborted); } catch (Exception ex) { try // Clean up { var comEx = ex as COMException; string message = comEx == null ? string.Format("Error executing operation: {0} ({1})", description, ex.Message) : string.Format( "Error executing operation: {0} ({1}; Error Code: {2})", description, comEx.Message, comEx.ErrorCode); _msg.Debug(message); if (!isInEditOperation) { // if the error occurred in StopEditOperation(), then // that edit operation might already be aborted -> check if (editWs2 != null && editWs2.IsInEditOperation) { AbortEditOperation(); } } if (!isBeingEdited) { StopEditing(false); } } catch (Exception e2) { // exception intentionally suppressed. _msg.Error("Error cleaning up after failed gdb function", e2); } throw; } finally { try { if (workspaceEditEvents != null) { workspaceEditEvents.OnAbortEditOperation -= editEvents_OnAbortEditOperation; } } catch (AccessViolationException e) { // exception intentionally suppressed. _msg.Warn("Error unregistering event handler", e); } } } }