Beispiel #1
0
        private DbExpression BuildPredicate(
            DbExpressionBinding target,
            PropagatorResult referenceRow,
            PropagatorResult current,
            TableChangeProcessor processor,
            ref bool rowMustBeTouched)
        {
            Dictionary <EdmProperty, PropagatorResult> dictionary = new Dictionary <EdmProperty, PropagatorResult>();
            int ordinal = 0;

            foreach (EdmProperty property in processor.Table.ElementType.Properties)
            {
                PropagatorResult memberValue = referenceRow.GetMemberValue(ordinal);
                PropagatorResult input       = current == null ? (PropagatorResult)null : current.GetMemberValue(ordinal);
                if (!rowMustBeTouched && (UpdateCompiler.HasFlag(memberValue, PropagatorFlags.ConcurrencyValue) || UpdateCompiler.HasFlag(input, PropagatorFlags.ConcurrencyValue)))
                {
                    rowMustBeTouched = true;
                }
                if (!dictionary.ContainsKey(property) && (UpdateCompiler.HasFlag(memberValue, PropagatorFlags.ConcurrencyValue | PropagatorFlags.Key) || UpdateCompiler.HasFlag(input, PropagatorFlags.ConcurrencyValue | PropagatorFlags.Key)))
                {
                    dictionary.Add(property, memberValue);
                }
                ++ordinal;
            }
            DbExpression left = (DbExpression)null;

            foreach (KeyValuePair <EdmProperty, PropagatorResult> keyValuePair in dictionary)
            {
                DbExpression equalityExpression = this.GenerateEqualityExpression(target, keyValuePair.Key, keyValuePair.Value);
                left = left != null ? (DbExpression)left.And(equalityExpression) : equalityExpression;
            }
            return(left);
        }
            internal override FunctionUpdateCommand Translate(
                UpdateTranslator translator,
                ExtractedStateEntry stateEntry)
            {
                if (this.m_mapping == null)
                {
                    return((FunctionUpdateCommand)null);
                }
                bool flag = EntityState.Added == stateEntry.State;

                EntityUtil.ValidateNecessaryModificationFunctionMapping(flag ? this.m_mapping.InsertFunctionMapping : this.m_mapping.DeleteFunctionMapping, flag ? "Insert" : "Delete", stateEntry.Source, "AssociationSet", this.m_mapping.AssociationSet.Name);
                ModificationFunctionMapping functionMapping       = flag ? this.m_mapping.InsertFunctionMapping : this.m_mapping.DeleteFunctionMapping;
                FunctionUpdateCommand       functionUpdateCommand = new FunctionUpdateCommand(functionMapping, translator, new ReadOnlyCollection <IEntityStateEntry>((IList <IEntityStateEntry>)((IEnumerable <IEntityStateEntry>) new IEntityStateEntry[1]
                {
                    stateEntry.Source
                }).ToList <IEntityStateEntry>()), stateEntry);
                PropagatorResult propagatorResult = !flag ? stateEntry.Original : stateEntry.Current;

                foreach (ModificationFunctionParameterBinding parameterBinding in functionMapping.ParameterBindings)
                {
                    EdmProperty          member1     = (EdmProperty)parameterBinding.MemberPath.Members[0];
                    AssociationEndMember member2     = (AssociationEndMember)parameterBinding.MemberPath.Members[1];
                    PropagatorResult     memberValue = propagatorResult.GetMemberValue((EdmMember)member2).GetMemberValue((EdmMember)member1);
                    functionUpdateCommand.SetParameterValue(memberValue, parameterBinding, translator);
                }
                functionUpdateCommand.RegisterRowsAffectedParameter(functionMapping.RowsAffectedParameter);
                return(functionUpdateCommand);
            }
