Example #1
0
        /// <summary>
        /// Tracks the DeleteLink method.
        /// </summary>
        /// <param name="data">The data service context data on which to apply state transition.</param>
        /// <param name="source">The source.</param>
        /// <param name="sourcePropertyName">Name of the source property.</param>
        /// <param name="target">The target.</param>
        public static void TrackDeleteLink(this DataServiceContextData data, object source, string sourcePropertyName, object target)
        {
            EntityDescriptorData sourceDescriptorData = GetTrackedEntityDescriptorData(data, source, "Cannot delete link:", "source");

            EntityDescriptorData targetDescriptorData = GetTrackedEntityDescriptorData(data, target, "Cannot delete link:", "target");

            LinkDescriptorData descriptorData;

            if (data.TryGetLinkDescriptorData(sourceDescriptorData, sourcePropertyName, targetDescriptorData, out descriptorData) &&
                descriptorData.State == EntityStates.Added)
            {
                data.RemoveDescriptorData(descriptorData);
            }
            else
            {
                CheckStateIsNot(EntityStates.Added, sourceDescriptorData, "Cannot delete link:", "source");
                CheckStateIsNot(EntityStates.Added, targetDescriptorData, "Cannot delete link:", "target");

                if (descriptorData == null)
                {
                    data.CreateLinkDescriptorData(EntityStates.Deleted, data.GetNextChangeOrder(), sourceDescriptorData, sourcePropertyName, targetDescriptorData);
                }
                else if (descriptorData.State != EntityStates.Deleted)
                {
                    data.ChangeStateAndChangeOrder(descriptorData, EntityStates.Deleted, data.GetNextChangeOrder());
                }
            }
        }
Example #2
0
        /// <summary>
        /// Tracks the AttachLink method.
        /// </summary>
        /// <param name="data">The data service context data on which to apply state transition.</param>
        /// <param name="source">The source.</param>
        /// <param name="sourcePropertyName">Name of the source property.</param>
        /// <param name="target">The target.</param>
        public static void TrackAttachLink(this DataServiceContextData data, object source, string sourcePropertyName, object target)
        {
            ExceptionUtilities.CheckArgumentNotNull(data, "data");

            LinkDescriptorData linkDescriptorData;

            if (data.TryGetLinkDescriptorData(source, sourcePropertyName, target, out linkDescriptorData))
            {
                throw new TaupoInvalidOperationException(
                          string.Format(CultureInfo.InvariantCulture, "The link already exists: {0}.", linkDescriptorData.ToString()));
            }

            EntityDescriptorData sourceDescriptorData = GetTrackedEntityDescriptorData(data, source, "Cannot attach link:", "source");

            CheckStateIsNot(EntityStates.Deleted, sourceDescriptorData, "Cannot attach link:", "source");
            CheckStateIsNot(EntityStates.Added, sourceDescriptorData, "Cannot attach link:", "source");

            EntityDescriptorData targetDescriptorData = null;

            if (target != null)
            {
                targetDescriptorData = GetTrackedEntityDescriptorData(data, target, "Cannot attach link:", "target");
                CheckStateIsNot(EntityStates.Deleted, targetDescriptorData, "Cannot attach link:", "target");
                CheckStateIsNot(EntityStates.Added, targetDescriptorData, "Cannot attach link:", "target");
            }

            data.CreateLinkDescriptorData(EntityStates.Unchanged, data.GetNextChangeOrder(), sourceDescriptorData, sourcePropertyName, targetDescriptorData);
        }
        internal static Uri GetEntityInsertUri(DataServiceContextData contextData, EntityDescriptorData entityDescriptorData)
        {
            Uri insertUri;

            if (entityDescriptorData.InsertLink != null)
            {
                insertUri = entityDescriptorData.InsertLink;
            }
            else
            {
                ExceptionUtilities.CheckObjectNotNull(entityDescriptorData.ParentForInsert, "Entity descriptor data did not have insert link or parent for insert: {0}", entityDescriptorData);
                ExceptionUtilities.CheckObjectNotNull(entityDescriptorData.ParentPropertyForInsert, "Entity descriptor data did not have insert link or parent property for insert: {0}", entityDescriptorData);

                var parentDescriptor = contextData.GetEntityDescriptorData(entityDescriptorData.ParentForInsert);
                var linkInfo         = parentDescriptor.LinkInfos.SingleOrDefault(l => l.Name == entityDescriptorData.ParentPropertyForInsert);

                if (linkInfo != null && linkInfo.NavigationLink != null)
                {
                    insertUri = linkInfo.NavigationLink;
                }
                else
                {
                    insertUri = new Uri(UriHelpers.ConcatenateUriSegments(parentDescriptor.EditLink.OriginalString, entityDescriptorData.ParentPropertyForInsert), UriKind.RelativeOrAbsolute);
                    if (!insertUri.IsAbsoluteUri && contextData.BaseUri != null)
                    {
                        insertUri = new Uri(contextData.BaseUri, insertUri);
                    }
                }
            }

            return(insertUri);
        }
