Ejemplo n.º 1
0
            /// <summary>
            /// Constructs a join propagator.
            /// </summary>
            /// <param name="left">Result of propagating changes in the left input to the join</param>
            /// <param name="right">Result of propagating changes in the right input to the join</param>
            /// <param name="node">Join operator in update mapping view over which to propagate changes</param>
            /// <param name="parent">Handler of propagation for the entire update mapping view</param>
            internal JoinPropagator(ChangeNode left, ChangeNode right, DbJoinExpression node, Propagator parent)
            {
                EntityUtil.CheckArgumentNull(left, "left");
                EntityUtil.CheckArgumentNull(right, "right");
                EntityUtil.CheckArgumentNull(node, "node");
                EntityUtil.CheckArgumentNull(parent, "parent");

                m_left           = left;
                m_right          = right;
                m_joinExpression = node;
                m_parent         = parent;

                Debug.Assert(DbExpressionKind.LeftOuterJoin == node.ExpressionKind || DbExpressionKind.InnerJoin == node.ExpressionKind, "(Update/JoinPropagagtor/JoinEvaluator) " +
                             "caller must ensure only left outer and inner joins are requested");
                // Retrieve propagation rules for the join type of the expression.
                if (DbExpressionKind.InnerJoin == m_joinExpression.ExpressionKind)
                {
                    m_insertRules = s_innerJoinInsertRules;
                    m_deleteRules = s_innerJoinDeleteRules;
                }
                else
                {
                    m_insertRules = s_leftOuterJoinInsertRules;
                    m_deleteRules = s_leftOuterJoinDeleteRules;
                }

                // Figure out key selectors involved in the equi-join (if it isn't an equi-join, we don't support it)
                JoinConditionVisitor.GetKeySelectors(node.JoinCondition, out m_leftKeySelectors, out m_rightKeySelectors);

                // Find the key selector expressions in the left and right placeholders
                m_leftPlaceholderKey  = ExtractKey(m_left.Placeholder, m_leftKeySelectors, m_parent);
                m_rightPlaceholderKey = ExtractKey(m_right.Placeholder, m_rightKeySelectors, m_parent);
            }
            /// <summary>
            /// Constructs a join propagator.
            /// </summary>
            /// <param name="left">Result of propagating changes in the left input to the join</param>
            /// <param name="right">Result of propagating changes in the right input to the join</param>
            /// <param name="node">Join operator in update mapping view over which to propagate changes</param>
            /// <param name="parent">Handler of propagation for the entire update mapping view</param>
            internal JoinPropagator(ChangeNode left, ChangeNode right, DbJoinExpression node, Propagator parent)
            {
                EntityUtil.CheckArgumentNull(left, "left");
                EntityUtil.CheckArgumentNull(right, "right");
                EntityUtil.CheckArgumentNull(node, "node");
                EntityUtil.CheckArgumentNull(parent, "parent");

                m_left = left;
                m_right = right;
                m_joinExpression = node;
                m_parent = parent;

                Debug.Assert(DbExpressionKind.LeftOuterJoin == node.ExpressionKind || DbExpressionKind.InnerJoin == node.ExpressionKind, "(Update/JoinPropagagtor/JoinEvaluator) " +
                    "caller must ensure only left outer and inner joins are requested");
                // Retrieve propagation rules for the join type of the expression.
                if (DbExpressionKind.InnerJoin == m_joinExpression.ExpressionKind)
                {
                    m_insertRules = s_innerJoinInsertRules;
                    m_deleteRules = s_innerJoinDeleteRules;
                }
                else
                {
                    m_insertRules = s_leftOuterJoinInsertRules;
                    m_deleteRules = s_leftOuterJoinDeleteRules;
                }

                // Figure out key selectors involved in the equi-join (if it isn't an equi-join, we don't support it)
                JoinConditionVisitor.GetKeySelectors(node.JoinCondition, out m_leftKeySelectors, out m_rightKeySelectors);

                // Find the key selector expressions in the left and right placeholders
                m_leftPlaceholderKey = ExtractKey(m_left.Placeholder, m_leftKeySelectors, m_parent);
                m_rightPlaceholderKey = ExtractKey(m_right.Placeholder, m_rightKeySelectors, m_parent);
            }
