/// <summary> /// Builds insert command. /// </summary> /// <param name="newRow">Row to insert.</param> /// <param name="processor">Context for the table we're inserting into.</param> /// <returns>Insert command.</returns> internal UpdateCommand BuildInsertCommand(PropagatorResult newRow, TableChangeProcessor processor) { // Bind the insert target DbExpressionBinding target = GetTarget(processor); // Create set clauses and returning parameter Dictionary <int, string> outputIdentifiers; DbExpression returning; bool rowMustBeTouched = true; // for inserts, the row must always be touched List <DbModificationClause> setClauses = new List <DbModificationClause>(); foreach (DbModificationClause clause in BuildSetClauses(target, newRow, null, processor, /* insertMode */ true, out outputIdentifiers, out returning, ref rowMustBeTouched)) { setClauses.Add(clause); } // Initialize DML command tree DbInsertCommandTree commandTree = new DbInsertCommandTree(m_translator.MetadataWorkspace, DataSpace.SSpace, target, setClauses.AsReadOnly(), returning); // Create command UpdateCommand command = new DynamicUpdateCommand(processor, m_translator, ModificationOperator.Insert, null, newRow, commandTree, outputIdentifiers); return(command); }
internal override int CompareToType(UpdateCommand otherCommand) { Debug.Assert(!object.ReferenceEquals(this, otherCommand), "caller is supposed to ensure otherCommand is different reference"); DynamicUpdateCommand other = (DynamicUpdateCommand)otherCommand; // order by operation type int result = (int)this.Operator - (int)other.Operator; if (0 != result) { return(result); } // order by Container.Table result = StringComparer.Ordinal.Compare(this.m_processor.Table.Name, other.m_processor.Table.Name); if (0 != result) { return(result); } result = StringComparer.Ordinal.Compare(this.m_processor.Table.EntityContainer.Name, other.m_processor.Table.EntityContainer.Name); if (0 != result) { return(result); } // order by table key PropagatorResult thisResult = (this.Operator == ModificationOperator.Delete ? this.OriginalValues : this.CurrentValues); PropagatorResult otherResult = (other.Operator == ModificationOperator.Delete ? other.OriginalValues : other.CurrentValues); for (int i = 0; i < m_processor.KeyOrdinals.Length; i++) { int keyOrdinal = m_processor.KeyOrdinals[i]; object thisValue = thisResult.GetMemberValue(keyOrdinal).GetSimpleValue(); object otherValue = otherResult.GetMemberValue(keyOrdinal).GetSimpleValue(); result = ByValueComparer.Default.Compare(thisValue, otherValue); 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 < m_processor.KeyOrdinals.Length; i++) { int keyOrdinal = m_processor.KeyOrdinals[i]; int thisValue = thisResult.GetMemberValue(keyOrdinal).Identifier; int otherValue = otherResult.GetMemberValue(keyOrdinal).Identifier; result = thisValue - otherValue; if (0 != result) { return(result); } } return(result); }
/// <summary> /// Builds an update command. /// </summary> /// <param name="oldRow">Old value of the row being updated.</param> /// <param name="newRow">New value for the row being updated.</param> /// <param name="processor">Context for the table containing row.</param> /// <returns>Update command.</returns> internal UpdateCommand BuildUpdateCommand(PropagatorResult oldRow, PropagatorResult newRow, TableChangeProcessor processor) { // If we're updating a row, the row may not need to be touched (e.g., no concurrency validation required) bool rowMustBeTouched = false; DbExpressionBinding target = GetTarget(processor); // Create set clauses and returning parameter Dictionary <int, string> outputIdentifiers; DbExpression returning; List <DbModificationClause> setClauses = new List <DbModificationClause>(); foreach (DbModificationClause clause in BuildSetClauses( target, newRow, oldRow, processor, /* insertMode */ false, out outputIdentifiers, out returning, ref rowMustBeTouched)) { setClauses.Add(clause); } // Construct predicate identifying the row to modify DbExpression predicate = BuildPredicate(target, oldRow, newRow, processor, ref rowMustBeTouched); if (0 == setClauses.Count) { if (rowMustBeTouched) { List <IEntityStateEntry> stateEntries = new List <IEntityStateEntry>(); stateEntries.AddRange(SourceInterpreter.GetAllStateEntries( oldRow, m_translator, processor.Table)); stateEntries.AddRange(SourceInterpreter.GetAllStateEntries( newRow, m_translator, processor.Table)); if (stateEntries.All(it => (it.State == EntityState.Unchanged))) { rowMustBeTouched = false; } } // Determine if there is nothing to do (i.e., no values to set, // no computed columns, and no concurrency validation required) if (!rowMustBeTouched) { return(null); } } // Initialize DML command tree DbUpdateCommandTree commandTree = new DbUpdateCommandTree(m_translator.MetadataWorkspace, DataSpace.SSpace, target, predicate, setClauses.AsReadOnly(), returning); // Create command UpdateCommand command = new DynamicUpdateCommand(processor, m_translator, ModificationOperator.Update, oldRow, newRow, commandTree, outputIdentifiers); return(command); }
/// <summary> /// Builds a delete command. /// </summary> /// <param name="oldRow">Value of the row being deleted.</param> /// <param name="processor">Context for the table containing row.</param> /// <returns>Delete command.</returns> internal UpdateCommand BuildDeleteCommand(PropagatorResult oldRow, TableChangeProcessor processor) { // If we're deleting a row, the row must always be touched bool rowMustBeTouched = true; // Initialize DML command tree DbExpressionBinding target = GetTarget(processor); // Create delete predicate DbExpression predicate = BuildPredicate(target, oldRow, null, processor, ref rowMustBeTouched); DbDeleteCommandTree commandTree = new DbDeleteCommandTree(m_translator.MetadataWorkspace, DataSpace.SSpace, target, predicate); // Set command // Initialize delete command UpdateCommand command = new DynamicUpdateCommand(processor, m_translator, ModificationOperator.Delete, oldRow, null, commandTree, null); return command; }
/// <summary> /// Builds a delete command. /// </summary> /// <param name="oldRow">Value of the row being deleted.</param> /// <param name="processor">Context for the table containing row.</param> /// <returns>Delete command.</returns> internal UpdateCommand BuildDeleteCommand(PropagatorResult oldRow, TableChangeProcessor processor) { // If we're deleting a row, the row must always be touched bool rowMustBeTouched = true; // Initialize DML command tree DbExpressionBinding target = GetTarget(processor); // Create delete predicate DbExpression predicate = BuildPredicate(target, oldRow, null, processor, ref rowMustBeTouched); DbDeleteCommandTree commandTree = new DbDeleteCommandTree(m_translator.MetadataWorkspace, DataSpace.SSpace, target, predicate); // Set command // Initialize delete command UpdateCommand command = new DynamicUpdateCommand(processor, m_translator, ModificationOperator.Delete, oldRow, null, commandTree, null); return(command); }
/// <summary> /// Builds an update command. /// </summary> /// <param name="oldRow">Old value of the row being updated.</param> /// <param name="newRow">New value for the row being updated.</param> /// <param name="processor">Context for the table containing row.</param> /// <returns>Update command.</returns> internal UpdateCommand BuildUpdateCommand(PropagatorResult oldRow, PropagatorResult newRow, TableChangeProcessor processor) { // If we're updating a row, the row may not need to be touched (e.g., no concurrency validation required) bool rowMustBeTouched = false; DbExpressionBinding target = GetTarget(processor); // Create set clauses and returning parameter Dictionary<int, string> outputIdentifiers; DbExpression returning; List<DbModificationClause> setClauses = new List<DbModificationClause>(); foreach (DbModificationClause clause in BuildSetClauses( target, newRow, oldRow, processor, /* insertMode */ false, out outputIdentifiers, out returning, ref rowMustBeTouched)) { setClauses.Add(clause); } // Construct predicate identifying the row to modify DbExpression predicate = BuildPredicate(target, oldRow, newRow, processor, ref rowMustBeTouched); if (0 == setClauses.Count) { if (rowMustBeTouched) { List<IEntityStateEntry> stateEntries = new List<IEntityStateEntry>(); stateEntries.AddRange(SourceInterpreter.GetAllStateEntries( oldRow, m_translator, processor.Table)); stateEntries.AddRange(SourceInterpreter.GetAllStateEntries( newRow, m_translator, processor.Table)); if (stateEntries.All(it => (it.State == EntityState.Unchanged))) { rowMustBeTouched = false; } } // Determine if there is nothing to do (i.e., no values to set, // no computed columns, and no concurrency validation required) if (!rowMustBeTouched) { return null; } } // Initialize DML command tree DbUpdateCommandTree commandTree = new DbUpdateCommandTree(m_translator.MetadataWorkspace, DataSpace.SSpace, target, predicate, setClauses.AsReadOnly(), returning); // Create command UpdateCommand command = new DynamicUpdateCommand(processor, m_translator, ModificationOperator.Update, oldRow, newRow, commandTree, outputIdentifiers); return command; }
/// <summary> /// Builds insert command. /// </summary> /// <param name="newRow">Row to insert.</param> /// <param name="processor">Context for the table we're inserting into.</param> /// <returns>Insert command.</returns> internal UpdateCommand BuildInsertCommand(PropagatorResult newRow, TableChangeProcessor processor) { // Bind the insert target DbExpressionBinding target = GetTarget(processor); // Create set clauses and returning parameter Dictionary<int, string> outputIdentifiers; DbExpression returning; bool rowMustBeTouched = true; // for inserts, the row must always be touched List<DbModificationClause> setClauses = new List<DbModificationClause>(); foreach (DbModificationClause clause in BuildSetClauses(target, newRow, null, processor, /* insertMode */ true, out outputIdentifiers, out returning, ref rowMustBeTouched)) { setClauses.Add(clause); } // Initialize DML command tree DbInsertCommandTree commandTree = new DbInsertCommandTree(m_translator.MetadataWorkspace, DataSpace.SSpace, target, setClauses.AsReadOnly(), returning); // Create command UpdateCommand command = new DynamicUpdateCommand(processor, m_translator, ModificationOperator.Insert, null, newRow, commandTree, outputIdentifiers); return command; }