Example #4
0
        /// <summary>
        /// Calculates the DataServiceVersion for a particular EntityDescriptor
        /// </summary>
        /// <param name="entityDescriptorData">Entity Descriptor Data</param>
        /// <param name="maxProtocolVersion">The client's max protocol version</param>
        /// <returns>A Data service protocol version</returns>
        public DataServiceProtocolVersion CalculateDataServiceVersion(EntityDescriptorData entityDescriptorData, DataServiceProtocolVersion maxProtocolVersion)
        {
            ExceptionUtilities.CheckArgumentNotNull(entityDescriptorData, "entityDescriptorData");

            Type       entityType     = entityDescriptorData.Entity.GetType();
            EntityType testEntityType = this.entityModelSchema.EntityTypes.Single(et => et.FullName == entityType.FullName);

            // Calculate expected version based on type's feed mappings.
            DataServiceProtocolVersion expectedVersion = VersionHelper.CalculateEntityPropertyMappingProtocolVersion(testEntityType, VersionCalculationType.Response, MimeTypes.ApplicationAtomXml, maxProtocolVersion, maxProtocolVersion);

            // Commenting out this code pending a quick versioning discussion with pratikp and ahmed
            // Cannot check in as with code it breaks BVT's, want to get this in and update pending discussion 12-7-10
            // if (testEntityType.AllProperties.Any(p => p.IsStream()))
            // {
            //    expectedVersion = VersionHelper.IncreaseVersionIfRequired(expectedVersion, DataServiceProtocolVersion.V4);
            // }
            // If there are bag properties then its at least v3
            if (testEntityType.HasMultiValue(true) ||
                testEntityType.HasSpatialProperties())
            {
                expectedVersion = VersionHelper.IncreaseVersionIfRequired(expectedVersion, DataServiceProtocolVersion.V4);
            }

            return(expectedVersion);
        }
 private HttpRequestData CreateDeleteRequest(EntityDescriptorData entityDescriptorData)
 {
     return(new HttpRequestData()
     {
         Verb = HttpVerb.Delete,
         Uri = entityDescriptorData.EditLink,
     });
 }
            /// <summary>
            /// Creates EntityChangeData which captures the state of the specified entity descriptor data.
            /// </summary>
            /// <param name="entityDescriptorData">The entity descriptor data.</param>
            /// <param name="propertiesValues">The properties values before SaveChanges.</param>
            /// <returns>Entity change data.</returns>
            public static ChangeData Create(EntityDescriptorData entityDescriptorData, IEnumerable <NamedValue> propertiesValues)
            {
                EntityChangeData changeData = new EntityChangeData(entityDescriptorData);

                foreach (NamedValue nv in propertiesValues)
                {
                    changeData.CachedPropertiesValues.Add(nv.Name, nv.Value);
                }

                changeData.ClrTypeForRequery = entityDescriptorData.EntityClrType;

                return(changeData);
            }