Ejemplo n.º 3
0
            /// <summary>
            /// Performs join propagation.
            /// </summary>
            /// <returns>Changes propagated to the current join node in the update mapping view.</returns>
            internal ChangeNode Propagate()
            {
                // Construct an empty change node for the result
                ChangeNode result = Propagator.BuildChangeNode(m_joinExpression);

                // Gather all keys involved in the join
                JoinDictionary leftDeletes  = ProcessKeys(m_left.Deleted, m_leftKeySelectors);
                JoinDictionary leftInserts  = ProcessKeys(m_left.Inserted, m_leftKeySelectors);
                JoinDictionary rightDeletes = ProcessKeys(m_right.Deleted, m_rightKeySelectors);
                JoinDictionary rightInserts = ProcessKeys(m_right.Inserted, m_rightKeySelectors);
                var            allKeys      = leftDeletes.Keys
                                              .Concat(leftInserts.Keys)
                                              .Concat(rightDeletes.Keys)
                                              .Concat(rightInserts.Keys)
                                              .Distinct(m_parent.UpdateTranslator.KeyComparer);

                // Perform propagation one key at a time
                foreach (CompositeKey key in allKeys)
                {
                    Propagate(key, result, leftDeletes, leftInserts, rightDeletes, rightInserts);
                }

                // Construct a new placeholder (see ChangeNode.Placeholder) for the join result node.
                result.Placeholder = CreateResultTuple(Tuple.Create((CompositeKey)null, m_left.Placeholder), Tuple.Create((CompositeKey)null, m_right.Placeholder), result);

                return(result);
            }
Ejemplo n.º 4
0
            /// <summary>
            /// Produce a tuple containing joined rows.
            /// </summary>
            /// <param name="left">Left row.</param>
            /// <param name="right">Right row.</param>
            /// <param name="leftKey">Key used to join left element.</param>
            /// <param name="rightKey">Key used to join right element.</param>
            /// <param name="result">Result change node; used for type information.</param>
            /// <returns>Result of joining the input rows.</returns>
            private PropagatorResult CreateResultTuple(Tuple <CompositeKey, PropagatorResult> left, Tuple <CompositeKey, PropagatorResult> right, ChangeNode result)
            {
                // using ref compare to avoid triggering value based
                CompositeKey leftKey  = left.Item1;
                CompositeKey rightKey = right.Item1;
                Dictionary <PropagatorResult, PropagatorResult> map = null;

                if (!object.ReferenceEquals(null, leftKey) &&
                    !object.ReferenceEquals(null, rightKey) &&
                    !object.ReferenceEquals(leftKey, rightKey))
                {
                    // Merge key values from the left and the right (since they're equal, there's a possibility we'll
                    // project values only from the left or the right hand side and lose important context.)
                    CompositeKey mergedKey = leftKey.Merge(m_parent.m_updateTranslator.KeyManager, rightKey);
                    // create a dictionary so that we can replace key values with merged key values (carrying context
                    // from both sides)
                    map = new Dictionary <PropagatorResult, PropagatorResult>();
                    for (int i = 0; i < leftKey.KeyComponents.Length; i++)
                    {
                        map[leftKey.KeyComponents[i]]  = mergedKey.KeyComponents[i];
                        map[rightKey.KeyComponents[i]] = mergedKey.KeyComponents[i];
                    }
                }

                PropagatorResult[] joinRecordValues = new PropagatorResult[2];
                joinRecordValues[0] = left.Item2;
                joinRecordValues[1] = right.Item2;
                PropagatorResult join = PropagatorResult.CreateStructuralValue(joinRecordValues, (StructuralType)result.ElementType.EdmType, false);

                // replace with merged key values as appropriate
                if (null != map)
                {
                    PropagatorResult replacement;
                    join = join.Replace(original => map.TryGetValue(original, out replacement) ? replacement : original);
                }

                return(join);
            }
