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);
        }
Exemple #2
0
            /// <summary>
            /// Constructor
            /// </summary>
            /// <param name="metadata">Sets Metadata</param>
            /// <param name="record">Record containing key value</param>
            /// <param name="isTarget">Indicates whether the source or target end of the constraint
            /// is being pulled</param>
            /// <param name="isInsert">Indicates whether this is an insert dependency or a delete
            /// dependency</param>
            private ForeignKeyValue(ReferentialConstraint metadata, PropagatorResult record,
                bool isTarget, bool isInsert)
            {
                Metadata = metadata;

                // construct key
                IList<EdmProperty> keyProperties = isTarget ? metadata.FromProperties :
                    metadata.ToProperties;
                PropagatorResult[] keyValues = new PropagatorResult[keyProperties.Count];
                bool hasNullMember = false;
                for (int i = 0; i < keyValues.Length; i++)
                {
                    keyValues[i] = record.GetMemberValue(keyProperties[i]);
                    if (keyValues[i].IsNull)
                    {
                        hasNullMember = true;
                        break;
                    }
                }

                if (hasNullMember)
                {
                    // set key to null to indicate that it is not behaving as a key
                    // (in SQL, keys with null parts do not participate in constraints)
                    Key = null;
                }
                else
                {
                    Key = new CompositeKey(keyValues);
                }

                IsInsert = isInsert;
            }
            // Walks through all parameter bindings in the function mapping and binds the parameters to the
            // requested properties of the given state entry.
            private void BindFunctionParameters(UpdateTranslator translator, ExtractedStateEntry stateEntry, StorageModificationFunctionMapping functionMapping, FunctionUpdateCommand command, Dictionary <AssociationEndMember, IEntityStateEntry> currentReferenceEnds, Dictionary <AssociationEndMember, IEntityStateEntry> originalReferenceEnds)
            {
                // bind all parameters
                foreach (StorageModificationFunctionParameterBinding parameterBinding in functionMapping.ParameterBindings)
                {
                    PropagatorResult result;

                    // extract value
                    if (null != parameterBinding.MemberPath.AssociationSetEnd)
                    {
                        // find the relationship entry corresponding to the navigation
                        AssociationEndMember endMember = parameterBinding.MemberPath.AssociationSetEnd.CorrespondingAssociationEndMember;
                        IEntityStateEntry    relationshipEntry;
                        bool hasTarget = parameterBinding.IsCurrent
                            ? currentReferenceEnds.TryGetValue(endMember, out relationshipEntry)
                            : originalReferenceEnds.TryGetValue(endMember, out relationshipEntry);
                        if (!hasTarget)
                        {
                            if (endMember.RelationshipMultiplicity == RelationshipMultiplicity.One)
                            {
                                string entitySetName      = stateEntry.Source.EntitySet.Name;
                                string associationSetName = parameterBinding.MemberPath.AssociationSetEnd.ParentAssociationSet.Name;
                                throw EntityUtil.Update(Strings.Update_MissingRequiredRelationshipValue(entitySetName, associationSetName),
                                                        null,
                                                        command.GetStateEntries(translator));
                            }
                            else
                            {
                                result = PropagatorResult.CreateSimpleValue(PropagatorFlags.NoFlags, null);
                            }
                        }
                        else
                        {
                            // get the actual value
                            PropagatorResult relationshipResult = parameterBinding.IsCurrent ?
                                                                  translator.RecordConverter.ConvertCurrentValuesToPropagatorResult(relationshipEntry, ModifiedPropertiesBehavior.AllModified) :
                                                                  translator.RecordConverter.ConvertOriginalValuesToPropagatorResult(relationshipEntry, ModifiedPropertiesBehavior.AllModified);
                            PropagatorResult endResult   = relationshipResult.GetMemberValue(endMember);
                            EdmProperty      keyProperty = (EdmProperty)parameterBinding.MemberPath.Members[0];
                            result = endResult.GetMemberValue(keyProperty);
                        }
                    }
                    else
                    {
                        // walk through the member path to find the appropriate propagator results
                        result = parameterBinding.IsCurrent ? stateEntry.Current : stateEntry.Original;
                        for (int i = parameterBinding.MemberPath.Members.Count; i > 0;)
                        {
                            --i;
                            EdmMember member = parameterBinding.MemberPath.Members[i];
                            result = result.GetMemberValue(member);
                        }
                    }

                    // create DbParameter
                    command.SetParameterValue(result, parameterBinding, translator);
                }
                // Add rows affected parameter
                command.RegisterRowsAffectedParameter(functionMapping.RowsAffectedParameter);
            }
        // Extracts key constants from the given row.
        private PropagatorResult[] GetKeyConstants(PropagatorResult row)
        {
            PropagatorResult[] keyConstants = new PropagatorResult[m_keyOrdinals.Length];
            for (int i = 0; i < m_keyOrdinals.Length; i++)
            {
                PropagatorResult constant = row.GetMemberValue(m_keyOrdinals[i]);

                keyConstants[i] = constant;
            }
            return(keyConstants);
        }
            internal override FunctionUpdateCommand Translate(
                UpdateTranslator translator,
                ExtractedStateEntry stateEntry)
            {
                if (null == m_mapping)
                {
                    return(null);
                }

                bool isInsert = EntityState.Added == stateEntry.State;

                EntityUtil.ValidateNecessaryModificationFunctionMapping(
                    isInsert ? m_mapping.InsertFunctionMapping : m_mapping.DeleteFunctionMapping,
                    isInsert ? "Insert" : "Delete",
                    stateEntry.Source, "AssociationSet", m_mapping.AssociationSet.Name);

                // initialize a new command
                StorageModificationFunctionMapping functionMapping = isInsert ? m_mapping.InsertFunctionMapping : m_mapping.DeleteFunctionMapping;
                FunctionUpdateCommand command = new FunctionUpdateCommand(functionMapping, translator, new [] { stateEntry.Source }.ToList().AsReadOnly(), stateEntry);

                // extract the relationship values from the state entry
                PropagatorResult recordResult;

                if (isInsert)
                {
                    recordResult = stateEntry.Current;
                }
                else
                {
                    recordResult = stateEntry.Original;
                }

                // bind parameters
                foreach (StorageModificationFunctionParameterBinding parameterBinding in functionMapping.ParameterBindings)
                {
                    // extract the relationship information
                    Debug.Assert(2 == parameterBinding.MemberPath.Members.Count, "relationship parameter binding member " +
                                 "path should include the relationship end and key property only");

                    EdmProperty          keyProperty = (EdmProperty)parameterBinding.MemberPath.Members[0];
                    AssociationEndMember endMember   = (AssociationEndMember)parameterBinding.MemberPath.Members[1];

                    // get the end member
                    PropagatorResult endResult = recordResult.GetMemberValue(endMember);
                    PropagatorResult keyResult = endResult.GetMemberValue(keyProperty);

                    command.SetParameterValue(keyResult, parameterBinding, translator);
                }
                // add rows affected output parameter
                command.RegisterRowsAffectedParameter(functionMapping.RowsAffectedParameter);

                return(command);
            }
        /// <summary>
        /// Determines predicate used to identify a row in a table.
        /// </summary>
        /// <remarks>
        /// Columns are included in the list when:
        /// <list>
        /// <item>They are keys for the table</item>
        /// <item>They are concurrency values</item>
        /// </list>
        /// </remarks>
        /// <param name="target">Expression binding representing the table containing the row</param>
        /// <param name="referenceRow">Values for the row being located.</param>
        /// <param name="current">Values being updated (may be null).</param>
        /// <param name="processor">Context for the table containing the row.</param>
        /// <param name="rowMustBeTouched">Output parameter indicating whether a row must be touched
        /// (whether it's being modified or not) because it contains a concurrency value</param>
        /// <returns>Column/value pairs.</returns>
        private DbExpression BuildPredicate(DbExpressionBinding target, PropagatorResult referenceRow, PropagatorResult current,
                                            TableChangeProcessor processor, ref bool rowMustBeTouched)
        {
            Dictionary <EdmProperty, PropagatorResult> whereClauses = new Dictionary <EdmProperty, PropagatorResult>();

            // add all concurrency tokens (note that keys are always concurrency tokens as well)
            int propertyOrdinal = 0;

            foreach (EdmProperty member in processor.Table.ElementType.Properties)
            {
                // members and result values are ordinally aligned
                PropagatorResult expectedValue = referenceRow.GetMemberValue(propertyOrdinal);
                PropagatorResult newValue      = null == current ? null : current.GetMemberValue(propertyOrdinal);

                // check if the rowMustBeTouched value should be set to true (if it isn't already
                // true and we've come across a concurrency value)
                if (!rowMustBeTouched &&
                    (HasFlag(expectedValue, PropagatorFlags.ConcurrencyValue) ||
                     HasFlag(newValue, PropagatorFlags.ConcurrencyValue)))
                {
                    rowMustBeTouched = true;
                }

                // determine if this is a concurrency value
                if (!whereClauses.ContainsKey(member) &&                                         // don't add to the set clause twice
                    (HasFlag(expectedValue, PropagatorFlags.ConcurrencyValue | PropagatorFlags.Key) ||
                     HasFlag(newValue, PropagatorFlags.ConcurrencyValue | PropagatorFlags.Key))) // tagged as concurrency value
                {
                    whereClauses.Add(member, expectedValue);
                }
                propertyOrdinal++;
            }

            // Build a binary AND expression tree from the clauses
            DbExpression predicate = null;

            foreach (KeyValuePair <EdmProperty, PropagatorResult> clause in whereClauses)
            {
                DbExpression clauseExpression = GenerateEqualityExpression(target, clause.Key, clause.Value);
                if (null == predicate)
                {
                    predicate = clauseExpression;
                }
                else
                {
                    predicate = predicate.And(clauseExpression);
                }
            }

            Debug.Assert(null != predicate, "some predicate term must exist");

            return(predicate);
        }
        // Extracts key constants from the given row.
        private PropagatorResult[] GetKeyConstants(PropagatorResult row)
        {
            PropagatorResult[] keyConstants = new PropagatorResult[m_keyOrdinals.Length];
            for (int i = 0; i < m_keyOrdinals.Length; i++)
            {
                PropagatorResult constant = row.GetMemberValue(m_keyOrdinals[i]);

                keyConstants[i] = constant;
            }
            return keyConstants;
        }
        /// <summary>
        /// Determines predicate used to identify a row in a table.
        /// </summary>
        /// <remarks>
        /// Columns are included in the list when:
        /// <list>
        /// <item>They are keys for the table</item>
        /// <item>They are concurrency values</item>
        /// </list>
        /// </remarks>
        /// <param name="target">Expression binding representing the table containing the row</param>
        /// <param name="referenceRow">Values for the row being located.</param>
        /// <param name="current">Values being updated (may be null).</param>
        /// <param name="processor">Context for the table containing the row.</param>
        /// <param name="rowMustBeTouched">Output parameter indicating whether a row must be touched
        /// (whether it's being modified or not) because it contains a concurrency value</param>
        /// <returns>Column/value pairs.</returns>
        private DbExpression BuildPredicate(DbExpressionBinding target, PropagatorResult referenceRow, PropagatorResult current,
            TableChangeProcessor processor, ref bool rowMustBeTouched)
        {
            Dictionary<EdmProperty, PropagatorResult> whereClauses = new Dictionary<EdmProperty, PropagatorResult>();

            // add all concurrency tokens (note that keys are always concurrency tokens as well)
            int propertyOrdinal = 0;
            foreach (EdmProperty member in processor.Table.ElementType.Properties)
            {
                // members and result values are ordinally aligned
                PropagatorResult expectedValue = referenceRow.GetMemberValue(propertyOrdinal);
                PropagatorResult newValue = null == current ? null : current.GetMemberValue(propertyOrdinal);

                // check if the rowMustBeTouched value should be set to true (if it isn't already
                // true and we've come across a concurrency value)
                if (!rowMustBeTouched &&
                    (HasFlag(expectedValue, PropagatorFlags.ConcurrencyValue) ||
                     HasFlag(newValue, PropagatorFlags.ConcurrencyValue)))
                {
                    rowMustBeTouched = true;
                }

                // determine if this is a concurrency value
                if (!whereClauses.ContainsKey(member) && // don't add to the set clause twice
                    (HasFlag(expectedValue, PropagatorFlags.ConcurrencyValue | PropagatorFlags.Key) ||
                     HasFlag(newValue, PropagatorFlags.ConcurrencyValue | PropagatorFlags.Key))) // tagged as concurrency value
                {
                    whereClauses.Add(member, expectedValue);
                }
                propertyOrdinal++;
            }

            // Build a binary AND expression tree from the clauses
            DbExpression predicate = null;
            foreach (KeyValuePair<EdmProperty, PropagatorResult> clause in whereClauses)
            {
                DbExpression clauseExpression = GenerateEqualityExpression(target, clause.Key, clause.Value);
                if (null == predicate) { predicate = clauseExpression; }
                else { predicate = predicate.And(clauseExpression); }
            }

            Debug.Assert(null != predicate, "some predicate term must exist");

            return predicate;
        }
        /// <summary>
        /// Determines column/value used to set values for a row.
        /// </summary>
        /// <remarks>
        /// The following columns are not included in the result:
        /// <list>
        /// <item>Keys in non-insert operations (keys are only set for inserts).</item>
        /// <item>Values flagged 'preserve' (these are values the propagator claims are untouched).</item>
        /// <item>Server generated values.</item>
        /// </list>
        /// </remarks>
        /// <param name="target">Expression binding representing the table.</param>
        /// <param name="row">Row containing values to set.</param>
        /// <param name="processor">Context for table.</param>
        /// <param name="insertMode">Determines whether key columns and 'preserve' columns are 
        /// omitted from the list.</param>
        /// <param name="outputIdentifiers">Dictionary listing server generated identifiers.</param>
        /// <param name="returning">DbExpression describing result projection for server generated values.</param>
        /// <param name="rowMustBeTouched">Indicates whether the row must be touched 
        /// because it produces a value (e.g. computed)</param>
        /// <returns>Column value pairs.</returns>
        private IEnumerable<DbModificationClause> BuildSetClauses(DbExpressionBinding target, PropagatorResult row,
            PropagatorResult originalRow, TableChangeProcessor processor, bool insertMode, out Dictionary<int, string> outputIdentifiers, out DbExpression returning,
            ref bool rowMustBeTouched)
        {
            Dictionary<EdmProperty, PropagatorResult> setClauses = new Dictionary<EdmProperty, PropagatorResult>();
            List<KeyValuePair<string, DbExpression>> returningArguments = new List<KeyValuePair<string, DbExpression>>();
            outputIdentifiers = new Dictionary<int, string>();

            // Determine which flags indicate a property should be omitted from the set list.
            PropagatorFlags omitMask = insertMode ? PropagatorFlags.NoFlags :
                PropagatorFlags.Preserve | PropagatorFlags.Unknown;

            for (int propertyOrdinal = 0; propertyOrdinal < processor.Table.ElementType.Properties.Count; propertyOrdinal++)
            {
                EdmProperty property = processor.Table.ElementType.Properties[propertyOrdinal];

                // Type members and result values are ordinally aligned
                PropagatorResult propertyResult = row.GetMemberValue(propertyOrdinal);

                if (PropagatorResult.NullIdentifier != propertyResult.Identifier)
                {
                    // retrieve principal value
                    propertyResult = propertyResult.ReplicateResultWithNewValue(
                        m_translator.KeyManager.GetPrincipalValue(propertyResult));
                }

                bool omitFromSetList = false;

                Debug.Assert(propertyResult.IsSimple);

                // Determine if this is a key value
                bool isKey = false;
                for (int i = 0; i < processor.KeyOrdinals.Length; i++)
                {
                    if (processor.KeyOrdinals[i] == propertyOrdinal)
                    {
                        isKey = true;
                        break;
                    }
                }

                // check if this value should be omitted
                PropagatorFlags flags = PropagatorFlags.NoFlags;
                if (!insertMode && isKey)
                {
                    // Keys are only set for inserts
                    omitFromSetList = true;
                }
                else
                {
                    // See if this value has been marked up with some context. If so, add the flag information
                    // from the markup. Markup includes information about whether the property is a concurrency value,
                    // whether it is known (it may be a property that is preserved across an update for instance)
                    flags |= propertyResult.PropagatorFlags;
                }

                // Determine if this value is server-generated
                StoreGeneratedPattern genPattern = MetadataHelper.GetStoreGeneratedPattern(property);
                bool isServerGen = genPattern == StoreGeneratedPattern.Computed ||
                    (insertMode && genPattern == StoreGeneratedPattern.Identity);
                if (isServerGen)
                {
                    DbPropertyExpression propertyExpression = target.Variable.Property(property);
                    returningArguments.Add(new KeyValuePair<string, DbExpression>(property.Name, propertyExpression));

                    // check if this is a server generated identifier
                    int identifier = propertyResult.Identifier;
                    if (PropagatorResult.NullIdentifier != identifier)
                    {
                        if (m_translator.KeyManager.HasPrincipals(identifier))
                        {
                            throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.Update_GeneratedDependent(property.Name));
                        }
                        outputIdentifiers.Add(identifier, property.Name);

                        // If this property maps an identifier (in the update pipeline) it may
                        // also be a store key. If so, the pattern had better be "Identity"
                        // since otherwise we're dealing with a mutable key.
                        if (genPattern != StoreGeneratedPattern.Identity &&
                            processor.IsKeyProperty(propertyOrdinal))
                        {
                            throw EntityUtil.NotSupported(System.Data.Entity.Strings.Update_NotSupportedComputedKeyColumn(
                                EdmProviderManifest.StoreGeneratedPatternFacetName,
                                XmlConstants.Computed,
                                XmlConstants.Identity,
                                property.Name,
                                property.DeclaringType.FullName));
                        }
                    }
                }

                if (PropagatorFlags.NoFlags != (flags & (omitMask)))
                {
                    // column value matches "omit" pattern, therefore should not be set
                    omitFromSetList = true;
                }
                else if (isServerGen)
                {
                    // column value does not match "omit" pattern, but it is server generated
                    // so it cannot be set
                    omitFromSetList = true;

                    // if the row has a modified value overridden by server gen,
                    // it must still be touched in order to retrieve the value
                    rowMustBeTouched = true;
                }

                // make the user is not updating an identity value
                if (!omitFromSetList && !insertMode && genPattern == StoreGeneratedPattern.Identity)
                {
                    //throw the error only if the value actually changed
                    Debug.Assert(originalRow != null, "Updated records should have a original row");
                    PropagatorResult originalPropertyResult = originalRow.GetMemberValue(propertyOrdinal);
                    Debug.Assert(originalPropertyResult.IsSimple, "Server Gen property that is not primitive?");
                    Debug.Assert(propertyResult.IsSimple, "Server Gen property that is not primitive?");

                    if (!ByValueEqualityComparer.Default.Equals(originalPropertyResult.GetSimpleValue(), propertyResult.GetSimpleValue()))
                    {
                        throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.Update_ModifyingIdentityColumn(
                            XmlConstants.Identity,
                            property.Name,
                            property.DeclaringType.FullName));
                    }
                    else
                    {
                        omitFromSetList = true;
                    }
                }

                if (!omitFromSetList) { setClauses.Add(property, propertyResult); }
            }

            // Construct returning projection
            if (0 < returningArguments.Count)
            {
                returning = DbExpressionBuilder.NewRow(returningArguments);
            }
            else
            {
                returning = null;
            }

            // Construct clauses corresponding to the set clauses
            List<DbModificationClause> result = new List<DbModificationClause>(setClauses.Count);
            foreach (KeyValuePair<EdmProperty, PropagatorResult> setClause in setClauses)
            {
                EdmProperty property = setClause.Key;

                result.Add(new DbSetClause(
                    GeneratePropertyExpression(target, setClause.Key),
                    GenerateValueExpression(setClause.Key, setClause.Value)));
            }

            return result;
        }
        /// <summary>
        /// Determines column/value used to set values for a row.
        /// </summary>
        /// <remarks>
        /// The following columns are not included in the result:
        /// <list>
        /// <item>Keys in non-insert operations (keys are only set for inserts).</item>
        /// <item>Values flagged 'preserve' (these are values the propagator claims are untouched).</item>
        /// <item>Server generated values.</item>
        /// </list>
        /// </remarks>
        /// <param name="target">Expression binding representing the table.</param>
        /// <param name="row">Row containing values to set.</param>
        /// <param name="processor">Context for table.</param>
        /// <param name="insertMode">Determines whether key columns and 'preserve' columns are
        /// omitted from the list.</param>
        /// <param name="outputIdentifiers">Dictionary listing server generated identifiers.</param>
        /// <param name="returning">DbExpression describing result projection for server generated values.</param>
        /// <param name="rowMustBeTouched">Indicates whether the row must be touched
        /// because it produces a value (e.g. computed)</param>
        /// <returns>Column value pairs.</returns>
        private IEnumerable <DbModificationClause> BuildSetClauses(DbExpressionBinding target, PropagatorResult row,
                                                                   PropagatorResult originalRow, TableChangeProcessor processor, bool insertMode, out Dictionary <int, string> outputIdentifiers, out DbExpression returning,
                                                                   ref bool rowMustBeTouched)
        {
            Dictionary <EdmProperty, PropagatorResult>  setClauses         = new Dictionary <EdmProperty, PropagatorResult>();
            List <KeyValuePair <string, DbExpression> > returningArguments = new List <KeyValuePair <string, DbExpression> >();

            outputIdentifiers = new Dictionary <int, string>();

            // Determine which flags indicate a property should be omitted from the set list.
            PropagatorFlags omitMask = insertMode ? PropagatorFlags.NoFlags :
                                       PropagatorFlags.Preserve | PropagatorFlags.Unknown;

            for (int propertyOrdinal = 0; propertyOrdinal < processor.Table.ElementType.Properties.Count; propertyOrdinal++)
            {
                EdmProperty property = processor.Table.ElementType.Properties[propertyOrdinal];

                // Type members and result values are ordinally aligned
                PropagatorResult propertyResult = row.GetMemberValue(propertyOrdinal);

                if (PropagatorResult.NullIdentifier != propertyResult.Identifier)
                {
                    // retrieve principal value
                    propertyResult = propertyResult.ReplicateResultWithNewValue(
                        m_translator.KeyManager.GetPrincipalValue(propertyResult));
                }

                bool omitFromSetList = false;

                Debug.Assert(propertyResult.IsSimple);

                // Determine if this is a key value
                bool isKey = false;
                for (int i = 0; i < processor.KeyOrdinals.Length; i++)
                {
                    if (processor.KeyOrdinals[i] == propertyOrdinal)
                    {
                        isKey = true;
                        break;
                    }
                }

                // check if this value should be omitted
                PropagatorFlags flags = PropagatorFlags.NoFlags;
                if (!insertMode && isKey)
                {
                    // Keys are only set for inserts
                    omitFromSetList = true;
                }
                else
                {
                    // See if this value has been marked up with some context. If so, add the flag information
                    // from the markup. Markup includes information about whether the property is a concurrency value,
                    // whether it is known (it may be a property that is preserved across an update for instance)
                    flags |= propertyResult.PropagatorFlags;
                }

                // Determine if this value is server-generated
                StoreGeneratedPattern genPattern = MetadataHelper.GetStoreGeneratedPattern(property);
                bool isServerGen = genPattern == StoreGeneratedPattern.Computed ||
                                   (insertMode && genPattern == StoreGeneratedPattern.Identity);
                if (isServerGen)
                {
                    DbPropertyExpression propertyExpression = target.Variable.Property(property);
                    returningArguments.Add(new KeyValuePair <string, DbExpression>(property.Name, propertyExpression));

                    // check if this is a server generated identifier
                    int identifier = propertyResult.Identifier;
                    if (PropagatorResult.NullIdentifier != identifier)
                    {
                        if (m_translator.KeyManager.HasPrincipals(identifier))
                        {
                            throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.Update_GeneratedDependent(property.Name));
                        }
                        outputIdentifiers.Add(identifier, property.Name);

                        // If this property maps an identifier (in the update pipeline) it may
                        // also be a store key. If so, the pattern had better be "Identity"
                        // since otherwise we're dealing with a mutable key.
                        if (genPattern != StoreGeneratedPattern.Identity &&
                            processor.IsKeyProperty(propertyOrdinal))
                        {
                            throw EntityUtil.NotSupported(System.Data.Entity.Strings.Update_NotSupportedComputedKeyColumn(
                                                              EdmProviderManifest.StoreGeneratedPatternFacetName,
                                                              XmlConstants.Computed,
                                                              XmlConstants.Identity,
                                                              property.Name,
                                                              property.DeclaringType.FullName));
                        }
                    }
                }

                if (PropagatorFlags.NoFlags != (flags & (omitMask)))
                {
                    // column value matches "omit" pattern, therefore should not be set
                    omitFromSetList = true;
                }
                else if (isServerGen)
                {
                    // column value does not match "omit" pattern, but it is server generated
                    // so it cannot be set
                    omitFromSetList = true;

                    // if the row has a modified value overridden by server gen,
                    // it must still be touched in order to retrieve the value
                    rowMustBeTouched = true;
                }

                // make the user is not updating an identity value
                if (!omitFromSetList && !insertMode && genPattern == StoreGeneratedPattern.Identity)
                {
                    //throw the error only if the value actually changed
                    Debug.Assert(originalRow != null, "Updated records should have a original row");
                    PropagatorResult originalPropertyResult = originalRow.GetMemberValue(propertyOrdinal);
                    Debug.Assert(originalPropertyResult.IsSimple, "Server Gen property that is not primitive?");
                    Debug.Assert(propertyResult.IsSimple, "Server Gen property that is not primitive?");

                    if (!ByValueEqualityComparer.Default.Equals(originalPropertyResult.GetSimpleValue(), propertyResult.GetSimpleValue()))
                    {
                        throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.Update_ModifyingIdentityColumn(
                                                              XmlConstants.Identity,
                                                              property.Name,
                                                              property.DeclaringType.FullName));
                    }
                    else
                    {
                        omitFromSetList = true;
                    }
                }

                if (!omitFromSetList)
                {
                    setClauses.Add(property, propertyResult);
                }
            }

            // Construct returning projection
            if (0 < returningArguments.Count)
            {
                returning = DbExpressionBuilder.NewRow(returningArguments);
            }
            else
            {
                returning = null;
            }

            // Construct clauses corresponding to the set clauses
            List <DbModificationClause> result = new List <DbModificationClause>(setClauses.Count);

            foreach (KeyValuePair <EdmProperty, PropagatorResult> setClause in setClauses)
            {
                EdmProperty property = setClause.Key;

                result.Add(new DbSetClause(
                               GeneratePropertyExpression(target, setClause.Key),
                               GenerateValueExpression(setClause.Key, setClause.Value)));
            }

            return(result);
        }