Example #7
0
        private void VerifyDescriptor(DescriptorData expected, Descriptor actual, int responseOrder)
        {
            EntityDescriptorData entityDescriptorData = expected as EntityDescriptorData;
            LinkDescriptorData   linkDescriptorData   = expected as LinkDescriptorData;
            StreamDescriptorData streamDescriptorData = expected as StreamDescriptorData;

            if (entityDescriptorData != null)
            {
                EntityDescriptor entityDescriptor = actual as EntityDescriptor;
                this.Assert.IsNotNull(entityDescriptor, GetVerificationFailureMessage(responseOrder, "Unexpected descriptor type:\r\nExpected: {0}\r\nActual:   {1}\r\nExpected descriptor data: {2}.", typeof(EntityDescriptor).Name, actual.GetType().Name, entityDescriptorData));

                this.Assert.AreSame(
                    entityDescriptorData.Entity,
                    entityDescriptor.Entity,
                    GetVerificationFailureMessage(responseOrder, "Entity verification failed for the entity descriptor data: {0}.", expected));
            }
            else if (linkDescriptorData != null)
            {
                LinkDescriptor linkDescriptor = actual as LinkDescriptor;
                this.Assert.IsNotNull(linkDescriptor, GetVerificationFailureMessage(responseOrder, "Unexpected descriptor type:\r\nExpected: {0}\r\nActual:   {1}\r\nExpected descriptor data: {2}.", typeof(LinkDescriptor).Name, actual.GetType().Name, linkDescriptorData));

                bool notMatch = linkDescriptorData.SourceDescriptor.Entity != linkDescriptor.Source ||
                                (linkDescriptorData.TargetDescriptor == null && linkDescriptor.Target != null) ||
                                (linkDescriptorData.TargetDescriptor != null && linkDescriptorData.TargetDescriptor.Entity != linkDescriptor.Target) ||
                                linkDescriptorData.SourcePropertyName != linkDescriptor.SourceProperty;

                this.Assert.IsFalse(notMatch, GetVerificationFailureMessage(responseOrder, "Link verification failed.\r\nExpected: {0}\r\nActual:   {1}", linkDescriptorData, linkDescriptor.ToTraceString()));
            }
            else
            {
#if WINDOWS_PHONE
                throw new TaupoNotSupportedException("StreamDescriptors are not supported on Windows Phone");
#else
                ExceptionUtilities.CheckObjectNotNull(streamDescriptorData, "Expected was not an entity, link, or stream descriptor: {0}", expected);

                StreamDescriptor streamDescriptor = actual as StreamDescriptor;

                this.Assert.IsNotNull(streamDescriptor, GetVerificationFailureMessage(responseOrder, "Unexpected descriptor type:\r\nExpected: {0}\r\nActual:   {1}\r\nExpected descriptor data: {2}.", typeof(StreamDescriptor).Name, actual.GetType().Name, streamDescriptorData));

                this.Assert.AreEqual(streamDescriptorData.State.ToProductEnum(), streamDescriptor.State, GetVerificationFailureMessage(responseOrder, "Stream descriptor state verification failed."));
                this.Assert.AreEqual(streamDescriptorData.Name, streamDescriptor.StreamLink.Name, GetVerificationFailureMessage(responseOrder, "Stream descriptor name verification failed."));
                this.Assert.AreEqual(streamDescriptorData.ETag, streamDescriptor.StreamLink.ETag, GetVerificationFailureMessage(responseOrder, "Stream descriptor etag verification failed."));
                this.Assert.AreEqual(streamDescriptorData.ContentType, streamDescriptor.StreamLink.ContentType, GetVerificationFailureMessage(responseOrder, "Stream descriptor content type verification failed."));
                this.Assert.AreEqual(streamDescriptorData.EditLink, streamDescriptor.StreamLink.EditLink, GetVerificationFailureMessage(responseOrder, "Stream descriptor edit link verification failed."));
                this.Assert.AreEqual(streamDescriptorData.SelfLink, streamDescriptor.StreamLink.SelfLink, GetVerificationFailureMessage(responseOrder, "Stream descriptor self link verification failed."));
#endif
            }
        }
Example #8
0
        /// <summary>
        /// Applies all pending updates for the given entity descriptor data
        /// </summary>
        /// <param name="data">The descriptor data to update</param>
        public void ApplyPendingUpdates(EntityDescriptorData data)
        {
            foreach (var update in this.headerUpdates.Where(u => u.Descriptor == data).ToList())
            {
                ExceptionUtilities.Assert(!this.ApplyUpdatesImmediately, "Should not have any pending header updates when ApplyUpdatesImmediately is true");
                Apply(update);
                this.headerUpdates.Remove(update);
            }

            foreach (var update in this.payloadUpdates.Where(u => u.Descriptor == data).ToList())
            {
                ExceptionUtilities.Assert(!this.ApplyUpdatesImmediately, "Should not have any pending payload updates when ApplyUpdatesImmediately is true");
                Apply(update);
                this.payloadUpdates.Remove(update);
            }
        }