Beispiel #3
0
        internal override int CompareToType(UpdateCommand otherCommand)
        {
            DynamicUpdateCommand dynamicUpdateCommand = (DynamicUpdateCommand)otherCommand;
            int num1 = (int)(this.Operator - dynamicUpdateCommand.Operator);

            if (num1 != 0)
            {
                return(num1);
            }
            int num2 = StringComparer.Ordinal.Compare(this._processor.Table.Name, dynamicUpdateCommand._processor.Table.Name);

            if (num2 != 0)
            {
                return(num2);
            }
            int num3 = StringComparer.Ordinal.Compare(this._processor.Table.EntityContainer.Name, dynamicUpdateCommand._processor.Table.EntityContainer.Name);

            if (num3 != 0)
            {
                return(num3);
            }
            PropagatorResult propagatorResult1 = this.Operator == ModificationOperator.Delete ? this.OriginalValues : this.CurrentValues;
            PropagatorResult propagatorResult2 = dynamicUpdateCommand.Operator == ModificationOperator.Delete ? dynamicUpdateCommand.OriginalValues : dynamicUpdateCommand.CurrentValues;

            for (int index = 0; index < this._processor.KeyOrdinals.Length; ++index)
            {
                int    keyOrdinal   = this._processor.KeyOrdinals[index];
                object simpleValue1 = propagatorResult1.GetMemberValue(keyOrdinal).GetSimpleValue();
                object simpleValue2 = propagatorResult2.GetMemberValue(keyOrdinal).GetSimpleValue();
                num3 = ByValueComparer.Default.Compare(simpleValue1, simpleValue2);
                if (num3 != 0)
                {
                    return(num3);
                }
            }
            for (int index = 0; index < this._processor.KeyOrdinals.Length; ++index)
            {
                int keyOrdinal = this._processor.KeyOrdinals[index];
                num3 = propagatorResult1.GetMemberValue(keyOrdinal).Identifier - propagatorResult2.GetMemberValue(keyOrdinal).Identifier;
                if (num3 != 0)
                {
                    return(num3);
                }
            }
            return(num3);
        }
