src/Misc/EFTools/XmlCore/Model/Commands/CommandProcessor.cs
/// <summary>
///     Invokes the commands in the queue.  If any command throws an exception, the transaction
///     will be rolled back and this will rethrow.
/// </summary>
Invokes the commands in the queue.  If any command throws an exception, the transaction
will be rolled back and this will rethrow.
Invokes the commands in the queue . If any command throws an exception the transaction will be rolled back and this will rethrow .
[SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly",
            Justification = @"Risky to change to InvalidOperationException since it has many upstream callers")]
        internal void Invoke()
        {
            Debug.Assert(_cpc != null, "cpc cannot be null");
            if (_cpc == null)
            {
                throw new ArgumentNullException("_cpc");
            }
            if (_commands.Count == 0
                && _cpc.IntegrityChecks.Count == 0)
            {
                return;
            }
            var artifactInitiallyDirty = _cpc.Artifact.IsDirty;
            _cpc.EnqueuedCommands.AddRange(_commands);
            foreach (var command in _commands)
            {
                command.CommandProcessor = this;
            }
            if (!_cpc.HasOpenTransaction)
            {
                if (!_cpc.Artifact.CanEditArtifact())
                {
                    var documentPath = String.Empty;
                    var uri = _cpc.Artifact.Uri;
                    try
                    {
                        documentPath = uri.LocalPath;
                    }
                    catch (InvalidOperationException)
                    {
                        Debug.Fail("Could not parse the LocalPath from the URI for this particular Artifact");
                    }
                    throw new FileNotEditableException(
                        String.Format(CultureInfo.CurrentCulture, Resources.FileNotEditableErrorMessage, documentPath));
                }
            }
            var tx = _cpc.EfiTransaction;
            var isOuterMostTransaction = false;
            try
            {
                if (_cpc.HasOpenTransaction == false)
                {
                    tx = _cpc.CreateTransaction();
                    isOuterMostTransaction = true;
                }
                Debug.Assert(isOuterMostTransaction ? tx != null : true, "Why is the transaction null & isOuterMostTransaction true?");
                while (_commands.Count > 0)
                {
                    var command = _commands.Dequeue();
                    command.Invoke(this);
                }
                if (isOuterMostTransaction)
                {
                    PostProcessUpdate(_cpc, tx, artifactInitiallyDirty);
                }
            }
            catch (Exception e)
            {
                if (isOuterMostTransaction
                    &&
                    tx != null
                    &&
                    tx.Status == EfiTransaction.EfiTxStatus.Open)
                {
                    tx.Rollback();
                }
                if (isOuterMostTransaction)
                {
                    _cpc.ClearBindingsForRebind();
                    _cpc.ClearIntegrityChecks();
                }
                if (!(e is CommandValidationFailedException))
                {
                    Debug.Fail("Exception thrown inside CommandProcessor. " + e.Message);
                }
                throw;
            }
            finally
            {
                if (isOuterMostTransaction)
                {
                    _cpc.DisposeTransaction();
                }
            }
        }
[ SuppressMessage ( " " , " " , Justification = @"Risky to change to InvalidOperationException since it has many upstream callers" ) ] internal void Invoke ( ) { Debug . Assert ( _cpc != null , " " ) ; if ( _cpc == null ) { throw new ArgumentNullException ( " " ) ; } if ( _commands . Count == 0 && _cpc . IntegrityChecks . Count == 0 ) { return ; } var artifactInitiallyDirty = _cpc . Artifact . IsDirty ; _cpc . EnqueuedCommands . AddRange ( _commands ) ; foreach ( var command in _commands ) { command . CommandProcessor = this ; } if ( ! _cpc . HasOpenTransaction ) { if ( ! _cpc . Artifact . CanEditArtifact ( ) ) { var documentPath = String . Empty ; var uri = _cpc . Artifact . Uri ; try { documentPath = uri . LocalPath ; } catch ( InvalidOperationException ) { Debug . Fail ( " " ) ; } throw new FileNotEditableException ( String . Format ( CultureInfo . CurrentCulture , Resources . FileNotEditableErrorMessage , documentPath ) ) ; } } var tx = _cpc . EfiTransaction ; var isOuterMostTransaction = false ; try { if ( _cpc . HasOpenTransaction == false ) { tx = _cpc . CreateTransaction ( ) ; isOuterMostTransaction = true ; } Debug . Assert ( isOuterMostTransaction ? tx != null : true , " " ) ; while ( _commands . Count > 0 ) { var command = _commands . Dequeue ( ) ; command . Invoke ( this ) ; } if ( isOuterMostTransaction ) { PostProcessUpdate ( _cpc , tx , artifactInitiallyDirty ) ; } } catch ( Exception e ) { if ( isOuterMostTransaction && tx != null && tx . Status == EfiTransaction . EfiTxStatus . Open ) { tx . Rollback ( ) ; } if ( isOuterMostTransaction ) { _cpc . ClearBindingsForRebind ( ) ; _cpc . ClearIntegrityChecks ( ) ; } if ( ! ( e is CommandValidationFailedException ) ) { Debug . Fail ( " " + e . Message ) ; } throw ; } finally { if ( isOuterMostTransaction ) { _cpc . DisposeTransaction ( ) ; } } }
Invokes the commands in the queue.
Invokes the commands in the queue .
// just to be safe, the c'tor should have caught this // if there is nothing to do, just return // Note down whether or not the artifact was originally dirty, since we don't want hydration commands marking the file // as clean if there are uncommited diagram layout edits for instance. // First add the commands to the command processor context so that the top-level processor can determine // how to post-process based on them. // We need to set the command processor since the behavior methods query this. // since the Invoke() method is the gateway towards editing the model, we should first // ask ourselves if we can perform edits. This query is propagated down to the XML model level // where we base our answer on what the SCC provider tells us if we are in VS. // But we should only do this for the top-level transaction (otherwise we end up calling  // VsXmlModel.CanEditXmlModel() for _every_ nested Command which causes perf problems // for transactions which use a large number of nested commands e.g. Update Model on a  // large database) // Note: this means we do not support multi-artifact transactions. If we started doing wanting // to support multi-artifact transactions then the approach below would need to be expanded to // call CanEditArtifact() for each artifact in the transaction // open a local transaction if the cpc doesn't have one // invoke all of the commands in our queue // if we are managing the outer most transaction, do our post-processing // BUGBUG: 557416