internal override int CompareToType(UpdateCommand otherCommand)
        {
            Debug.Assert(!object.ReferenceEquals(this, otherCommand), "caller should ensure other command is different");

            FunctionUpdateCommand other = (FunctionUpdateCommand)otherCommand;

            // first state entry is the 'main' state entry for the command (see ctor)
            IEntityStateEntry thisParent  = this.m_stateEntries[0];
            IEntityStateEntry otherParent = other.m_stateEntries[0];

            // order by operator
            int result = (int)GetModificationOperator(thisParent.State) -
                         (int)GetModificationOperator(otherParent.State);

            if (0 != result)
            {
                return(result);
            }

            // order by entity set
            result = StringComparer.Ordinal.Compare(thisParent.EntitySet.Name, otherParent.EntitySet.Name);
            if (0 != result)
            {
                return(result);
            }
            result = StringComparer.Ordinal.Compare(thisParent.EntitySet.EntityContainer.Name, otherParent.EntitySet.EntityContainer.Name);
            if (0 != result)
            {
                return(result);
            }

            // order by key values
            int thisInputIdentifierCount  = (null == this.m_inputIdentifiers ? 0 : this.m_inputIdentifiers.Count);
            int otherInputIdentifierCount = (null == other.m_inputIdentifiers ? 0 : other.m_inputIdentifiers.Count);

            result = thisInputIdentifierCount - otherInputIdentifierCount;
            if (0 != result)
            {
                return(result);
            }
            for (int i = 0; i < thisInputIdentifierCount; i++)
            {
                DbParameter thisParameter  = this.m_inputIdentifiers[i].Value;
                DbParameter otherParameter = other.m_inputIdentifiers[i].Value;
                result = ByValueComparer.Default.Compare(thisParameter.Value, otherParameter.Value);
                if (0 != result)
                {
                    return(result);
                }
            }

            // If the result is still zero, it means key values are all the same. Switch to synthetic identifiers
            // to differentiate.
            for (int i = 0; i < thisInputIdentifierCount; i++)
            {
                int thisIdentifier  = this.m_inputIdentifiers[i].Key;
                int otherIdentifier = other.m_inputIdentifiers[i].Key;
                result = thisIdentifier - otherIdentifier;
                if (0 != result)
                {
                    return(result);
                }
            }

            return(result);
        }
        // Processes all insert and delete requests in the table's <see cref="ChangeNode" />. Inserts
        // and deletes with the same key are merged into updates.
        internal List <UpdateCommand> CompileCommands(ChangeNode changeNode, UpdateCompiler compiler)
        {
            Set <CompositeKey> keys = new Set <CompositeKey>(compiler.m_translator.KeyComparer);

            // Retrieve all delete results (original values) and insert results (current values) while
            // populating a set of all row keys. The set contains a single key per row.
            Dictionary <CompositeKey, PropagatorResult> deleteResults = ProcessKeys(compiler, changeNode.Deleted, keys);
            Dictionary <CompositeKey, PropagatorResult> insertResults = ProcessKeys(compiler, changeNode.Inserted, keys);

            List <UpdateCommand> commands = new List <UpdateCommand>(deleteResults.Count + insertResults.Count);

            // Examine each row key to see if the row is being deleted, inserted or updated
            foreach (CompositeKey key in keys)
            {
                PropagatorResult deleteResult;
                PropagatorResult insertResult;

                bool hasDelete = deleteResults.TryGetValue(key, out deleteResult);
                bool hasInsert = insertResults.TryGetValue(key, out insertResult);

                Debug.Assert(hasDelete || hasInsert, "(update/TableChangeProcessor) m_keys must not contain a value " +
                             "if there is no corresponding insert or delete");

                try
                {
                    if (!hasDelete)
                    {
                        // this is an insert
                        commands.Add(compiler.BuildInsertCommand(insertResult, this));
                    }
                    else if (!hasInsert)
                    {
                        // this is a delete
                        commands.Add(compiler.BuildDeleteCommand(deleteResult, this));
                    }
                    else
                    {
                        // this is an update because it has both a delete result and an insert result
                        UpdateCommand updateCommand = compiler.BuildUpdateCommand(deleteResult, insertResult, this);
                        if (null != updateCommand)
                        {
                            // if null is returned, it means it is a no-op update
                            commands.Add(updateCommand);
                        }
                    }
                }
                catch (Exception e)
                {
                    if (UpdateTranslator.RequiresContext(e))
                    {
                        // collect state entries in scope for the current compilation
                        List <IEntityStateEntry> stateEntries = new List <IEntityStateEntry>();
                        if (null != deleteResult)
                        {
                            stateEntries.AddRange(SourceInterpreter.GetAllStateEntries(
                                                      deleteResult, compiler.m_translator, m_table));
                        }
                        if (null != insertResult)
                        {
                            stateEntries.AddRange(SourceInterpreter.GetAllStateEntries(
                                                      insertResult, compiler.m_translator, m_table));
                        }

                        throw EntityUtil.Update(System.Data.Entity.Strings.Update_GeneralExecutionException,
                                                e, stateEntries);
                    }
                    throw;
                }
            }

            return(commands);
        }