Ejemplo n.º 5
0
            /// <summary>
            /// Propagate all changes associated with a particular join key.
            /// </summary>
            /// <param name="key">Key.</param>
            /// <param name="result">Resulting changes are added to this result.</param>
            private void Propagate(CompositeKey key, ChangeNode result, JoinDictionary leftDeletes, JoinDictionary leftInserts,
                                   JoinDictionary rightDeletes, JoinDictionary rightInserts)
            {
                // Retrieve changes associates with this join key
                Tuple <CompositeKey, PropagatorResult> leftInsert  = null;
                Tuple <CompositeKey, PropagatorResult> leftDelete  = null;
                Tuple <CompositeKey, PropagatorResult> rightInsert = null;
                Tuple <CompositeKey, PropagatorResult> rightDelete = null;

                Ops input = Ops.Nothing;

                if (leftInserts.TryGetValue(key, out leftInsert))
                {
                    input |= Ops.LeftInsert;
                }
                if (leftDeletes.TryGetValue(key, out leftDelete))
                {
                    input |= Ops.LeftDelete;
                }
                if (rightInserts.TryGetValue(key, out rightInsert))
                {
                    input |= Ops.RightInsert;
                }
                if (rightDeletes.TryGetValue(key, out rightDelete))
                {
                    input |= Ops.RightDelete;
                }

                // Get propagation rules for the changes
                Ops insertRule = m_insertRules[input];
                Ops deleteRule = m_deleteRules[input];

                if (Ops.Unsupported == insertRule || Ops.Unsupported == deleteRule)
                {
                    // If no propagation rules are defined, it suggests an invalid workload (e.g.
                    // a required entity or relationship is missing). In general, such exceptions
                    // should be caught by the RelationshipConstraintValidator, but we defensively
                    // check for problems here regardless. For instance, a 0..1:1..1 self-assocation
                    // implied a stronger constraint that cannot be checked by RelationshipConstraintValidator.

                    // First gather state entries contributing to the problem
                    List <IEntityStateEntry> stateEntries = new List <IEntityStateEntry>();
                    Action <Tuple <CompositeKey, PropagatorResult> > addStateEntries = (r) =>
                    {
                        if (r != null)
                        {
                            stateEntries.AddRange(SourceInterpreter.GetAllStateEntries(r.Item2, this.m_parent.m_updateTranslator,
                                                                                       this.m_parent.m_table));
                        }
                    };
                    addStateEntries(leftInsert);
                    addStateEntries(leftDelete);
                    addStateEntries(rightInsert);
                    addStateEntries(rightDelete);

                    throw EntityUtil.Update(Strings.Update_InvalidChanges, null, stateEntries);
                }

                // Where needed, substitute null/unknown placeholders. In some of the join propagation
                // rules, we handle the case where a side of the join is 'unknown', or where one side
                // of a join is comprised of an record containing only nulls. For instance, we may update
                // only one extent appearing in a row of a table (unknown), or; we may insert only
                // the left hand side of a left outer join, in which case the right hand side is 'null'.
                if (0 != (Ops.LeftUnknown & insertRule))
                {
                    leftInsert = Tuple.Create(key, LeftPlaceholder(key, PopulateMode.Unknown));
                }
                if (0 != (Ops.LeftUnknown & deleteRule))
                {
                    leftDelete = Tuple.Create(key, LeftPlaceholder(key, PopulateMode.Unknown));
                }
                if (0 != (Ops.RightNullModified & insertRule))
                {
                    rightInsert = Tuple.Create(key, RightPlaceholder(key, PopulateMode.NullModified));
                }
                else if (0 != (Ops.RightNullPreserve & insertRule))
                {
                    rightInsert = Tuple.Create(key, RightPlaceholder(key, PopulateMode.NullPreserve));
                }
                else if (0 != (Ops.RightUnknown & insertRule))
                {
                    rightInsert = Tuple.Create(key, RightPlaceholder(key, PopulateMode.Unknown));
                }

                if (0 != (Ops.RightNullModified & deleteRule))
                {
                    rightDelete = Tuple.Create(key, RightPlaceholder(key, PopulateMode.NullModified));
                }
                else if (0 != (Ops.RightNullPreserve & deleteRule))
                {
                    rightDelete = Tuple.Create(key, RightPlaceholder(key, PopulateMode.NullPreserve));
                }
                else if (0 != (Ops.RightUnknown & deleteRule))
                {
                    rightDelete = Tuple.Create(key, RightPlaceholder(key, PopulateMode.Unknown));
                }

                // Populate elements in join output
                if (null != leftInsert && null != rightInsert)
                {
                    result.Inserted.Add(CreateResultTuple(leftInsert, rightInsert, result));
                }
                if (null != leftDelete && null != rightDelete)
                {
                    result.Deleted.Add(CreateResultTuple(leftDelete, rightDelete, 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;
        }
            /// <summary>
            /// Produce a tuple containing joined rows.
            /// </summary>
            /// <param name="left">Left row.</param>
            /// <param name="right">Right row.</param>
            /// <param name="leftKey">Key used to join left element.</param>
            /// <param name="rightKey">Key used to join right element.</param>
            /// <param name="result">Result change node; used for type information.</param>
            /// <returns>Result of joining the input rows.</returns>
            private PropagatorResult CreateResultTuple(Tuple<CompositeKey, PropagatorResult> left, Tuple<CompositeKey, PropagatorResult> right, ChangeNode result)
            {
                // using ref compare to avoid triggering value based
                CompositeKey leftKey = left.Item1;
                CompositeKey rightKey = right.Item1;
                Dictionary<PropagatorResult, PropagatorResult> map = null;
                if (!object.ReferenceEquals(null, leftKey) &&
                    !object.ReferenceEquals(null, rightKey) &&
                    !object.ReferenceEquals(leftKey, rightKey))
                {
                    // Merge key values from the left and the right (since they're equal, there's a possibility we'll
                    // project values only from the left or the right hand side and lose important context.)
                    CompositeKey mergedKey = leftKey.Merge(m_parent.m_updateTranslator.KeyManager, rightKey);
                    // create a dictionary so that we can replace key values with merged key values (carrying context
                    // from both sides)
                    map = new Dictionary<PropagatorResult, PropagatorResult>();
                    for (int i = 0; i < leftKey.KeyComponents.Length; i++)
                    {
                        map[leftKey.KeyComponents[i]] = mergedKey.KeyComponents[i];
                        map[rightKey.KeyComponents[i]] = mergedKey.KeyComponents[i];
                    }
                }

                PropagatorResult[] joinRecordValues = new PropagatorResult[2];
                joinRecordValues[0] = left.Item2;
                joinRecordValues[1] = right.Item2;
                PropagatorResult join = PropagatorResult.CreateStructuralValue(joinRecordValues, (StructuralType)result.ElementType.EdmType, false);

                // replace with merged key values as appropriate
                if (null != map)
                {
                    PropagatorResult replacement;
                    join = join.Replace(original => map.TryGetValue(original, out replacement) ? replacement : original);
                }

                return join;
            }
            /// <summary>
            /// Propagate all changes associated with a particular join key.
            /// </summary>
            /// <param name="key">Key.</param>
            /// <param name="result">Resulting changes are added to this result.</param>
            private void Propagate(CompositeKey key, ChangeNode result, JoinDictionary leftDeletes, JoinDictionary leftInserts,
                JoinDictionary rightDeletes, JoinDictionary rightInserts)
            {
                // Retrieve changes associates with this join key
                Tuple<CompositeKey, PropagatorResult> leftInsert = null;
                Tuple<CompositeKey, PropagatorResult> leftDelete = null;
                Tuple<CompositeKey, PropagatorResult> rightInsert = null;
                Tuple<CompositeKey, PropagatorResult> rightDelete = null;

                Ops input = Ops.Nothing;

                if (leftInserts.TryGetValue(key, out leftInsert)) { input |= Ops.LeftInsert; }
                if (leftDeletes.TryGetValue(key, out leftDelete)) { input |= Ops.LeftDelete; }
                if (rightInserts.TryGetValue(key, out rightInsert)) { input |= Ops.RightInsert; } 
                if (rightDeletes.TryGetValue(key, out rightDelete)) { input |= Ops.RightDelete; }

                // Get propagation rules for the changes
                Ops insertRule = m_insertRules[input];
                Ops deleteRule = m_deleteRules[input];

                if (Ops.Unsupported == insertRule || Ops.Unsupported == deleteRule)
                {
                    // If no propagation rules are defined, it suggests an invalid workload (e.g.
                    // a required entity or relationship is missing). In general, such exceptions
                    // should be caught by the RelationshipConstraintValidator, but we defensively
                    // check for problems here regardless. For instance, a 0..1:1..1 self-assocation
                    // implied a stronger constraint that cannot be checked by RelationshipConstraintValidator.

                    // First gather state entries contributing to the problem
                    List<IEntityStateEntry> stateEntries = new List<IEntityStateEntry>();
                    Action<Tuple<CompositeKey, PropagatorResult>> addStateEntries = (r) =>
                        {
                            if (r != null)
                            {
                                stateEntries.AddRange(SourceInterpreter.GetAllStateEntries(r.Item2, this.m_parent.m_updateTranslator,
                                    this.m_parent.m_table));
                            }
                        };
                    addStateEntries(leftInsert);
                    addStateEntries(leftDelete);
                    addStateEntries(rightInsert);
                    addStateEntries(rightDelete);

                    throw EntityUtil.Update(Strings.Update_InvalidChanges, null, stateEntries);
                }

                // Where needed, substitute null/unknown placeholders. In some of the join propagation
                // rules, we handle the case where a side of the join is 'unknown', or where one side
                // of a join is comprised of an record containing only nulls. For instance, we may update
                // only one extent appearing in a row of a table (unknown), or; we may insert only
                // the left hand side of a left outer join, in which case the right hand side is 'null'.
                if (0 != (Ops.LeftUnknown & insertRule))
                {
                    leftInsert = Tuple.Create(key, LeftPlaceholder(key, PopulateMode.Unknown));
                }
                if (0 != (Ops.LeftUnknown & deleteRule))
                {
                    leftDelete = Tuple.Create(key, LeftPlaceholder(key, PopulateMode.Unknown));
                }
                if (0 != (Ops.RightNullModified & insertRule)) 
                {
                    rightInsert = Tuple.Create(key, RightPlaceholder(key, PopulateMode.NullModified));
                }
                else if (0 != (Ops.RightNullPreserve & insertRule)) 
                {
                    rightInsert = Tuple.Create(key, RightPlaceholder(key, PopulateMode.NullPreserve));
                }
                else if (0 != (Ops.RightUnknown & insertRule)) 
                { 
                    rightInsert = Tuple.Create(key, RightPlaceholder(key, PopulateMode.Unknown)); 
                }

                if (0 != (Ops.RightNullModified & deleteRule)) 
                {
                    rightDelete = Tuple.Create(key, RightPlaceholder(key, PopulateMode.NullModified));
                }
                else if (0 != (Ops.RightNullPreserve & deleteRule)) 
                {
                    rightDelete = Tuple.Create(key, RightPlaceholder(key, PopulateMode.NullPreserve));
                }
                else if (0 != (Ops.RightUnknown & deleteRule)) 
                {
                    rightDelete = Tuple.Create(key, RightPlaceholder(key, PopulateMode.Unknown));
                }

                // Populate elements in join output
                if (null != leftInsert && null != rightInsert)
                {
                    result.Inserted.Add(CreateResultTuple(leftInsert, rightInsert, result));
                }
                if (null != leftDelete && null != rightDelete)
                {
                    result.Deleted.Add(CreateResultTuple(leftDelete, rightDelete, result));
                }
            }
        /// <summary>
        /// Retrieve a change node for an extent. If none exists, creates and registers a new one.
        /// </summary>
        /// <param name="extent">Extent for which to return a change node.</param>
        /// <returns>Change node for requested extent.</returns>
        internal ChangeNode GetExtentModifications(EntitySetBase extent)
        {
            EntityUtil.CheckArgumentNull(extent, "extent");
            Debug.Assert(null != m_changes, "(UpdateTranslator/GetChangeNodeForExtent) method called before translator initialized");

            ChangeNode changeNode;

            if (!m_changes.TryGetValue(extent, out changeNode))
            {
                changeNode = new ChangeNode(TypeUsage.Create(extent.ElementType));
                m_changes.Add(extent, changeNode);
            }

            return changeNode;
        }
Ejemplo n.º 10
0
        // 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);
        }