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); }