Example #9
0
        /// <summary>
        /// Tracks the AddRelatedObject method.
        /// </summary>
        /// <param name="data">The data service context data on which to apply state transition.</param>
        /// <param name="source">The source.</param>
        /// <param name="sourcePropertyName">Name of the source property.</param>
        /// <param name="target">The target.</param>
        public static void TrackAddRelatedObject(this DataServiceContextData data, object source, string sourcePropertyName, object target)
        {
            CheckEntityIsNotTracked(data, target);

            EntityDescriptorData sourceDescriptorData = GetTrackedEntityDescriptorData(data, source, "Cannot add link:", "source");

            CheckStateIsNot(EntityStates.Deleted, sourceDescriptorData, "Cannot add related object:", "source");

            EntityDescriptorData targetDescriptorData = data.CreateEntityDescriptorData(EntityStates.Added, data.GetNextChangeOrder(), target);

            data.CreateLinkDescriptorData(EntityStates.Added, uint.MaxValue, sourceDescriptorData, sourcePropertyName, targetDescriptorData);

            targetDescriptorData
            .SetParentForInsert(source)
            .SetParentPropertyForInsert(sourcePropertyName);
        }
            /// <summary>
            /// Normalizes the given entity payload element
            /// </summary>
            /// <param name="entityPayload">The entity payload element</param>
            /// <param name="entityDescriptorData">The descriptor data for the entity</param>
            public void Normalize(EntityInstance entityPayload, EntityDescriptorData entityDescriptorData)
            {
                ExceptionUtilities.CheckArgumentNotNull(entityPayload, "entityPayload");
                ExceptionUtilities.CheckArgumentNotNull(entityDescriptorData, "entityDescriptorData");
                this.typeStack.Push(entityDescriptorData.EntityClrType);

                // do this before recursing because it could be over-written by the visit method
                entityPayload.FullTypeName = entityDescriptorData.ServerTypeName;

                entityPayload.Id = string.Empty;
                if (entityDescriptorData.Identity != null)
                {
                    entityPayload.Id = entityDescriptorData.Identity.OriginalString;
                }

                entityPayload.Accept(this);
            }
        private EntityInstance BuildEntityPayload(
            DataServiceContextData contextData,
            IDictionary <object, IEnumerable <NamedValue> > propertyValuesBeforeSave,
            EntityDescriptorData entityDescriptorData,
            DataServiceProtocolVersion dsv)
        {
            IEnumerable <NamedValue> propertyValues;

            ExceptionUtilities.Assert(propertyValuesBeforeSave.TryGetValue(entityDescriptorData.Entity, out propertyValues), "Could not find property values for descriptor: {0}", entityDescriptorData);

            var entityType     = this.ModelSchema.EntityTypes.Single(t => t.FullName == entityDescriptorData.EntityClrType.FullName);
            var entityInstance = this.PayloadBuilder.EntityInstance(entityType, propertyValues);

            new ExpectedPayloadNormalizer(contextData, dsv).Normalize(entityInstance, entityDescriptorData);

            return(entityInstance);
        }
        private HttpRequestData CreateUpdateRequest(SaveChangesOptions options, EntityDescriptorData entityDescriptorData)
        {
            HttpVerb updateVerb = HttpVerb.Patch;

            if (options == SaveChangesOptions.ReplaceOnUpdate)
            {
                updateVerb = HttpVerb.Put;
            }
            else if (options == SaveChangesOptions.PatchOnUpdate)
            {
                updateVerb = HttpVerb.Patch;
            }

            return(new HttpRequestData()
            {
                Verb = updateVerb,
                Uri = entityDescriptorData.EditLink,
            });
        }
Example #13
0
        /// <summary>
        /// Tracks a pending update to the given descriptor based on values read from a response payload
        /// </summary>
        /// <param name="data">The descriptor data to update</param>
        /// <param name="payload">The payload that was read</param>
        /// <param name="baseUri">The base uri of the context</param>
        public void TrackUpdateFromPayload(EntityDescriptorData data, EntityInstance payload, Uri baseUri)
        {
            ExceptionUtilities.CheckArgumentNotNull(data, "data");
            var update = new PayloadUpdate()
            {
                Descriptor = data, Payload = payload, BaseUri = baseUri
            };

            if (!this.IgnoreAllUpdates)
            {
                if (this.ApplyUpdatesImmediately)
                {
                    Apply(update);
                }
                else
                {
                    this.payloadUpdates.Add(update);
                }
            }
        }
Example #14
0
        /// <summary>
        /// Tracks a pending update to the given descriptor based on values read from response headers
        /// </summary>
        /// <param name="data">The descriptor data to update</param>
        /// <param name="headers">The headers that were read</param>
        public void TrackUpdateFromHeaders(EntityDescriptorData data, IDictionary <string, string> headers)
        {
            ExceptionUtilities.CheckArgumentNotNull(data, "data");
            var update = new HeaderUpdate()
            {
                Descriptor = data, Headers = headers
            };

            if (!this.IgnoreAllUpdates)
            {
                if (this.ApplyUpdatesImmediately)
                {
                    Apply(update);
                }
                else
                {
                    this.headerUpdates.Add(update);
                }
            }
        }
