internal override FunctionUpdateCommand Translate(
                UpdateTranslator translator,
                ExtractedStateEntry stateEntry)
            {
                ModificationFunctionMapping functionMapping = this.GetFunctionMapping(stateEntry).Item2;
                EntityKey entityKey = stateEntry.Source.EntityKey;
                HashSet <IEntityStateEntry> entityStateEntrySet = new HashSet <IEntityStateEntry>()
                {
                    stateEntry.Source
                };
                IEnumerable <Tuple <AssociationEndMember, IEntityStateEntry> > tuples      = functionMapping.CollocatedAssociationSetEnds.Join <AssociationSetEnd, IEntityStateEntry, StructuralType, Tuple <AssociationEndMember, IEntityStateEntry> >(translator.GetRelationships(entityKey), (Func <AssociationSetEnd, StructuralType>)(end => end.CorrespondingAssociationEndMember.DeclaringType), (Func <IEntityStateEntry, StructuralType>)(candidateEntry => (StructuralType)candidateEntry.EntitySet.ElementType), (Func <AssociationSetEnd, IEntityStateEntry, Tuple <AssociationEndMember, IEntityStateEntry> >)((end, candidateEntry) => Tuple.Create <AssociationEndMember, IEntityStateEntry>(end.CorrespondingAssociationEndMember, candidateEntry)));
                Dictionary <AssociationEndMember, IEntityStateEntry>           dictionary1 = new Dictionary <AssociationEndMember, IEntityStateEntry>();
                Dictionary <AssociationEndMember, IEntityStateEntry>           dictionary2 = new Dictionary <AssociationEndMember, IEntityStateEntry>();

                foreach (Tuple <AssociationEndMember, IEntityStateEntry> tuple in tuples)
                {
                    ModificationFunctionMappingTranslator.EntitySetTranslator.ProcessReferenceCandidate(entityKey, entityStateEntrySet, dictionary1, dictionary2, tuple.Item1, tuple.Item2);
                }
                FunctionUpdateCommand command;

                if (entityStateEntrySet.All <IEntityStateEntry>((Func <IEntityStateEntry, bool>)(e => e.State == EntityState.Unchanged)))
                {
                    command = (FunctionUpdateCommand)null;
                }
                else
                {
                    command = new FunctionUpdateCommand(functionMapping, translator, new ReadOnlyCollection <IEntityStateEntry>((IList <IEntityStateEntry>)entityStateEntrySet.ToList <IEntityStateEntry>()), stateEntry);
                    ModificationFunctionMappingTranslator.EntitySetTranslator.BindFunctionParameters(translator, stateEntry, functionMapping, command, dictionary1, dictionary2);
                    if (functionMapping.ResultBindings != null)
                    {
                        foreach (ModificationFunctionResultBinding resultBinding in functionMapping.ResultBindings)
                        {
                            PropagatorResult memberValue = stateEntry.Current.GetMemberValue((EdmMember)resultBinding.Property);
                            command.AddResultColumn(translator, resultBinding.ColumnName, memberValue);
                        }
                    }
                }
                return(command);
            }
            internal override FunctionUpdateCommand Translate(
                UpdateTranslator translator,
                ExtractedStateEntry stateEntry)
            {
                var mapping         = GetFunctionMapping(stateEntry);
                var functionMapping = mapping.Item2;
                var entityKey       = stateEntry.Source.EntityKey;

                var stateEntries = new HashSet <IEntityStateEntry>
                {
                    stateEntry.Source
                };

                // gather all referenced association ends
                var collocatedEntries =
                    // find all related entries corresponding to collocated association types
                    from end in functionMapping.CollocatedAssociationSetEnds
                    join candidateEntry in translator.GetRelationships(entityKey)
                    on end.CorrespondingAssociationEndMember.DeclaringType equals candidateEntry.EntitySet.ElementType
                    select Tuple.Create(end.CorrespondingAssociationEndMember, candidateEntry);

                var currentReferenceEnds  = new Dictionary <AssociationEndMember, IEntityStateEntry>();
                var originalReferenceEnds = new Dictionary <AssociationEndMember, IEntityStateEntry>();

                foreach (var candidate in collocatedEntries)
                {
                    ProcessReferenceCandidate(
                        entityKey, stateEntries, currentReferenceEnds, originalReferenceEnds, candidate.Item1, candidate.Item2);
                }

                // create function object
                FunctionUpdateCommand command;

                // consider the following scenario, we need to loop through all the state entries that is correlated with entity2 and make sure it is not changed.
                // entity1 <-- Independent Association <-- entity2 <-- Fk association <-- entity 3
                //                                           |
                //              entity4 <-- Fk association <--
                if (stateEntries.All(e => e.State == EntityState.Unchanged))
                {
                    // we shouldn't update the entity if it is unchanged, only update when referenced association is changed.
                    // if not, then this will trigger a fake update for principal
                    command = null;
                }
                else
                {
                    command = new FunctionUpdateCommand(functionMapping, translator, new ReadOnlyCollection <IEntityStateEntry>(stateEntries.ToList()), stateEntry);

                    // bind all function parameters
                    BindFunctionParameters(translator, stateEntry, functionMapping, command, currentReferenceEnds, originalReferenceEnds);

                    // interpret all result bindings
                    if (null != functionMapping.ResultBindings)
                    {
                        foreach (var resultBinding in functionMapping.ResultBindings)
                        {
                            var result = stateEntry.Current.GetMemberValue(resultBinding.Property);
                            command.AddResultColumn(translator, resultBinding.ColumnName, result);
                        }
                    }
                }

                return(command);
            }
            internal override FunctionUpdateCommand Translate(
                UpdateTranslator translator,
                ExtractedStateEntry stateEntry)
            {
                var mapping = GetFunctionMapping(stateEntry);
                var functionMapping = mapping.Item2;
                var entityKey = stateEntry.Source.EntityKey;

                var stateEntries = new HashSet<IEntityStateEntry>
                    {
                        stateEntry.Source
                    };

                // gather all referenced association ends
                var collocatedEntries =
                    // find all related entries corresponding to collocated association types
                    from end in functionMapping.CollocatedAssociationSetEnds
                    join candidateEntry in translator.GetRelationships(entityKey)
                        on end.CorrespondingAssociationEndMember.DeclaringType equals candidateEntry.EntitySet.ElementType
                    select Tuple.Create(end.CorrespondingAssociationEndMember, candidateEntry);

                var currentReferenceEnds = new Dictionary<AssociationEndMember, IEntityStateEntry>();
                var originalReferenceEnds = new Dictionary<AssociationEndMember, IEntityStateEntry>();

                foreach (var candidate in collocatedEntries)
                {
                    ProcessReferenceCandidate(
                        entityKey, stateEntries, currentReferenceEnds, originalReferenceEnds, candidate.Item1, candidate.Item2);
                }

                // create function object
                FunctionUpdateCommand command;

                // consider the following scenario, we need to loop through all the state entries that is correlated with entity2 and make sure it is not changed.
                // entity1 <-- Independent Association <-- entity2 <-- Fk association <-- entity 3
                //                                           |
                //              entity4 <-- Fk association <--
                if (stateEntries.All(e => e.State == EntityState.Unchanged))
                {
                    // we shouldn't update the entity if it is unchanged, only update when referenced association is changed.
                    // if not, then this will trigger a fake update for principal
                    command = null;
                }
                else
                {
                    command = new FunctionUpdateCommand(functionMapping, translator, new ReadOnlyCollection<IEntityStateEntry>(stateEntries.ToList()), stateEntry);

                    // bind all function parameters
                    BindFunctionParameters(translator, stateEntry, functionMapping, command, currentReferenceEnds, originalReferenceEnds);

                    // interpret all result bindings
                    if (null != functionMapping.ResultBindings)
                    {
                        foreach (var resultBinding in functionMapping.ResultBindings)
                        {
                            var result = stateEntry.Current.GetMemberValue(resultBinding.Property);
                            command.AddResultColumn(translator, resultBinding.ColumnName, result);
                        }
                    }
                }

                return command;
            }