/// <summary>
        /// Builds the list of submit operations from the current <see cref="EntityChangeSet"/>.
        /// </summary>
        /// <param name="changeSet">The <see cref="EntityChangeSet"/> to process.</param>
        /// <returns>The list of <see cref="ChangeSetEntry"/> for the specified <see cref="EntityChangeSet"/>.</returns>
        private static List<ChangeSetEntry> BuildOperations(EntityChangeSet changeSet)
        {
            List<ChangeSetEntry> operations = new List<ChangeSetEntry>();
            int clientID = 0;
            EntityOperationType operationType = EntityOperationType.None;
            foreach (Entity entity in changeSet)
            {
                switch (entity.EntityState)
                {
                    case EntityState.New:
                        operationType = EntityOperationType.Insert;
                        break;
                    case EntityState.Modified:
                        operationType = EntityOperationType.Update;
                        break;
                    case EntityState.Deleted:
                        operationType = EntityOperationType.Delete;
                        break;
                    default:
                        continue;
                }

                // create the operation and apply any original values
                ChangeSetEntry changeSetEntry = new ChangeSetEntry(entity, clientID++, operationType);
                if (entity.OriginalValues != null)
                {
                    if (entity.MetaType.ShouldRoundtripOriginal && entity.OriginalValues != null)
                    {
                        changeSetEntry.OriginalEntity = GetRoundtripEntity(entity);
                    }
                    else
                    {
                        // In cases where the entity is modified but we're not sending
                        // an original we need to flag the entity as having changes.
                        // For example, this happens in Timestamp scenarios.
                        changeSetEntry.HasMemberChanges = true;
                    }
                }

                // add any custom method invocations
                if (entity.CustomMethodInvocation != null)
                {
                    if (string.IsNullOrEmpty(entity.CustomMethodInvocation.Name))
                    {
                        throw new ArgumentException(Resource.DomainClient_InvocationNameCannotBeNullOrEmpty);
                    }

                    if (changeSetEntry.EntityActions == null)
                    {
                        changeSetEntry.EntityActions = new Dictionary<string, object[]>();
                    }
                    changeSetEntry.EntityActions.Add(entity.CustomMethodInvocation.Name, entity.CustomMethodInvocation.Parameters.ToArray());
                }

                operations.Add(changeSetEntry);
            }

            return operations;
        }
 /// <summary>
 /// Build and set the association maps for all operations in the specified changeset
 /// </summary>
 private void Build()
 {
     foreach (var entityGroup in this._changeSetEntries.GroupBy(p => p.Entity.GetType()))
     {
         foreach (ChangeSetEntry changeSetEntry in entityGroup)
         {
             this._currentChangeSetEntry = changeSetEntry;
             this.Visit(changeSetEntry.Entity);
         }
     }
 }
            public override void Visit(Entity entity)
            {
                if (this._visited.ContainsKey(entity))
                {
                    return;
                }

                // if the entity is unmodified, add an ChangeSetEntry for it
                if (this._isChild && entity.EntityState == EntityState.Unmodified)
                {
                    ChangeSetEntry op = new ChangeSetEntry(entity, this._id++, EntityOperationType.None);
                    this._changeSetEntries.Add(op);
                }

                this._visited.Add(entity, true);

                base.Visit(entity);
            }
        /// <summary>
        /// Builds the list of submit operations from the current <see cref="EntityChangeSet"/>.
        /// </summary>
        /// <param name="changeSet">The <see cref="EntityChangeSet"/> to process.</param>
        /// <returns>The list of <see cref="ChangeSetEntry"/> for the specified <see cref="EntityChangeSet"/>.</returns>
        private static List <ChangeSetEntry> BuildOperations(EntityChangeSet changeSet)
        {
            List <ChangeSetEntry> operations = new List <ChangeSetEntry>();
            int clientID = 0;
            EntityOperationType operationType = EntityOperationType.None;

            foreach (Entity entity in changeSet)
            {
                switch (entity.EntityState)
                {
                case EntityState.New:
                    operationType = EntityOperationType.Insert;
                    break;

                case EntityState.Modified:
                    operationType = EntityOperationType.Update;
                    break;

                case EntityState.Deleted:
                    operationType = EntityOperationType.Delete;
                    break;

                default:
                    continue;
                }

                // create the operation and apply any original values
                ChangeSetEntry changeSetEntry = new ChangeSetEntry(entity, clientID++, operationType);

                if (entity.OriginalValues != null)
                {
                    if (entity.MetaType.ShouldRoundtripOriginal && entity.OriginalValues != null)
                    {
                        changeSetEntry.OriginalEntity = GetRoundtripEntity(entity);
                    }
                    else
                    {
                        // In cases where the entity is modified but we're not sending
                        // an original we need to flag the entity as having changes.
                        // For example, this happens in Timestamp scenarios.
                        changeSetEntry.HasMemberChanges = true;
                    }
                }

                // add any custom method invocations
                var entityActions = (ICollection <EntityAction>)entity.EntityActions;
                foreach (EntityAction customInvokation in entityActions)
                {
                    if (string.IsNullOrEmpty(customInvokation.Name))
                    {
                        throw new ArgumentException(Resource.DomainClient_InvocationNameCannotBeNullOrEmpty);
                    }

                    if (changeSetEntry.EntityActions == null)
                    {
                        changeSetEntry.EntityActions = new List <Serialization.KeyValue <string, object[]> >();
                    }
                    changeSetEntry.EntityActions.Add(
                        new Serialization.KeyValue <string, object[]>(customInvokation.Name, customInvokation.Parameters.ToArray()));
                }

                operations.Add(changeSetEntry);
            }

            return(operations);
        }
            protected override void VisitEntityRef(IEntityRef entityRef, Entity parent, MetaMember member)
            {
                // Check for [ExternalReference] properties, if found we can skip visiting these
                // external entities so they will not be included in our change set.
                if (member.IsExternalReference)
                {
                    return;
                }

                // We don't want to cause any deferred loading of the EntityRef in non-compositional
                // cases. Note that the UnmodifiedOperationAdder has already caused compositional
                // associations to load, so they will have values.
                Entity referenced = null;

                if (entityRef != null && entityRef.HasValue)
                {
                    referenced = entityRef.Entity;
                }

                // Now determine the originally referenced entity if this association is a composition
                // and the child has been removed
                Entity prevReferenced = null;
                bool   isComposition  = member.IsComposition;

                if (isComposition && parent.EntityState != EntityState.New)
                {
                    ChangeSetEntry entry = this.FindOriginalChildren(member.AssociationAttribute).SingleOrDefault();
                    if (entry != null)
                    {
                        prevReferenced = entry.Entity;
                    }
                }

                if (isComposition && prevReferenced == null)
                {
                    // if this is an unmodified composition, set the previously referenced entity
                    // to the currently referenced entity
                    prevReferenced = referenced;
                }

                // If the referenced entity is New and the parent is not Deleted or the referenced entity is a composed child and the target
                // is part of the changeset, set the association
                int  refId = -1;
                bool shouldIncludeNewAssociation = referenced != null && (this._currentChangeSetEntry.Entity.EntityState != EntityState.Deleted && referenced.EntityState == EntityState.New);

                if (referenced != null && (shouldIncludeNewAssociation || isComposition) && this._entityIdMap.TryGetValue(referenced, out refId))
                {
                    // set the current reference
                    Dictionary <string, int[]> associatedEntities = (Dictionary <string, int[]>) this._currentChangeSetEntry.Associations;
                    if (associatedEntities == null)
                    {
                        associatedEntities = new Dictionary <string, int[]>();
                        this._currentChangeSetEntry.Associations = associatedEntities;
                    }
                    associatedEntities.Add(member.Name, new int[] { refId });
                }

                // If the association is a composition, set the original reference
                if (prevReferenced != null && isComposition && this._entityIdMap.TryGetValue(prevReferenced, out refId))
                {
                    Dictionary <string, int[]> associatedEntities = (Dictionary <string, int[]>) this._currentChangeSetEntry.OriginalAssociations;
                    if (associatedEntities == null)
                    {
                        associatedEntities = new Dictionary <string, int[]>();
                        this._currentChangeSetEntry.OriginalAssociations = associatedEntities;
                    }
                    associatedEntities.Add(member.Name, new int[] { refId });
                }
            }
            public override void Visit(Entity entity)
            {
                if (this._visited.ContainsKey(entity))
                {
                    return;
                }

                // if the entity is unmodified, add an ChangeSetEntry for it
                if (this._isChild && entity.EntityState == EntityState.Unmodified)
                {
                    ChangeSetEntry op = new ChangeSetEntry(entity, this._id++, EntityOperationType.None);
                    this._changeSetEntries.Add(op);
                }

                this._visited.Add(entity, true);

                base.Visit(entity);
            }
 /// <summary>
 /// Build and set the association maps for all operations in the specified changeset
 /// </summary>
 private void Build()
 {
     foreach (var entityGroup in this._changeSetEntries.GroupBy(p => p.Entity.GetType()))
     {
         foreach (ChangeSetEntry changeSetEntry in entityGroup)
         {
             this._currentChangeSetEntry = changeSetEntry;
             this.Visit(changeSetEntry.Entity);
         }
     }
 }