Example #15
0
        /// <summary>
        /// Tracks the SetLink method.
        /// </summary>
        /// <param name="data">The data service context data on which to apply state transition.</param>
        /// <param name="source">The source.</param>
        /// <param name="sourcePropertyName">Name of the source property.</param>
        /// <param name="target">The target.</param>
        public static void TrackSetLink(this DataServiceContextData data, object source, string sourcePropertyName, object target)
        {
            ExceptionUtilities.CheckStringArgumentIsNotNullOrEmpty(sourcePropertyName, "sourcePropertyName");

            EntityDescriptorData sourceDescriptorData = GetTrackedEntityDescriptorData(data, source, "Cannot set link:", "source");

            CheckStateIsNot(EntityStates.Deleted, sourceDescriptorData, "Cannot set link:", "source");

            EntityDescriptorData targetDescriptorData = null;

            if (target != null)
            {
                targetDescriptorData = GetTrackedEntityDescriptorData(data, target, "Cannot set link:", "target");
                CheckStateIsNot(EntityStates.Deleted, sourceDescriptorData, "Cannot set link:", "target");
            }

            var relatedToSource = data.LinkDescriptorsData.Where(e => e.SourceDescriptor.Entity == source && e.SourcePropertyName == sourcePropertyName).ToList();

            if (relatedToSource.Count > 1)
            {
                throw new TaupoInvalidOperationException("Cannot set link: source contains multiple links for the property: " + sourcePropertyName);
            }

            LinkDescriptorData existingLinkDescriptorData = relatedToSource.FirstOrDefault();

            if (existingLinkDescriptorData == null)
            {
                data.CreateLinkDescriptorData(EntityStates.Modified, data.GetNextChangeOrder(), sourceDescriptorData, sourcePropertyName, targetDescriptorData);
            }
            else
            {
                if (existingLinkDescriptorData.State != EntityStates.Modified || existingLinkDescriptorData.TargetDescriptor != targetDescriptorData)
                {
                    data.ChangeStateAndChangeOrder(existingLinkDescriptorData, EntityStates.Modified, data.GetNextChangeOrder());
                }

                existingLinkDescriptorData.TargetDescriptor = targetDescriptorData;
            }
        }
            private EntityDescriptor GetEntityDescriptor(EntityDescriptorData entityDescriptorData)
            {
                EntityDescriptor descriptor = null;

                if (entityDescriptorData.Entity != null)
                {
                    descriptor = this.context.GetEntityDescriptor(entityDescriptorData.Entity);
                }
                else
                {
                    ExceptionUtilities.Assert(entityDescriptorData.Identity == null, "Entity descriptor's Identity cannnot be null when entity is null.");

                    descriptor = this.FindEntityDescriptorWithIdentity(entityDescriptorData.Identity);
                }

                if (descriptor == null)
                {
                    throw new AssertionFailedException(
                              string.Format(CultureInfo.InvariantCulture, "Entity descriptor is missing from the data service context. Expected entity descriptor: {{{0}}}.", entityDescriptorData));
                }

                return(descriptor);
            }
        private ExpectedClientRequest CreateEntityDeleteRequest(EntityDescriptorData entityDescriptorData, SaveChangesOptions options)
        {
            var request = new ExpectedClientRequest()
            {
                Verb = HttpVerb.Delete,
                Uri  = entityDescriptorData.EditLink,
            };

            request.Headers[HttpHeaders.IfMatch] = entityDescriptorData.ETag;
            request.Headers[HttpHeaders.Prefer]  = null;

            request.Headers[HttpHeaders.DataServiceVersion] = ToClientHeaderFormat(DataServiceProtocolVersion.V4);

            this.SetDefaultAcceptHeader(request, options);

            request.Headers[HttpHeaders.ContentType] = null;

            string hintString = @"Entity delete\r\n{{\r\n  Descriptor = {0}\r\n}}";

            request.DebugHintString = string.Format(CultureInfo.InvariantCulture, hintString, entityDescriptorData);

            return(request);
        }
        private void AddFoldedLinksToEntityInsertPayload(DataServiceContextData contextData, EntityDescriptorData entityDescriptorData, EntityInstance payload)
        {
            var entityType = this.ModelSchema.EntityTypes.Single(t => t.FullName == entityDescriptorData.EntityClrType.FullName);

            foreach (var linkDescriptor in contextData.LinkDescriptorsData.Where(l => l.SourceDescriptor == entityDescriptorData))
            {
                if (linkDescriptor.TargetDescriptor.State == EntityStates.Added)
                {
                    continue;
                }

                var navigationProperty = entityType.AllNavigationProperties.Single(n => n.Name == linkDescriptor.SourcePropertyName);

                string contentType = MimeTypes.ApplicationAtomXml + ";type=";
                if (navigationProperty.ToAssociationEnd.Multiplicity == EndMultiplicity.Many)
                {
                    contentType += "feed";
                }
                else
                {
                    contentType += "entry";
                }

                // note: the edit-link is used rather than identity because the server needs to be able to query for the target entity
                // and the identity may not be an actual uri
                var link = new DeferredLink()
                {
                    UriString = linkDescriptor.TargetDescriptor.EditLink.OriginalString
                }
                .WithContentType(contentType).WithTitleAttribute(linkDescriptor.SourcePropertyName);

                payload.Add(new NavigationPropertyInstance(linkDescriptor.SourcePropertyName, link));
            }
        }
        private ExpectedClientRequest CreateEntityInsertRequest(DataServiceContextData contextData, IDictionary <object, IEnumerable <NamedValue> > propertyValuesBeforeSave, EntityDescriptorData entityDescriptorData, SaveChangesOptions options)
        {
            ExceptionUtilities.Assert(!entityDescriptorData.IsMediaLinkEntry, "Can only be used for non media-link-entries");

            var insertUri = GetEntityInsertUri(contextData, entityDescriptorData);

            ExpectedClientRequest request = new ExpectedClientRequest()
            {
                Verb = HttpVerb.Post, Uri = insertUri
            };

            string preference = contextData.AddAndUpdateResponsePreference.ToHeaderValue();
            DataServiceProtocolVersion dsv = GetDataServiceVersion(HttpVerb.Post, preference);

            dsv = dsv.IncreaseVersionIfRequired(this.VersionCalculator.CalculateDataServiceVersion(entityDescriptorData, contextData.MaxProtocolVersion));

            var payload = this.BuildEntityPayload(contextData, propertyValuesBeforeSave, entityDescriptorData, dsv);

            request.Body = payload;

            this.AddFoldedLinksToEntityInsertPayload(contextData, entityDescriptorData, payload);

            request.Headers[HttpHeaders.DataServiceVersion] = ToClientHeaderFormat(dsv);
            request.Headers[HttpHeaders.IfMatch]            = null;
            request.Headers[HttpHeaders.Prefer]             = preference;

            this.SetDefaultAcceptHeader(request, options);
            this.SetContentTypeHeaderForEntity(request);

            string hintString = @"Entity insert\r\n{{\r\n  Descriptor = {0}\r\n  Options = {1}\r\n}}";

            request.DebugHintString = string.Format(CultureInfo.InvariantCulture, hintString, entityDescriptorData, options);

            return(request);
        }
            private void VerifyEntityDescriptor(EntityDescriptorData expectedDescriptorData, EntityDescriptor actualDescriptor)
            {
                VerifyState(expectedDescriptorData, actualDescriptor);

                VerifyETag(expectedDescriptorData.ETag, actualDescriptor.ETag, expectedDescriptorData);

                VerifyExpectedVsActual(expectedDescriptorData.ServerTypeName, actualDescriptor.ServerTypeName, expectedDescriptorData, "ServerTypeName");

                VerifyExpectedVsActual(expectedDescriptorData.Identity, actualDescriptor.Identity, expectedDescriptorData, "Identity");

                VerifyExpectedVsActual(expectedDescriptorData.EditLink, actualDescriptor.EditLink, expectedDescriptorData, "EditLink");

                EntityDescriptor expectedParentForInsert = null;

                if (expectedDescriptorData.ParentForInsert != null)
                {
                    EntityDescriptorData parentForInsertDescriptorData;
                    if (!this.contextData.TryGetEntityDescriptorData(expectedDescriptorData.ParentForInsert, out parentForInsertDescriptorData))
                    {
                        throw new TaupoInvalidOperationException(
                                  string.Format(
                                      CultureInfo.InvariantCulture,
                                      "Expected context data should have entity descriptor for the parent for insert {0}. Descriptor data = {1}.",
                                      expectedDescriptorData.ParentForInsert,
                                      expectedDescriptorData));
                    }

                    expectedParentForInsert = this.GetEntityDescriptor(parentForInsertDescriptorData);
                }

                VerifyExpectedVsActual(expectedParentForInsert, actualDescriptor.ParentForInsert, expectedDescriptorData, "ParentForInsert");

                VerifyExpectedVsActual(expectedDescriptorData.ParentPropertyForInsert, actualDescriptor.ParentPropertyForInsert, expectedDescriptorData, "ParentPropertyForInsert");

                if (actualDescriptor.ParentForInsert == null)
                {
                    ExceptionUtilities.Assert(actualDescriptor.ParentPropertyForInsert == null, "ParentPropertyForInsert must be null when ParentForInsert is null.");
                }
                else
                {
                    ExceptionUtilities.Assert(!string.IsNullOrEmpty(actualDescriptor.ParentPropertyForInsert), "ParentPropertyForInsert cannot be null or empty when ParentForInsert is not null.");
                }

                VerifyExpectedVsActual(expectedDescriptorData.EditLink, actualDescriptor.EditLink, expectedDescriptorData, "EditLink");
                VerifyExpectedVsActual(expectedDescriptorData.SelfLink, actualDescriptor.SelfLink, expectedDescriptorData, "SelfLink");

                VerifyExpectedVsActual(expectedDescriptorData.EditStreamUri, actualDescriptor.EditStreamUri, expectedDescriptorData, "EditStreamUri");
                VerifyExpectedVsActual(expectedDescriptorData.ReadStreamUri, actualDescriptor.ReadStreamUri, expectedDescriptorData, "ReadStreamUri");
                VerifyExpectedVsActual(expectedDescriptorData.StreamETag, actualDescriptor.StreamETag, expectedDescriptorData, "StreamETag");

                // Check that the internal StreamDescriptor for the default stream is in the correct state, if we can do the reflection safely.
                // Note that if the descriptor is not an MLE, we don't check whether the internal value is null, since that is very much an implementation detail
#if !SILVERLIGHT
                if (expectedDescriptorData.IsMediaLinkEntry && AppDomain.CurrentDomain.IsFullyTrusted)
                {
                    var defaultStreamDescriptorProperty = typeof(EntityDescriptor).GetProperty("DefaultStreamDescriptor", BindingFlags.Instance | BindingFlags.NonPublic);
                    ExceptionUtilities.CheckObjectNotNull(defaultStreamDescriptorProperty, "Could not find property 'DefaultStreamDescriptor' on EntityDescriptor");

                    var defaultStreamDescriptor = (StreamDescriptor)defaultStreamDescriptorProperty.GetValue(actualDescriptor, null);
                    ExceptionUtilities.CheckObjectNotNull(defaultStreamDescriptor, "Product's default stream descriptor was null for entity descriptor: {0}", expectedDescriptorData);

                    var defaultStreamState = defaultStreamDescriptor.State;
                    VerifyExpectedVsActual(expectedDescriptorData.DefaultStreamState, defaultStreamState.ToTestEnum(), expectedDescriptorData, "DefaultStreamDesciptor.State");
                }
#endif

#if !WINDOWS_PHONE
                VerifyExpectedVsActual(expectedDescriptorData.LinkInfos.Count, actualDescriptor.LinkInfos.Count, expectedDescriptorData, "LinkInfos.Count");

                for (int i = 0; i < expectedDescriptorData.LinkInfos.Count; i++)
                {
                    var expectedLinkInfo = expectedDescriptorData.LinkInfos.ElementAt(i);
                    var actualLinkInfo   = actualDescriptor.LinkInfos.ElementAt(i);

                    VerifyExpectedVsActual(expectedLinkInfo.Name, actualLinkInfo.Name, expectedDescriptorData, "LinkInfos[" + i + "].Name");
                    VerifyExpectedVsActual(expectedLinkInfo.NavigationLink, actualLinkInfo.NavigationLink, expectedDescriptorData, "LinkInfos[" + i + "].NavigationLink");
                    VerifyExpectedVsActual(expectedLinkInfo.RelationshipLink, actualLinkInfo.AssociationLink, expectedDescriptorData, "LinkInfos[" + i + "].AssociationLink");
                }

                VerifyExpectedVsActual(expectedDescriptorData.OperationDescriptors.Count, actualDescriptor.OperationDescriptors.Count, expectedDescriptorData, "OperationDescriptors.Count");
                for (int i = 0; i < expectedDescriptorData.OperationDescriptors.Count; i++)
                {
                    var expectedOperationDescriptor = expectedDescriptorData.OperationDescriptors.ElementAt(i);
                    var actualOperationDescriptor   = actualDescriptor.OperationDescriptors.ElementAt(i);

                    VerifyExpectedVsActual(expectedOperationDescriptor.Metadata, actualOperationDescriptor.Metadata, expectedDescriptorData, "OperationDescriptors[" + i + "].Metadata");
                    VerifyExpectedVsActual(expectedOperationDescriptor.Target, actualOperationDescriptor.Target, expectedDescriptorData, "OperationDescriptors[" + i + "].Target");
                    VerifyExpectedVsActual(expectedOperationDescriptor.Title, actualOperationDescriptor.Title, expectedDescriptorData, "OperationDescriptors[" + i + "].Title");
                    VerifyExpectedVsActual(expectedOperationDescriptor.IsAction, actualOperationDescriptor is ActionDescriptor, "OperationDescriptors[" + i + "].IsAction");
                }

                VerifyExpectedVsActual(expectedDescriptorData.StreamDescriptors.Count, actualDescriptor.StreamDescriptors.Count, expectedDescriptorData, "StreamDescriptors.Count");
                for (int i = 0; i < expectedDescriptorData.StreamDescriptors.Count; i++)
                {
                    var expectedStreamDescriptor = expectedDescriptorData.StreamDescriptors.ElementAt(i);
                    var actualStreamDescriptor   = actualDescriptor.StreamDescriptors.ElementAt(i);

                    VerifyExpectedVsActual(expectedStreamDescriptor.Name, actualStreamDescriptor.StreamLink.Name, expectedDescriptorData, "StreamDescriptors[" + i + "].Name");
                    VerifyExpectedVsActual(expectedStreamDescriptor.ContentType, actualStreamDescriptor.StreamLink.ContentType, expectedDescriptorData, "StreamDescriptors[" + i + "].ContentType");
                    VerifyExpectedVsActual(expectedStreamDescriptor.EditLink, actualStreamDescriptor.StreamLink.EditLink, expectedDescriptorData, "StreamDescriptors[" + i + "].EditLink");
                    VerifyExpectedVsActual(expectedStreamDescriptor.ETag, actualStreamDescriptor.StreamLink.ETag, expectedDescriptorData, "StreamDescriptors[" + i + "].ETag");
                    VerifyExpectedVsActual(expectedStreamDescriptor.SelfLink, actualStreamDescriptor.StreamLink.SelfLink, expectedDescriptorData, "StreamDescriptors[" + i + "].SelfLink");

                    ExceptionUtilities.Assert(object.ReferenceEquals(expectedDescriptorData, expectedStreamDescriptor.EntityDescriptor), "Stream descriptor data had unexpected entity descriptor data");
                    VerifyExpectedVsActual(actualDescriptor, actualStreamDescriptor.EntityDescriptor, expectedDescriptorData, "StreamDescriptors[" + i + "].EntityDescriptor");
                }
#endif
            }
 private static void VerifyETag(string expectedETag, string actualETag, EntityDescriptorData entityEntry)
 {
     VerifyExpectedVsActual(expectedETag, actualETag, entityEntry, "ETag");
 }
        private ExpectedClientRequest CreateEntityUpdateRequest(DataServiceContextData contextData, IDictionary <object, IEnumerable <NamedValue> > propertyValuesBeforeSave, EntityDescriptorData entityDescriptorData, SaveChangesOptions options)
        {
            var request = new ExpectedClientRequest()
            {
                Verb = GetUpdateVerb(options),
                Uri  = entityDescriptorData.EditLink,
            };

            string preference = contextData.AddAndUpdateResponsePreference.ToHeaderValue();
            var    dsv        = GetDataServiceVersion(request.Verb, preference);

            dsv = dsv.IncreaseVersionIfRequired(this.VersionCalculator.CalculateDataServiceVersion(entityDescriptorData, contextData.MaxProtocolVersion));

            request.Headers[HttpHeaders.DataServiceVersion] = ToClientHeaderFormat(dsv);
            request.Headers[HttpHeaders.IfMatch]            = entityDescriptorData.ETag;
            request.Headers[HttpHeaders.Prefer]             = preference;

            this.SetDefaultAcceptHeader(request, options);
            this.SetContentTypeHeaderForEntity(request);

            request.Body = this.BuildEntityPayload(contextData, propertyValuesBeforeSave, entityDescriptorData, dsv);

            string hintString = @"Entity update\r\n{{\r\n  Descriptor = {0}\r\n  Options = {1}\r\n}}";

            request.DebugHintString = string.Format(CultureInfo.InvariantCulture, hintString, entityDescriptorData, options);

            return(request);
        }
        private void ApplyNextResponseHeadersAndPayload(DataServiceContextData dataBeforeSaveChanges, EntityDescriptorData entityDescriptorData, Queue <DSClient.OperationResponse> responseQueue)
        {
            ExceptionUtilities.CheckArgumentNotNull(dataBeforeSaveChanges, "dataBeforeSaveChanges");
            ExceptionUtilities.CheckArgumentNotNull(entityDescriptorData, "entityDescriptorData");
            ExceptionUtilities.CheckArgumentNotNull(responseQueue, "responseQueue");

            ExceptionUtilities.Assert(responseQueue.Count > 0, "Response queue unexpectedly empty");

            var responseForRequest = responseQueue.Dequeue();

            entityDescriptorData.UpdateFromHeaders(responseForRequest.Headers);
        }
        private HttpRequestData CreateInsertRequest(DataServiceContextData dataBeforeSaveChanges, EntityDescriptorData entityDescriptorData)
        {
            Uri insertUri;

            if (entityDescriptorData.InsertLink != null)
            {
                insertUri = entityDescriptorData.InsertLink;
            }
            else
            {
                ExceptionUtilities.CheckObjectNotNull(entityDescriptorData.ParentForInsert, "Entity descriptor data did not have insert link or parent for insert: {0}", entityDescriptorData);
                ExceptionUtilities.CheckObjectNotNull(entityDescriptorData.ParentPropertyForInsert, "Entity descriptor data did not have insert link or parent property for insert: {0}", entityDescriptorData);

                var parentDescriptor = dataBeforeSaveChanges.GetEntityDescriptorData(entityDescriptorData.ParentForInsert);
                var linkInfo         = parentDescriptor.LinkInfos.SingleOrDefault(l => l.Name == entityDescriptorData.ParentPropertyForInsert);
                if (linkInfo != null && linkInfo.NavigationLink != null)
                {
                    insertUri = linkInfo.NavigationLink;
                }
                else
                {
                    insertUri = new Uri(UriHelpers.ConcatenateUriSegments(parentDescriptor.EditLink.OriginalString, entityDescriptorData.ParentPropertyForInsert));
                }
            }

            return(new HttpRequestData()
            {
                Verb = HttpVerb.Post, Uri = insertUri
            });
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="EntityChangeData"/> class.
 /// </summary>
 /// <param name="entityDescriptorData">The entity descriptor data.</param>
 protected EntityChangeData(EntityDescriptorData entityDescriptorData)
     : base(entityDescriptorData)
 {
     this.CachedPropertiesValues = new Dictionary <string, object>();
 }