Ejemplo n.º 1
0
        /// <summary>
        /// Changes the state and change order.
        /// </summary>
        /// <param name="descriptorData">The descriptor data.</param>
        /// <param name="state">The state.</param>
        /// <param name="changeOrder">The change order.</param>
        /// <remarks>There is no check that change order is unique as it's expensive.
        /// Use <see cref="GetNextChangeOrder"/> to treat the change (if any) as latest.
        /// </remarks>
        /// <exception cref="TaupoArgumentNullException">
        /// When descriptorData is null.
        /// </exception>
        /// <exception cref="TaupoInvalidOperationException">
        /// When state is Detached, change order is less then 0 or change order is 0 and state is not Unchanged.
        /// </exception>
        public void ChangeStateAndChangeOrder(DescriptorData descriptorData, EntityStates state, long changeOrder)
        {
            ExceptionUtilities.CheckArgumentNotNull(descriptorData, "descriptorData");

            if (state == EntityStates.Detached)
            {
                throw new TaupoInvalidOperationException("Cannot create descriptor in a Detached state.");
            }

            if (changeOrder < 0)
            {
                throw new TaupoInvalidOperationException("Change order cannot be less then 0.");
            }

            if (changeOrder == 0 && state != EntityStates.Unchanged)
            {
                throw new TaupoInvalidOperationException("Change order cannot be 0 when state is not Unchanged.");
            }

            //// Note: there is no check that change order is unique as it's expensive.

            descriptorData.State = state;
            descriptorData.ChangeOrder = changeOrder;

            if (this.nextChangeOrder <= descriptorData.ChangeOrder && descriptorData.ChangeOrder != uint.MaxValue)
            {
                this.nextChangeOrder = descriptorData.ChangeOrder + 1;
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Removes the descriptor data.
        /// </summary>
        /// <param name="descriptorData">The descriptor data.</param>
        /// <returns>False if the descriptor data is not found, true otherwise.</returns>
        public bool RemoveDescriptorData(DescriptorData descriptorData)
        {
            ExceptionUtilities.CheckArgumentNotNull(descriptorData, "descriptorData");

            var entityData = descriptorData as EntityDescriptorData;

            if (entityData != null)
            {
                return this.RemoveEntityData(entityData);
            }
            else
            {
                return this.RemoveLinkData((LinkDescriptorData)descriptorData);
            }
        }
        /// <summary>
        /// Calculates expected data for a request during DataServiceContext.SaveChanges for a particular descriptor.
        /// </summary>
        /// <param name="contextData">The context data</param>
        /// <param name="propertyValuesBeforeSave">The property values of the tracked client objects before the call to SaveChanges</param>
        /// <param name="descriptorData">The descriptor data</param>
        /// <param name="options">The save changes options</param>
        /// <returns>The expected client request</returns>
        public ExpectedClientRequest CalculateRequest(DataServiceContextData contextData, IDictionary<object, IEnumerable<NamedValue>> propertyValuesBeforeSave, DescriptorData descriptorData, SaveChangesOptions options)
        {
            ExceptionUtilities.CheckArgumentNotNull(contextData, "contextData");
            ExceptionUtilities.CheckArgumentNotNull(descriptorData, "descriptorData");
            ExceptionUtilities.CheckArgumentNotNull(propertyValuesBeforeSave, "propertyValuesBeforeSave");

            var linkDescriptorData = descriptorData as LinkDescriptorData;
            var entityDescriptorData = descriptorData as EntityDescriptorData;
            var streamDescriptorData = descriptorData as StreamDescriptorData;

            ExpectedClientRequest request = null;
            if (linkDescriptorData != null)
            {
                if (linkDescriptorData.WillTriggerSeparateRequest())
                {
                    request = this.CreateLinkRequest(linkDescriptorData, options);
                }
            }
            else if (entityDescriptorData != null)
            {
                if (entityDescriptorData.State == EntityStates.Added)
                {
                    request = this.CreateEntityInsertRequest(contextData, propertyValuesBeforeSave, entityDescriptorData, options);
                }
                else if (entityDescriptorData.State == EntityStates.Modified)
                {
                    request = this.CreateEntityUpdateRequest(contextData, propertyValuesBeforeSave, entityDescriptorData, options);
                }
                else if (entityDescriptorData.State == EntityStates.Deleted)
                {
                    request = this.CreateEntityDeleteRequest(entityDescriptorData, options);
                }
            }
            else if (streamDescriptorData != null)
            {
                if (streamDescriptorData.State == EntityStates.Added)
                {
                    request = this.CreateStreamInsertRequest(contextData, streamDescriptorData, options);
                }
                else if (streamDescriptorData.State == EntityStates.Modified)
                {
                    request = this.CreateStreamUpdateRequest(streamDescriptorData, options);
                }
            }

            if (request != null)
            {
                request.Headers[HttpHeaders.MaxDataServiceVersion] = ToClientHeaderFormat(contextData.MaxProtocolVersion);

                // perform sanity checks
                var missingHeaders = headersThatWillBeGenerated.Where(h => !request.Headers.ContainsKey(h)).ToArray();
                ExceptionUtilities.Assert(missingHeaders.Length == 0, "Generated request was missing headers: {0}", string.Join(", ", missingHeaders));
                ExceptionUtilities.CheckObjectNotNull(request.Uri, "Generated request was missing a Uri");

                // sanity check: Client sends content-type header for delete request
                if (request.GetEffectiveVerb() == HttpVerb.Delete)
                {
                    ExceptionUtilities.Assert(
                        request.Headers[HttpHeaders.ContentType] == null,
                        "Incorrect expectation: client should never send ContentType header for DELETE requests.");
                }
            }

            return request;
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ChangeOperationResponseData"/> class.
        /// </summary>
        /// <param name="descriptorData">The descriptor data that represents tha change operation.</param>
        public ChangeOperationResponseData(DescriptorData descriptorData)
        {
            ExceptionUtilities.CheckArgumentNotNull(descriptorData, "descriptorData");

            this.DescriptorData = descriptorData;
        }
            private void UpdateResponse(DataServiceResponseData responseData, DescriptorData descriptor, HttpResponseData response)
            {
                var operationResponse = new ChangeOperationResponseData(descriptor);
                operationResponse.StatusCode = (int)response.StatusCode;
                foreach (var header in response.Headers)
                {
                    operationResponse.Headers.Add(header.Key, header.Value);
                }

                responseData.Add(operationResponse);
            }
            private void ApplyResponseToDescriptor(DescriptorData descriptor, HttpResponseData response)
            {
                var entityDescriptor = descriptor as EntityDescriptorData;
                var streamDescriptor = descriptor as StreamDescriptorData;

                if (entityDescriptor != null)
                {
                    if (entityDescriptor.IsMediaLinkEntry && entityDescriptor.DefaultStreamState == EntityStates.Modified)
                    {
                        // in this case (and only this case), the response headers apply to the stream itself
                        entityDescriptor.DefaultStreamDescriptor.UpdateFromHeaders(response.Headers);
                    }
                    else
                    {
                        entityDescriptor.UpdateFromHeaders(response.Headers);
                    }

                    if (response.StatusCode != HttpStatusCode.NoContent)
                    {
                        var entityInstance = response.DeserializeAndCast<EntityInstance>(this.parent.FormatSelector);
                        entityDescriptor.UpdateFromPayload(entityInstance, this.contextData.BaseUri);
                    }

                    if (entityDescriptor.IsMediaLinkEntry && entityDescriptor.DefaultStreamState != EntityStates.Unchanged)
                    {
                        this.VerifyStreamClosed(entityDescriptor.DefaultStreamDescriptor);
                    }
                }
                else
                {
                    if (streamDescriptor != null)
                    {
                        streamDescriptor.UpdateFromHeaders(response.Headers);
                        this.VerifyStreamClosed(streamDescriptor);
                    }
                    else
                    {
                        ExceptionUtilities.Assert(descriptor is LinkDescriptorData, "Descriptor is of unexpected type '{0}'", descriptor.GetType());
                    }
                }
            }
            private void UpdateDescriptorState(DescriptorData descriptor)
            {
                var entityDescriptor = descriptor as EntityDescriptorData;
                var streamDescriptor = descriptor as StreamDescriptorData;

                if (entityDescriptor != null)
                {
                    var initialState = entityDescriptor.State;
                    if (entityDescriptor.State == EntityStates.Deleted)
                    {
                        this.contextData.RemoveDescriptorData(entityDescriptor);

                        foreach (var link in this.contextData.LinkDescriptorsData.Where(l => l.SourceDescriptor == entityDescriptor || l.TargetDescriptor == entityDescriptor).ToList())
                        {
                            this.contextData.RemoveDescriptorData(link);
                        }
                    }
                    else
                    {
                        if (entityDescriptor.State == EntityStates.Added)
                        {
                            this.contextData.LinkDescriptorsData
                                .Where(l => l.SourceDescriptor == entityDescriptor && l.State != EntityStates.Deleted && l.TargetDescriptor.State != EntityStates.Added)
                                .ForEach(l => l.State = EntityStates.Unchanged);

                            if (entityDescriptor.ParentForInsert != null)
                            {
                                var parentLink = this.contextData.LinkDescriptorsData
                                    .SingleOrDefault(l => l.SourceDescriptor.Entity == entityDescriptor.ParentForInsert
                                        && l.SourcePropertyName == entityDescriptor.ParentPropertyForInsert
                                        && l.TargetDescriptor == descriptor);
                                ExceptionUtilities.CheckObjectNotNull(parentLink, "Could not find parent link descriptor for entity descriptor: '{0}'", entityDescriptor);
                                ExceptionUtilities.Assert(parentLink.State == EntityStates.Added, "Parent link for entity descriptor '{0}' was not in the added state", entityDescriptor);
                                parentLink.State = EntityStates.Unchanged;
                            }
                            
                            entityDescriptor.InsertLink = null;
                            entityDescriptor.ParentForInsert = null;
                            entityDescriptor.ParentPropertyForInsert = null;
                        }

                        entityDescriptor.State = EntityStates.Unchanged;
                    }

                    if (entityDescriptor.IsMediaLinkEntry)
                    {
                        if (entityDescriptor.DefaultStreamState == EntityStates.Added)
                        {
                            // the stream insert should always leave the entity in modified state, so that the properties are updated
                            entityDescriptor.State = EntityStates.Modified;
                        }
                        else if (entityDescriptor.DefaultStreamState == EntityStates.Modified)
                        {
                            // if the stream was being updated, the entity's state should not have changed
                            entityDescriptor.State = initialState;
                        }

                        entityDescriptor.DefaultStreamState = EntityStates.Unchanged;
                    }
                }
                else
                {
                    if (streamDescriptor == null)
                    {
                        ExceptionUtilities.CheckObjectNotNull(descriptor as LinkDescriptorData, "Descriptor is of unexpected type '{0}'", descriptor.GetType());
                    }
                    
                    if (descriptor.State == EntityStates.Deleted)
                    {
                        this.contextData.RemoveDescriptorData(descriptor);
                    }
                    else
                    {
                        descriptor.State = EntityStates.Unchanged;
                    }
                }
            }
            private void ApplyResponseAndUpdateState(DescriptorData descriptor, KeyValuePair<IHttpRequest, HttpResponseData> pair)
            {
                this.ApplyResponseToDescriptor(descriptor, pair.Value);

                if (!pair.Value.StatusCode.IsError())
                {
                    this.UpdateDescriptorState(descriptor);
                }
            }
 private static void CheckStateIsNot(EntityStates state, DescriptorData descriptorData, string errorMessage, string argumentName)
 {
     if (descriptorData.State == state)
     {
         throw new TaupoInvalidOperationException(
             string.Format(CultureInfo.InvariantCulture, "{0} {1} is in {2} state.", errorMessage, argumentName, state));
     }
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="ChangeData"/> class.
 /// </summary>
 /// <param name="descriptorData">The descriptor data.</param>
 protected ChangeData(DescriptorData descriptorData)
 {
     this.State = descriptorData.State;
     this.DescriptorData = descriptorData;
 }
        private ChangeData CreateChangeData(DescriptorData descriptorData, IDictionary<object, IEnumerable<NamedValue>> propertyValuesBeforeSave)
        {
            var entityDescriptorData = descriptorData as EntityDescriptorData;
            if (entityDescriptorData != null)
            {
                IEnumerable<NamedValue> propertyValues;
                ExceptionUtilities.Assert(propertyValuesBeforeSave.TryGetValue(entityDescriptorData.Entity, out propertyValues), "Could not find property values for descriptor: {0}", entityDescriptorData);

                return EntityChangeData.Create(entityDescriptorData, propertyValues);
            }

            var linkDescriptorData = descriptorData as LinkDescriptorData;
            ExceptionUtilities.CheckObjectNotNull(linkDescriptorData, "Descriptor was neither an entity nor a link");

            return LinkChangeData.Create(linkDescriptorData);
        }
Ejemplo n.º 12
0
 /// <summary>
 /// Returns a value indicating whether the descriptor should be updated based on its state and the context's merge option
 /// </summary>
 /// <param name="contextData">The context data</param>
 /// <param name="descriptorData">The descriptor data</param>
 /// <param name="isNewDescriptor">A value indicating whether the descriptor has just been created</param>
 /// <returns>True if changes should be applied, false otherwise</returns>
 public static bool ShouldApplyChangeToDescriptor(this DataServiceContextData contextData, DescriptorData descriptorData, bool isNewDescriptor)
 {
     return isNewDescriptor || contextData.MergeOption == MergeOption.OverwriteChanges || (contextData.MergeOption == MergeOption.PreserveChanges && descriptorData.State == EntityStates.Unchanged);
 }
Ejemplo n.º 13
0
 private static void SetDetachedState(DescriptorData data)
 {
     data.State = EntityStates.Detached;
 }
        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
            }
        }
 private static void SetContentIDHeader(DescriptorData descriptor, ExpectedClientRequest expectedRequest, bool isBatch)
 {
     if (isBatch)
     {
         expectedRequest.Headers[HttpHeaders.ContentId] = descriptor.ChangeOrder.ToString(CultureInfo.InvariantCulture);
         var entityDescriptorData = descriptor as EntityDescriptorData;
        
         if (entityDescriptorData != null && entityDescriptorData.Identity == null)
         {
             entityDescriptorData.Identity = new Uri("$" + descriptor.ChangeOrder, UriKind.Relative);
             entityDescriptorData.EditLink = entityDescriptorData.Identity;
         }
     }
     else
     {
         expectedRequest.Headers[HttpHeaders.ContentId] = null;
     }
 }
Ejemplo n.º 16
0
 /// <summary>
 /// Returns a value indicating whether the descriptor should be updated based on its state and the context's merge option
 /// </summary>
 /// <param name="contextData">The context data</param>
 /// <param name="descriptorData">The descriptor data</param>
 /// <param name="isNewDescriptor">A value indicating whether the descriptor has just been created</param>
 /// <returns>True if changes should be applied, false otherwise</returns>
 public static bool ShouldApplyChangeToDescriptor(this DataServiceContextData contextData, DescriptorData descriptorData, bool isNewDescriptor)
 {
     return(isNewDescriptor || contextData.MergeOption == MergeOption.OverwriteChanges || (contextData.MergeOption == MergeOption.PreserveChanges && descriptorData.State == EntityStates.Unchanged));
 }
        /// <summary>
        /// Initializes a new instance of the <see cref="ChangeOperationResponseData"/> class.
        /// </summary>
        /// <param name="descriptorData">The descriptor data that represents tha change operation.</param>
        public ChangeOperationResponseData(DescriptorData descriptorData)
        {
            ExceptionUtilities.CheckArgumentNotNull(descriptorData, "descriptorData");

            this.DescriptorData = descriptorData;
        }