Example #1
0
        /// <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);
        }
Example #3
0
        /// <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;
        }
Example #5
0
        /// <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;
        }