Beispiel #4
0
        /// <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)
        {
            var whereClauses = new Dictionary <EdmProperty, PropagatorResult>();

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

            foreach (var member in processor.Table.ElementType.Properties)
            {
                // members and result values are ordinally aligned
                var expectedValue = referenceRow.GetMemberValue(propertyOrdinal);
                var 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 (var clause in whereClauses)
            {
                var 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);
        }
Beispiel #5
0
 private PropagatorResult[] GetKeyConstants(PropagatorResult row)
 {
     PropagatorResult[] propagatorResultArray = new PropagatorResult[this.m_keyOrdinals.Length];
     for (int index = 0; index < this.m_keyOrdinals.Length; ++index)
     {
         PropagatorResult memberValue = row.GetMemberValue(this.m_keyOrdinals[index]);
         propagatorResultArray[index] = memberValue;
     }
     return(propagatorResultArray);
 }
        // Extracts key constants from the given row.
        private PropagatorResult[] GetKeyConstants(PropagatorResult row)
        {
            var keyConstants = new PropagatorResult[m_keyOrdinals.Length];

            for (var i = 0; i < m_keyOrdinals.Length; i++)
            {
                var constant = row.GetMemberValue(m_keyOrdinals[i]);

                keyConstants[i] = constant;
            }
            return(keyConstants);
        }
Beispiel #7
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;
                var keyValues     = new PropagatorResult[keyProperties.Count];
                var hasNullMember = false;

                for (var 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;
            }
            private ForeignKeyValue(
                ReferentialConstraint metadata,
                PropagatorResult record,
                bool isTarget,
                bool isInsert)
            {
                this.Metadata = metadata;
                IList <EdmProperty> edmPropertyList = isTarget ? (IList <EdmProperty>)metadata.FromProperties : (IList <EdmProperty>)metadata.ToProperties;

                PropagatorResult[] constants = new PropagatorResult[edmPropertyList.Count];
                bool flag = false;

                for (int index = 0; index < constants.Length; ++index)
                {
                    constants[index] = record.GetMemberValue((EdmMember)edmPropertyList[index]);
                    if (constants[index].IsNull)
                    {
                        flag = true;
                        break;
                    }
                }
                this.Key      = !flag ? new CompositeKey(constants) : (CompositeKey)null;
                this.IsInsert = isInsert;
            }
Beispiel #9
0
        /// <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)
        {
            var setClauses         = new Dictionary <EdmProperty, PropagatorResult>();
            var returningArguments = new List <KeyValuePair <string, DbExpression> >();

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

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

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

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

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

                var omitFromSetList = false;

                Debug.Assert(propertyResult.IsSimple);

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

                // check if this value should be omitted
                var 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
                var genPattern  = MetadataHelper.GetStoreGeneratedPattern(property);
                var isServerGen = genPattern == StoreGeneratedPattern.Computed ||
                                  (insertMode && genPattern == StoreGeneratedPattern.Identity);
                if (isServerGen)
                {
                    var propertyExpression = target.Variable.Property(property);
                    returningArguments.Add(new KeyValuePair <string, DbExpression>(property.Name, propertyExpression));

                    // check if this is a server generated identifier
                    var identifier = propertyResult.Identifier;
                    if (PropagatorResult.NullIdentifier != identifier)
                    {
                        if (m_translator.KeyManager.HasPrincipals(identifier))
                        {
                            throw new InvalidOperationException(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 new NotSupportedException(
                                      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");
                    var 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 new InvalidOperationException(
                                  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
            var result = new List <DbModificationClause>(setClauses.Count);

            foreach (var setClause in setClauses)
            {
                var property = setClause.Key;

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

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

                keyConstants[i] = constant;
            }
            return keyConstants;
        }
Beispiel #11
0
        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>  dictionary       = new Dictionary <EdmProperty, PropagatorResult>();
            List <KeyValuePair <string, DbExpression> > keyValuePairList = new List <KeyValuePair <string, DbExpression> >();

            outputIdentifiers = new Dictionary <int, string>();
            PropagatorFlags propagatorFlags1 = insertMode ? PropagatorFlags.NoFlags : PropagatorFlags.Preserve | PropagatorFlags.Unknown;

            for (int index1 = 0; index1 < processor.Table.ElementType.Properties.Count; ++index1)
            {
                EdmProperty      property = processor.Table.ElementType.Properties[index1];
                PropagatorResult result   = row.GetMemberValue(index1);
                if (-1 != result.Identifier)
                {
                    result = result.ReplicateResultWithNewValue(this.m_translator.KeyManager.GetPrincipalValue(result));
                }
                bool flag1 = false;
                bool flag2 = false;
                for (int index2 = 0; index2 < processor.KeyOrdinals.Length; ++index2)
                {
                    if (processor.KeyOrdinals[index2] == index1)
                    {
                        flag2 = true;
                        break;
                    }
                }
                PropagatorFlags propagatorFlags2 = PropagatorFlags.NoFlags;
                if (!insertMode && flag2)
                {
                    flag1 = true;
                }
                else
                {
                    propagatorFlags2 |= result.PropagatorFlags;
                }
                StoreGeneratedPattern generatedPattern = MetadataHelper.GetStoreGeneratedPattern((EdmMember)property);
                bool flag3 = generatedPattern == StoreGeneratedPattern.Computed || insertMode && generatedPattern == StoreGeneratedPattern.Identity;
                if (flag3)
                {
                    DbPropertyExpression propertyExpression = target.Variable.Property(property);
                    keyValuePairList.Add(new KeyValuePair <string, DbExpression>(property.Name, (DbExpression)propertyExpression));
                    int identifier = result.Identifier;
                    if (-1 != identifier)
                    {
                        if (this.m_translator.KeyManager.HasPrincipals(identifier))
                        {
                            throw new InvalidOperationException(Strings.Update_GeneratedDependent((object)property.Name));
                        }
                        outputIdentifiers.Add(identifier, property.Name);
                        if (generatedPattern != StoreGeneratedPattern.Identity && processor.IsKeyProperty(index1))
                        {
                            throw new NotSupportedException(Strings.Update_NotSupportedComputedKeyColumn((object)"StoreGeneratedPattern", (object)"Computed", (object)"Identity", (object)property.Name, (object)property.DeclaringType.FullName));
                        }
                    }
                }
                if ((propagatorFlags2 & propagatorFlags1) != PropagatorFlags.NoFlags)
                {
                    flag1 = true;
                }
                else if (flag3)
                {
                    flag1            = true;
                    rowMustBeTouched = true;
                }
                if (!flag1 && !insertMode && generatedPattern == StoreGeneratedPattern.Identity)
                {
                    PropagatorResult memberValue = originalRow.GetMemberValue(index1);
                    if (!ByValueEqualityComparer.Default.Equals(memberValue.GetSimpleValue(), result.GetSimpleValue()))
                    {
                        throw new InvalidOperationException(Strings.Update_ModifyingIdentityColumn((object)"Identity", (object)property.Name, (object)property.DeclaringType.FullName));
                    }
                    flag1 = true;
                }
                if (!flag1)
                {
                    dictionary.Add(property, result);
                }
            }
            returning = 0 >= keyValuePairList.Count ? (DbExpression)null : (DbExpression)DbExpressionBuilder.NewRow((IEnumerable <KeyValuePair <string, DbExpression> >)keyValuePairList);
            List <DbModificationClause> modificationClauseList = new List <DbModificationClause>(dictionary.Count);

            foreach (KeyValuePair <EdmProperty, PropagatorResult> keyValuePair in dictionary)
            {
                EdmProperty key = keyValuePair.Key;
                modificationClauseList.Add((DbModificationClause) new DbSetClause(UpdateCompiler.GeneratePropertyExpression(target, keyValuePair.Key), this.GenerateValueExpression(keyValuePair.Key, keyValuePair.Value)));
            }
            return((IEnumerable <DbModificationClause>)modificationClauseList);
        }
        /// <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)
        {
            var whereClauses = new Dictionary<EdmProperty, PropagatorResult>();

            // add all concurrency tokens (note that keys are always concurrency tokens as well)
            var propertyOrdinal = 0;
            foreach (var member in processor.Table.ElementType.Properties)
            {
                // members and result values are ordinally aligned
                var expectedValue = referenceRow.GetMemberValue(propertyOrdinal);
                var 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 (var clause in whereClauses)
            {
                var 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)
        {
            var setClauses = new Dictionary<EdmProperty, PropagatorResult>();
            var returningArguments = new List<KeyValuePair<string, DbExpression>>();
            outputIdentifiers = new Dictionary<int, string>();

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

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

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

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

                var omitFromSetList = false;

                Debug.Assert(propertyResult.IsSimple);

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

                // check if this value should be omitted
                var 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
                var genPattern = MetadataHelper.GetStoreGeneratedPattern(property);
                var isServerGen = genPattern == StoreGeneratedPattern.Computed ||
                                  (insertMode && genPattern == StoreGeneratedPattern.Identity);
                if (isServerGen)
                {
                    var propertyExpression = target.Variable.Property(property);
                    returningArguments.Add(new KeyValuePair<string, DbExpression>(property.Name, propertyExpression));

                    // check if this is a server generated identifier
                    var identifier = propertyResult.Identifier;
                    if (PropagatorResult.NullIdentifier != identifier)
                    {
                        if (m_translator.KeyManager.HasPrincipals(identifier))
                        {
                            throw new InvalidOperationException(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 new NotSupportedException(
                                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");
                    var 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 new InvalidOperationException(
                            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
            var result = new List<DbModificationClause>(setClauses.Count);
            foreach (var setClause in setClauses)
            {
                var property = setClause.Key;

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

            return result;
        }