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); }
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); }
/// <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); }
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); }
// <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; }
/// <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; }
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; }