internal EntityDescriptor(string identity, Uri selfLink, Uri editLink, object entity, EntityDescriptor parentEntity, string parentProperty, string entitySetName, string etag, EntityStates state)
            : base(state)
        {
            Debug.Assert(entity != null, "entity is null");
            Debug.Assert((parentEntity == null && parentProperty == null) || (parentEntity != null && parentProperty != null), "When parentEntity is specified, must also specify parentProperyName");

            #if DEBUG
            if (state == EntityStates.Added)
            {
                Debug.Assert(identity == null && selfLink == null && editLink == null && etag == null, "For objects in added state, identity, self-link, edit-link and etag must be null");
                Debug.Assert(
                             (!string.IsNullOrEmpty(entitySetName) && parentEntity == null && string.IsNullOrEmpty(parentProperty)) ||
                             (string.IsNullOrEmpty(entitySetName) && parentEntity != null && !string.IsNullOrEmpty(parentProperty)),
                             "For entities in added state, entity set name or the insert path must be specified");
            }
            else
            {
                Debug.Assert(identity != null, "For objects in non-added state, identity must never be null");
                Debug.Assert(string.IsNullOrEmpty(entitySetName) && string.IsNullOrEmpty(parentProperty) && parentEntity == null, "For non-added entities, the entity set name and the insert path must be null");
            }
            #endif

            this.identity = identity;
            this.selfLink = selfLink;
            this.editLink = editLink;

            this.parentDescriptor = parentEntity;
            this.parentProperty = parentProperty;
            this.entity = entity;
            this.etag = etag;
            this.entitySetName = entitySetName;
        }
 internal void RestoreParentState(EntityDescriptor parentDescriptor, string parentProperty)
 {
     this.parentDescriptor = parentDescriptor;
     this.parentProperty = parentProperty;
 }
        internal void ApplyToContext()
        {
            Debug.Assert(
                this.mergeOption != MergeOption.OverwriteChanges || this.foundEntriesWithMedia.Count == 0,
                "mergeOption != MergeOption.OverwriteChanges || foundEntriesWithMedia.Count == 0 - we only use the 'entries-with-media' lookaside when we're not in overwrite mode, otherwise we track everything through identity stack");

            if (!this.Tracking)
            {
                return;
            }

            foreach (KeyValuePair<string, AtomEntry> entity in this.identityStack)
            {
                AtomEntry entry = entity.Value;
                if (entry.CreatedByMaterializer ||
                    entry.ResolvedObject == this.insertRefreshObject ||
                    entry.ShouldUpdateFromPayload)
                {
                    EntityDescriptor descriptor = new EntityDescriptor(entity.Key, entry.QueryLink, entry.EditLink, entry.ResolvedObject, null, null, null, entry.ETagText, EntityStates.Unchanged);
                    descriptor = this.context.InternalAttachEntityDescriptor(descriptor, false);

                    descriptor.State = EntityStates.Unchanged;

                    this.ApplyMediaEntryInformation(entry, descriptor);
                    descriptor.ServerTypeName = entry.TypeName;
                }
                else
                {
                    EntityStates state;
                    this.context.TryGetEntity(entity.Key, entry.ETagText, this.mergeOption, out state);
                }
            }

            foreach (AtomEntry entry in this.foundEntriesWithMedia.Values)
            {
                Debug.Assert(entry.ResolvedObject != null, "entry.ResolvedObject != null -- otherwise it wasn't found");
                EntityDescriptor descriptor = this.context.GetEntityDescriptor(entry.ResolvedObject);
                this.ApplyMediaEntryInformation(entry, descriptor);
            }

            foreach (LinkDescriptor link in this.links)
            {
                if (EntityStates.Added == link.State)
                {
                    if ((EntityStates.Deleted == this.context.GetEntityDescriptor(link.Target).State) ||
                        (EntityStates.Deleted == this.context.GetEntityDescriptor(link.Source).State))
                    {
                        this.context.DeleteLink(link.Source, link.SourceProperty, link.Target);
                    }
                    else
                    {
                        this.context.AttachLink(link.Source, link.SourceProperty, link.Target, this.mergeOption);
                    }
                }
                else if (EntityStates.Modified == link.State)
                {
                    object target = link.Target;
                    if (MergeOption.PreserveChanges == this.mergeOption)
                    {
                        LinkDescriptor end = this.context.GetLinks(link.Source, link.SourceProperty).FirstOrDefault();
                        if (null != end && null == end.Target)
                        {
                            continue;
                        }

                        if ((null != target && EntityStates.Deleted == this.context.GetEntityDescriptor(target).State) ||
                            EntityStates.Deleted == this.context.GetEntityDescriptor(link.Source).State)
                        {
                            target = null;
                        }
                    }

                    this.context.AttachLink(link.Source, link.SourceProperty, target, this.mergeOption);
                }
                else
                {
                    Debug.Assert(EntityStates.Detached == link.State, "not detached link");
                    this.context.DetachLink(link.Source, link.SourceProperty, link.Target);
                }
            }
        }
        internal static EntityDescriptor RestoreState(EntityDescriptorState state)
        {
            SaveStreamState saveStreamState = state.SaveStream;
            DataServiceContext.DataServiceSaveStream saveStream = (saveStreamState != null)
                ? DataServiceContext.DataServiceSaveStream.RestoreState(saveStreamState)
                : null;

            var entityDescriptor = new EntityDescriptor(
                state.Identity,
                state.SelfLink,
                state.EditLink,
                state.Entity,
                null,
                null,
                state.EntitySetName,
                state.Etag,
                state.State)
            {
                editMediaLink = state.EditMediaLink,
                readStreamLink = state.ReadStreamLink,
                saveStream = saveStream,
                selfLink = state.SelfLink,
                serverTypeName = state.ServerTypeName,
                streamETag = state.StreamETag,
                streamState = state.StreamState,
            };

            entityDescriptor.RestoreState((DescriptorState)state);

            return entityDescriptor;
        }
        private void ApplyMediaEntryInformation(AtomEntry entry, EntityDescriptor descriptor)
        {
            Debug.Assert(entry != null, "entry != null");
            Debug.Assert(descriptor != null, "descriptor != null");

            if (entry.MediaEditUri != null || entry.MediaContentUri != null)
            {
                if (entry.MediaEditUri != null)
                {
                    descriptor.EditStreamUri = new Uri(this.context.BaseUriWithSlash, entry.MediaEditUri);
                }

                if (entry.MediaContentUri != null)
                {
                    descriptor.ReadStreamUri = new Uri(this.context.BaseUriWithSlash, entry.MediaContentUri);
                }

                descriptor.StreamETag = entry.StreamETagText;
            }
        }