src/Shared/EntityFramework/Core/Mapping/Update/Internal/UpdateCompiler.cs
// <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>
Determines column/value used to set values for a row.
Determines column / value used to set values for a row .
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>();
            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];
                var propertyResult = row.GetMemberValue(propertyOrdinal);
                if (PropagatorResult.NullIdentifier
                    != propertyResult.Identifier)
                {
                    propertyResult = propertyResult.ReplicateResultWithNewValue(
                        m_translator.KeyManager.GetPrincipalValue(propertyResult));
                }
                var omitFromSetList = false;
                Debug.Assert(propertyResult.IsSimple);
                var isKey = false;
                for (var i = 0; i < processor.KeyOrdinals.Length; i++)
                {
                    if (processor.KeyOrdinals[i] == propertyOrdinal)
                    {
                        isKey = true;
                        break;
                    }
                }
                var flags = PropagatorFlags.NoFlags;
                if (!insertMode && isKey)
                {
                    omitFromSetList = true;
                }
                else
                {
                    flags |= propertyResult.PropagatorFlags;
                }
                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));
                    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 (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)))
                {
                    omitFromSetList = true;
                }
                else if (isServerGen)
                {
                    omitFromSetList = true;
                    rowMustBeTouched = true;
                }
                if (!omitFromSetList
                    && !insertMode
                    && genPattern == StoreGeneratedPattern.Identity)
                {
                    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);
                }
            }
            if (0 < returningArguments.Count)
            {
                returning = DbExpressionBuilder.NewRow(returningArguments);
            }
            else
            {
                returning = null;
            }
            var result = new List<DbModificationClause>(setClauses.Count);
            foreach (var setClause in setClauses)
            {
                result.Add(
                    new DbSetClause(
                        GeneratePropertyExpression(target, setClause.Key),
                        GenerateValueExpression(setClause.Key, setClause.Value)));
            }
            return result;
        }
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 > ( ) ; 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 ] ; var propertyResult = row . GetMemberValue ( propertyOrdinal ) ; if ( PropagatorResult . NullIdentifier != propertyResult . Identifier ) { propertyResult = propertyResult . ReplicateResultWithNewValue ( m_translator . KeyManager . GetPrincipalValue ( propertyResult ) ) ; } var omitFromSetList = false ; Debug . Assert ( propertyResult . IsSimple ) ; var isKey = false ; for ( var i = 0 ; i < processor . KeyOrdinals . Length ; i ++ ) { if ( processor . KeyOrdinals [ i ] == propertyOrdinal ) { isKey = true ; break ; } } var flags = PropagatorFlags . NoFlags ; if ( ! insertMode && isKey ) { omitFromSetList = true ; } else { flags |= propertyResult . PropagatorFlags ; } 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 ) ) ; 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 ( 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 ) ) ) { omitFromSetList = true ; } else if ( isServerGen ) { omitFromSetList = true ; rowMustBeTouched = true ; } if ( ! omitFromSetList && ! insertMode && genPattern == StoreGeneratedPattern . Identity ) { Debug . Assert ( originalRow != null , " " ) ; var originalPropertyResult = originalRow . GetMemberValue ( propertyOrdinal ) ; Debug . Assert ( originalPropertyResult . IsSimple , " " ) ; Debug . Assert ( propertyResult . IsSimple , " " ) ; 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 ) ; } } if ( 0 < returningArguments . Count ) { returning = DbExpressionBuilder . NewRow ( returningArguments ) ; } else { returning = null ; } var result = new List < DbModificationClause > ( setClauses . Count ) ; foreach ( var setClause in setClauses ) { result . Add ( new DbSetClause ( GeneratePropertyExpression ( target , setClause . Key ) , GenerateValueExpression ( setClause . Key , setClause . Value ) ) ) ; } return result ; }
Determines column/value used to set values for a row.
Determines column / value used to set values for a row .
// Determine which flags indicate a property should be omitted from the set list. // Type members and result values are ordinally aligned // retrieve principal value // Determine if this is a key value // check if this value should be omitted // Keys are only set for inserts // 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) // Determine if this value is server-generated // check if this is a server generated identifier // 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. // column value matches "omit" pattern, therefore should not be set // column value does not match "omit" pattern, but it is server generated // so it cannot be set // if the row has a modified value overridden by server gen, // it must still be touched in order to retrieve the value // make the user is not updating an identity value //throw the error only if the value actually changed // Construct returning projection // Construct clauses corresponding to the set clauses
Column value pairs.
Column value pairs .
target
DbExpressionBinding
Expression binding representing the table.
Expression binding representing the table .
row
PropagatorResult
Row containing values to set.
Row containing values to set .
originalRow
PropagatorResult
processor
TableChangeProcessor
Context for table.
Context for table .
insertMode
bool
Determines whether key columns and 'preserve' columns are omitted from the list.
Determines whether key columns and ' preserve ' columns are omitted from the list .
Dictionary<int, string>
out
DbExpression
out
bool
ref
outputIdentifiers
Dictionary listing server generated identifiers.
Dictionary listing server generated identifiers .
returning
DbExpression describing result projection for server generated values.
DbExpression describing result projection for server generated values .
rowMustBeTouched
Indicates whether the row must be touched because it produces a value
Indicates whether the row must be touched because it produces a value
remarks
The following columns are not included in the result.

Keys in non-insert operations (keys are only set for inserts).Values flagged 'preserve' (these are values the propagator claims are untouched).Server generated values.
The following columns are not included in the result . Keys in non - insert operations ( keys are only set for inserts ) . Values flagged ' preserve ' ( these are values the propagator claims are untouched ) . Server generated values .