Пример #1
30
        public void SingleChangesetShouldBeAtomic()
        {
            this.TestClientContext.MergeOption = MergeOption.OverwriteChanges;
            SaveChangesOptions[] options = new SaveChangesOptions[]
            {
                // All modifications share one changeset
                SaveChangesOptions.BatchWithSingleChangeset,

                // Each modification uses seperate changeset
                SaveChangesOptions.BatchWithIndependentOperations
            };

            Airline airline = new Airline()
            {
                Name = "American Delta",
                AirlineCode = "DL",
                TimeStampValue = new byte[] { 0 }
            };

            Airline airline1 = new Airline()
            {
                Name = "American Delta",
                AirlineCode = "DL",
                TimeStampValue = new byte[] { 0 }
            };

            Flight flight = new Flight()
            {
                ConfirmationCode = "JH58496",
                FlightNumber = "DL589",
                StartsAt = new DateTimeOffset(new DateTime(2014, 2, 10, 15, 00, 0)),
                EndsAt = new DateTimeOffset(new DateTime(2014, 2, 10, 16, 30, 0)),
                AirlineId = "DL",
                SeatNumber = "C32",
                FromId = "KSEA",
                ToId = "ZSSS",
                Airline = airline
            };

            foreach (var option in options)
            {
                this.TestClientContext.ResetDataSource().Execute();

                this.TestClientContext.AddToAirlines(airline);
                this.TestClientContext.AddToFlights(flight);
                // Post an entity with same ID, this would cause creation failture.
                this.TestClientContext.AddToAirlines(airline1);

                switch (option)
                {
                    case SaveChangesOptions.BatchWithIndependentOperations:
                        DataServiceResponse response1 = this.TestClientContext.SaveChanges(option);
                        Assert.Equal(200, response1.BatchStatusCode);
                        Assert.True(response1.IsBatchResponse);
                        Assert.Equal(3, response1.Count());
                        var result = response1.ToList();

                        // 3rd operation would fail, but new flight entry would be inserted.
                        Assert.Equal(201, result[0].StatusCode);
                        Assert.Equal(201, result[1].StatusCode);
                        Assert.Equal(500, result[2].StatusCode);
                        Assert.Equal(1,
                            this.TestClientContext
                                .Flights.Where(f => f.FlightNumber == flight.FlightNumber).ToList().Count);
                        break;
                    case SaveChangesOptions.BatchWithSingleChangeset:
                        bool exc = false;
                        try
                        {
                            // The single changeset would fail.
                            this.TestClientContext.SaveChanges(option);
                        }
                        catch (Exception)
                        {
                            exc = true;
                        }

                        Assert.True(exc);

                        Assert.Equal(0,
                            this.TestClientContext
                                .Flights.Where(f => f.FlightNumber == flight.FlightNumber).ToList().Count);
                        break;
                }


                this.TestClientContext.Detach(airline1);
                this.TestClientContext.Detach(airline);
                this.TestClientContext.Detach(flight);
            }
        }
Пример #2
0
        /// <summary>
        /// constructor for SaveResult
        /// </summary>
        /// <param name="context">context</param>
        /// <param name="method">method</param>
        /// <param name="options">options</param>
        /// <param name="callback">user callback</param>
        /// <param name="state">user state object</param>
        internal SaveResult(DataServiceContext context, string method, SaveChangesOptions options, AsyncCallback callback, object state)
            : base(context, method, null, options, callback, state)
        {
            Debug.Assert(!Util.IsBatch(this.Options), "Util.IsBatch(this.Options) is not set");

            this.cachedResponses = new List<CachedResponse>();
        }
Пример #3
0
        private SaveChangesResultCollection CreateSaveChangesResultCollection(SaveChangesOptions option)
        {
            var con     = typeof(SaveChangesResultCollection).GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance).FirstOrDefault();
            var results = con.Invoke(new object[] { option }) as SaveChangesResultCollection;

            return(results);
        }
Пример #4
0
        public void AddObjectTestAction(ODataFormat format, MergeOption mergeOption, SaveChangesOptions saveChangesOption)
        {
            DataServiceContextWrapper <DefaultContainer> contextWrapper = this.CreateContext();

            contextWrapper.Context.MergeOption = mergeOption;
            if (format == ODataFormat.Json)
            {
                contextWrapper.Format.UseJson();
            }

            contextWrapper.Configurations.RequestPipeline
            .OnEntryStarting(PipelineEventsTestsHelper.ModifyPropertyValueCustomerEntity_Writing)
            .OnEntryEnding(PipelineEventsTestsHelper.ModifyPropertyValueCustomerEntry_Writing);

            Customer customer = PipelineEventsTestsHelper.CreateNewCustomer(100);

            contextWrapper.AddObject("Customer", customer);
            contextWrapper.SaveChanges(saveChangesOption);

            Assert.IsTrue(customer.Name.EndsWith("UpdatedODataEntryPropertyValue"), "Unexpected primitive property");
            Assert.IsTrue(customer.Auditing.ModifiedBy.Equals("UpdatedODataEntryPropertyValue"), "Unexpected complex property");
            Assert.IsTrue(customer.PrimaryContactInfo.EmailBag.Contains("UpdatedODataEntryPropertyValue"));

            contextWrapper.DeleteObject(customer);
            contextWrapper.SaveChanges();
        }
Пример #5
0
        public async new Task <DataServiceResponse> SaveChangesAsync(SaveChangesOptions options)
        {
            try
            {
                var result = await Task.Factory.FromAsync(
                    BeginSaveChanges,
                    new Func <IAsyncResult, DataServiceResponse>(EndSaveChanges),
                    options,
                    null,
                    TaskCreationOptions.None);

                foreach (var i in _modifiedEntities)
                {
                    i.ResetChanges();
                }

                _modifiedEntities.Clear();
                return(result);
            }
            catch (Exception ex)
            {
                var newException = ProcessException(ex);

                if (newException != null)
                {
                    throw newException;
                }

                throw;
            }
        }
Пример #6
0
 /// <summary>
 /// constructor for BatchSaveResult
 /// </summary>
 /// <param name="context">context</param>
 /// <param name="method">method</param>
 /// <param name="queries">queries</param>
 /// <param name="options">options</param>
 /// <param name="callback">user callback</param>
 /// <param name="state">user state object</param>
 internal BatchSaveResult(DataServiceContext context, string method, DataServiceRequest[] queries, SaveChangesOptions options, AsyncCallback callback, object state)
     : base(context, method, queries, options, callback, state)
 {
     Debug.Assert(Util.IsBatch(options), "the options must have batch  flag set");
     this.Queries = queries;
     this.streamCopyBuffer = new byte[StreamCopyBufferSize];
 }
Пример #7
0
        /// <summary>
        /// constructor for SaveResult
        /// </summary>
        /// <param name="context">context</param>
        /// <param name="method">method</param>
        /// <param name="options">options</param>
        /// <param name="callback">user callback</param>
        /// <param name="state">user state object</param>
        internal SaveResult(DataServiceContext context, string method, SaveChangesOptions options, AsyncCallback callback, object state)
            : base(context, method, null, options, callback, state)
        {
            Debug.Assert(!Util.IsBatch(this.Options), "Util.IsBatch(this.Options) is not set");

            this.cachedResponses = new List <CachedResponse>();
        }
Пример #8
0
        public void PostFullPropertiesInBatch()
        {
            var batchFlags = new SaveChangesOptions[] { SaveChangesOptions.BatchWithSingleChangeset, SaveChangesOptions.BatchWithIndependentOperations };

            foreach (var batchFlag in batchFlags)
            {
                List <ODataResource> entries = new List <ODataResource>();
                this.TestClientContext.Configurations.RequestPipeline.OnEntryEnding((arg) =>
                {
                    entries.Add(arg.Entry);
                });

                DataServiceCollection <CustomerPlus> people =
                    new DataServiceCollection <CustomerPlus>(this.TestClientContext, "People", null, null);
                var person = new CustomerPlus();
                people.Add(person);

                person.FirstNamePlus = "Nelson";
                person.LastNamePlus  = "Black";
                person.NumbersPlus   = new ObservableCollection <string> {
                };
                person.EmailsPlus    = new ObservableCollection <string> {
                    "*****@*****.**"
                };
                person.PersonIDPlus = 10001;
                person.CityPlus     = "London";
                person.TimeBetweenLastTwoOrdersPlus = new TimeSpan(1);
                person.HomeAddressPlus = new HomeAddressPlus()
                {
                    CityPlus       = "Redmond",
                    PostalCodePlus = "98052",
                    StreetPlus     = "1 Microsoft Way"
                };

                DataServiceCollection <AccountPlus> accounts =
                    new DataServiceCollection <AccountPlus>(this.TestClientContext);
                var account = new AccountPlus();
                accounts.Add(account);
                account.AccountIDPlus     = 110;
                account.CountryRegionPlus = "CN";

                DataServiceCollection <ProductPlus> products = new DataServiceCollection <ProductPlus>(this.TestClientContext);
                ProductPlus product = new ProductPlus();
                products.Add(product);
                product.NamePlus            = "Apple";
                product.ProductIDPlus       = 1000000;
                product.QuantityInStockPlus = 20;
                product.QuantityPerUnitPlus = "Pound";
                product.UnitPricePlus       = 0.35f;
                product.DiscontinuedPlus    = false;
                product.CoverColorsPlus     = new ObservableCollection <ColorPlus>();

                //Post entity into an entity set
                this.TestClientContext.SaveChanges(batchFlag);

                Assert.Equal(10, entries.Where(e => e.TypeName.Contains("CustomerPlus")).First().Properties.Count());
                Assert.Equal(2, entries.Where(e => e.TypeName.Contains("AccountPlus")).First().Properties.Count());
                Assert.Equal(9, entries.Where(e => e.TypeName.Contains("ProductPlus")).First().Properties.Count());
            }
        }
        public void AddObjectTestAction(ODataFormat format, MergeOption mergeOption, SaveChangesOptions saveChangesOption)
        {
            DataServiceContextWrapper <DefaultContainer> contextWrapper = this.CreateContext();

            contextWrapper.Context.MergeOption = mergeOption;
            if (format == ODataFormat.Json)
            {
                contextWrapper.Format.UseJson();
            }

            contextWrapper.Configurations.RequestPipeline
            .OnEntryStarting(PipelineEventsTestsHelper.ModifyPropertyValueCustomerEntity_Writing)
            .OnEntryEnding(PipelineEventsTestsHelper.ModifyPropertyValueCustomerEntry_Writing);

            Customer customer = PipelineEventsTestsHelper.CreateNewCustomer(1100);

            contextWrapper.AddObject("Customer", customer);

            IAsyncResult r1 = contextWrapper.BeginSaveChanges(
                saveChangesOption,
                result =>
            {
                contextWrapper.EndSaveChanges(result);
            },
                null);

            while (!r1.IsCompleted)
            {
                Thread.Sleep(1000);
            }


            if (format == ODataFormat.Atom)
            {
                // Make the ATOM payload order consistence with JSON.
                Assert.IsTrue(customer.Name.EndsWith("UpdatedODataEntryPropertyValueModifyPropertyValueCustomerEntry_Writing"), "Unexpected primitive property");
            }
            else
            {
                Assert.IsTrue(customer.Name.EndsWith("UpdatedODataEntryPropertyValue"), "Unexpected primitive property");
            }

            Assert.IsTrue(customer.Auditing.ModifiedBy.Equals("UpdatedODataEntryPropertyValue"), "Unexpected complex property");
            Assert.IsTrue(customer.PrimaryContactInfo.EmailBag.Contains("UpdatedODataEntryPropertyValue"));

            contextWrapper.DeleteObject(customer);
            IAsyncResult r2 = contextWrapper.BeginSaveChanges(
                saveChangesOption,
                result =>
            {
                contextWrapper.EndSaveChanges(result);
            },
                null);

            while (!r2.IsCompleted)
            {
                Thread.Sleep(1000);
            }
        }
        /// <summary>
        /// Wrapper entry for the DataServiceContext.SaveChanges method.
        /// </summary>
        /// <param name="options">options on how to save changes</param>
        /// <returns>changeset response</returns>
        public DataServiceResponse SaveChanges(SaveChangesOptions options)
        {
#if SILVERLIGHT || PORTABLELIB
            throw new NotImplementedException();
#else
            return(this.wrappedInstance.SaveChanges(options));
#endif
        }
Пример #11
0
        /// <summary>
        /// Wrapper entry for the DataServiceContext.SaveChanges method.
        /// </summary>
        /// <param name="options">options on how to save changes</param>
        /// <returns>changeset response</returns>
        public DataServiceResponse SaveChanges(SaveChangesOptions options)
        {
#if (NETCOREAPP1_0 || NETCOREAPP2_0)
            throw new NotImplementedException();
#else
            return(this.wrappedInstance.SaveChanges(options));
#endif
        }
 public static Task<DataServiceResponse> SaveChangesWithRetriesAsync(this TableServiceContext context, SaveChangesOptions options)
 {
     return
         Task.Factory.FromAsync<SaveChangesOptions, DataServiceResponse>(context.BeginSaveChangesWithRetries,
                                                                         context.EndSaveChangesWithRetries,
                                                                         options,
                                                                         null);
 }
Пример #13
0
        public override object GetResults(IAsyncResult async)
        {
            object[]           state   = (object[])async.AsyncState;
            SaveChangesOptions option  = (SaveChangesOptions)state[0];
            DataServiceContext context = (DataServiceContext)state[1];

            return(context.EndSaveChanges(async));
        }
        public ICancellableAsyncResult BeginSaveChangesWithRetries(SaveChangesOptions options, TableRequestOptions requestOptions, OperationContext operationContext, AsyncCallback callback, object state)
        {
            requestOptions   = TableRequestOptions.ApplyDefaults(requestOptions, this.ServiceClient);
            operationContext = operationContext ?? new OperationContext();
            TableCommand <DataServiceResponse, DataServiceResponse> cmd = this.GenerateSaveChangesCommand(options, requestOptions);

            return(TableExecutor.BeginExecuteAsync(cmd, requestOptions.RetryPolicy, operationContext, callback, state));
        }
Пример #15
0
 /// <summary>
 /// Initializes a new instance of the PipelineEmulator class
 /// </summary>
 /// <param name="parent">The parent instance to get dependencies from</param>
 /// <param name="contextData">The current context data</param>
 /// <param name="propertyValuesBeforeSave">The property values of the tracked client objects before the call to SaveChanges</param>
 /// <param name="options">The current save-changes options</param>
 /// <param name="requestResponsePairs">The observed http traffic for the current save-changes call</param>
 public PipelineEmulator(SaveChangesHttpValidatingEmulator parent, DataServiceContextData contextData, IDictionary <object, IEnumerable <NamedValue> > propertyValuesBeforeSave, SaveChangesOptions options, IEnumerable <KeyValuePair <IHttpRequest, HttpResponseData> > requestResponsePairs)
 {
     this.parent      = parent;
     this.contextData = contextData;
     this.propertyValuesBeforeSave = propertyValuesBeforeSave;
     this.options   = options;
     this.httpQueue = new Queue <KeyValuePair <IHttpRequest, HttpResponseData> >(requestResponsePairs);
 }
Пример #16
0
 /// <summary>
 /// Begins an asynchronous operation to save changes, using the retry policy specified for the service context.
 /// </summary>
 /// <param name="options">Additional options for saving changes.</param>
 /// <param name="callback">The callback delegate that will receive notification when the asynchronous operation completes.</param>
 /// <param name="state">A user-defined object that will be passed to the callback delegate.</param>
 /// <returns>An <see cref="IAsyncResult"/> that references the asynchronous operation.</returns>
 public IAsyncResult BeginSaveChangesWithRetries(SaveChangesOptions options, AsyncCallback callback, object state)
 {
     return(TaskImplHelper.BeginImplWithRetry <DataServiceResponse>(
                (setResult) => this.SaveChangesWithRetriesImpl(options, setResult),
                RetryPolicy,
                callback,
                state));
 }
Пример #17
0
        /// <summary>
        /// Saves the changes with retries implementation.
        /// </summary>
        /// <param name="options">The options for saving changes.</param>
        /// <param name="setResult">The action to set result.</param>
        /// <returns>A sequence of tasks to perform the operation.</returns>
        private TaskSequence SaveChangesWithRetriesImpl(SaveChangesOptions options, Action <DataServiceResponse> setResult)
        {
            var task = this.SaveChangesAsync(options);

            yield return(task);

            setResult(task.Result);
        }
        public DataServiceResponse SaveChangesWithRetries(SaveChangesOptions options, TableRequestOptions requestOptions = null, OperationContext operationContext = null)
        {
            requestOptions   = TableRequestOptions.ApplyDefaults(requestOptions, this.ServiceClient);
            operationContext = operationContext ?? new OperationContext();
            TableCommand <DataServiceResponse, DataServiceResponse> cmd = this.GenerateSaveChangesCommand(options, requestOptions);

            return(TableExecutor.ExecuteSync(cmd, requestOptions.RetryPolicy, operationContext));
        }
        /// <summary>
        /// Validates the requests sent, updates the expected state, and produces the expected response data for a single call to SaveChanges
        /// </summary>
        /// <param name="contextData">The context data at the time save-changes was called</param>
        /// <param name="propertyValuesBeforeSave">The property values of the tracked client objects before the call to SaveChanges</param>
        /// <param name="options">The save changes options used</param>
        /// <param name="requestResponsePairs">The observed HTTP traffic during save-changes</param>
        /// <returns>The expected response data</returns>
        public DataServiceResponseData ValidateAndTrackChanges(DataServiceContextData contextData,  IDictionary<object, IEnumerable<NamedValue>> propertyValuesBeforeSave, SaveChangesOptions options, IEnumerable<KeyValuePair<HttpRequestData, HttpResponseData>> requestResponsePairs)
        {
            ExceptionUtilities.CheckArgumentNotNull(contextData, "contextData");
            ExceptionUtilities.CheckArgumentNotNull(requestResponsePairs, "requestResponsePairs");

            var castPairs = requestResponsePairs.Select(p => new KeyValuePair<IHttpRequest, HttpResponseData>(p.Key, p.Value));
            var emulator = new PipelineEmulator(this, contextData, propertyValuesBeforeSave, options, castPairs);
            return emulator.Run();
        }
        public Task <IMediaDataServiceResponse> SaveChangesAsync(SaveChangesOptions options, object state, CancellationToken token)
        {
            Task <DataServiceResponse> task = Task.Factory.FromAsync <SaveChangesOptions, DataServiceResponse>(
                _dataContext.BeginSaveChanges,
                _dataContext.EndSaveChanges,
                options,
                state).HandleCancellation(token);

            return(task.ContinueWith <IMediaDataServiceResponse>(t => WrapTask(t)));
        }
Пример #21
0
        /// <summary>
        /// checks whether the batch flag with independent Operation per change set is set
        /// </summary>
        /// <param name="options">options as specified by the user.</param>
        /// <returns>true if the given flag is set, otherwise false.</returns>
        internal static bool IsBatchWithIndependentOperations(SaveChangesOptions options)
        {
            if (Util.IsFlagSet(options, SaveChangesOptions.BatchWithIndependentOperations))
            {
                Debug.Assert(!Util.IsFlagSet(options, SaveChangesOptions.BatchWithSingleChangeset), "!Util.IsFlagSet(options, SaveChangesOptions.BatchWithSingleChangeset)");
                return(true);
            }

            return(false);
        }
        private void SetDefaultAcceptHeader(ExpectedClientRequest request, SaveChangesOptions options)
        {
            request.Headers[HttpHeaders.Accept] = string.IsNullOrWhiteSpace(this.ClientRequestAcceptHeader) ? DefaultAccept : this.ClientRequestAcceptHeader;
#if !SILVERLIGHT
            request.Headers[HttpHeaders.AcceptCharset] = DefaultEncoding;
#else
            // Silverlight does not specify AcceptCharset at the top level "because the http stack does not support it"
            request.Headers[HttpHeaders.AcceptCharset] = (options == SaveChangesOptions.Batch) ? DefaultEncoding : null;
#endif
        }
Пример #23
0
        /// <summary>
        /// Saves the changes for the given CRM organization context.
        /// </summary>
        /// <param name="saveChangesOptions">SaveChangesOptions</param>
        /// <returns>A collection of the action results <see cref="SaveChangesResultCollection"/> class.</returns>
        public virtual SaveChangesResultCollection SaveChanges(SaveChangesOptions saveChangesOptions)
        {
            Trace(string.Format(CultureInfo.InvariantCulture, TraceMessageHelper.EnteredMethod, SystemTypeName, MethodBase.GetCurrentMethod().Name));

            SaveChangesResultCollection scrc = OrganizationServiceContext.SaveChanges(saveChangesOptions);

            Trace(string.Format(CultureInfo.InvariantCulture, TraceMessageHelper.ExitingMethod, SystemTypeName, MethodBase.GetCurrentMethod().Name));

            return(scrc);
        }
        /// <summary>
        /// Saves the changes asynchronously.
        /// </summary>
        /// <param name="options">The options.</param>
        /// <param name="state">The state.</param>
        /// <returns>A function delegate that returns the future result to be available through the Task.</returns>
        public Task <IMediaDataServiceResponse> SaveChangesAsync(SaveChangesOptions options, object state)
        {
            Task <DataServiceResponse> task = Task.Factory.FromAsync <SaveChangesOptions, DataServiceResponse>(
                _dataContext.BeginSaveChanges,
                _dataContext.EndSaveChanges,
                options,
                state);

            return(task.ContinueWith <IMediaDataServiceResponse>(t => WrapTask(t), TaskContinuationOptions.AttachedToParent));
        }
Пример #25
0
        // [DataRow(SaveChangesOptions.BatchWithSingleChangeset)]
        public async Task References(SaveChangesOptions saveChangesOptions)
        {
            var book = new Book()
            {
                Id = "Id" + RandomInt(), Title = "Title " + RandomInt()
            };
            var publisher = new Publisher()
            {
                Title = "New Publisher " + RandomInt()
            };
            var author = new Author()
            {
                LastName = "New Publisher " + RandomInt()
            };

            dataServiceContext.AddObject(author);
            dataServiceContext.AddObject(publisher);
            dataServiceContext.AddObject(book);

            dataServiceContext.AddLink(publisher, Pluralize <Book>(), book);
            dataServiceContext.AddLink(author, Pluralize <Book>(), book);

            var dataServiceResponse = await dataServiceContext.SaveChangesAsync(saveChangesOptions);

            dataServiceResponse.Select(c => c.StatusCode).SequenceEqual(new[] { 201, 201, 204 });

            var authorWithBooks = await GetAuthorAsync(author.Id);

            authorWithBooks.Should().NotBeNull("Author was saved");
            authorWithBooks.Books.Any().Should().BeTrue("Book was added to author");

            var publisherWithBooks = await GetPublisherAsync(publisher);

            publisherWithBooks.Should().NotBeNull("Publisher was saved");
            publisherWithBooks.Books.Any().Should().BeTrue("Book was added to publisher");

            var bookWithPublisher = await GetBookAsync(book.Id);

            bookWithPublisher.Publisher.Should().NotBeNull("Reference was added");

            dataServiceContext.DeleteLink(publisher, "Books", book);

            dataServiceResponse = await dataServiceContext.SaveChangesAsync(saveChangesOptions);

            bookWithPublisher = await GetBookAsync(book.Id);

            bookWithPublisher.Publisher.Should().BeNull("Reference was removed");

            dataServiceContext.DeleteObject(book);
            dataServiceContext.DeleteObject(author);
            dataServiceContext.DeleteObject(publisher);
            dataServiceResponse = await dataServiceContext.SaveChangesAsync(saveChangesOptions);

            (await GetPublisherAsync(publisher)).Should().BeNull("Publisher was deleted");
        }
Пример #26
0
        /// <param name="deferSaveChanges">true to delay saving until batch is saved; false to save immediately.</param>
        /// <param name="saveChangesOption">Save changes option to control how change requests are sent to the service.</param>
        public Task SaveChangesAsync(bool deferSaveChanges = false, SaveChangesOptions saveChangesOption = SaveChangesOptions.None)
        {
            if (deferSaveChanges)
            {
                var retVal = new TaskCompletionSource <object>();
                retVal.SetResult(null);
                return(retVal.Task);
            }

            return(Context.SaveChangesAsync(saveChangesOption));
        }
        private static Action AddObjectWithInjectedObjectDisposedOnGetStreamO(SaveChangesOptions saveChangesOptions)
        {
            IODataRequestMessage requestMessage = new ODataTestMessage();
            var responseMessage = CreateResponseMessageWithGetStreamThrowingObjectDisposeException();

            var context = new DataServiceContextWithCustomTransportLayer(ODataProtocolVersion.V4, requestMessage, responseMessage);

            context.AddObject("Products", new SimpleNorthwind.Product()
            {
                ID = 1
            });
            return(() => context.SaveChanges(saveChangesOptions));
        }
Пример #28
0
        private List <Exception> SaveConcurrent(int numberOfCalls, SaveChangesOptions options)
        {
            // Do several calls to force some timeouts
            // or manually disconnect the network while this test is running.
            string partitionKey = Guid.NewGuid().ToString();
            var    exceptions   = new ConcurrentBag <Exception>();

            var entities = Enumerable.Range(0, numberOfCalls)
                           .Select(x => new TestServiceEntity {
                PartitionKey = partitionKey, RowKey = x.ToString()
            })
                           .ToList();

            var barrier   = new Barrier(numberOfCalls);
            var countdown = new CountdownEvent(numberOfCalls);

            foreach (var entity in entities)
            {
                ThreadPool.QueueUserWorkItem(x =>
                {
                    try
                    {
                        var client         = account.CreateCloudTableClient();
                        client.RetryPolicy = RetryPolicies.NoRetry();
                        // Explicitly set a VERY short timeout, to force a timeout very frequently.
                        client.Timeout = TimeSpan.FromSeconds(1);
                        var context    = client.GetDataServiceContext();
                        context.AddObject(tableName, x);
                        barrier.SignalAndWait();
                        context.SaveChanges(options);
                    }
                    catch (Exception ex)
                    {
                        exceptions.Add(ex);
                    }
                    finally
                    {
                        countdown.Signal();
                    }
                }, entity);
            }

            countdown.Wait();
            if (exceptions.Count == 0)
            {
                Assert.Inconclusive("No exceptions were thrown to check if they are transient");
            }

            return(exceptions.ToList());
        }
Пример #29
0
        /// <summary>
        /// Executes SaveChanges on the specified context and with specified options and verifies the results.
        /// </summary>
        /// <param name="verifier">The verifier to use for verification.</param>
        /// <param name="contextData">The data for the context.</param>
        /// <param name="context">The context to verify SaveChanges on.</param>
        /// <param name="options">The options for saving changes.</param>
        /// <returns>The response from SaveChanges</returns>
        public static DSClient.DataServiceResponse VerifySaveChanges(this ISaveChangesVerifier verifier, DataServiceContextData contextData, DSClient.DataServiceContext context, SaveChangesOptions? options)
        {
#if SILVERLIGHT
            throw new TaupoNotSupportedException("Not supported in Silverlight");
#else
            ExceptionUtilities.CheckArgumentNotNull(verifier, "verifier");
            ExceptionUtilities.CheckArgumentNotNull(contextData, "contextData");
            ExceptionUtilities.CheckArgumentNotNull(context, "context");

            DSClient.DataServiceResponse response = null;
            SyncHelpers.ExecuteActionAndWait(c1 => verifier.VerifySaveChanges(c1, contextData, context, options, (c2, r) => { response = r; c2.Continue(); }));
            return response;
#endif
        }
 internal static HttpVerb GetUpdateVerb(SaveChangesOptions options)
 {
     if (options == SaveChangesOptions.ReplaceOnUpdate)
     {
         return(HttpVerb.Put);
     }
     else if (options == SaveChangesOptions.PatchOnUpdate)
     {
         return(HttpVerb.Patch);
     }
     else
     {
         return(HttpVerb.Patch);
     }
 }
Пример #31
0
        internal BaseSaveResult(DataServiceContext context, string method, DataServiceRequest[] queries, SaveChangesOptions options, AsyncCallback callback, object state)
            : base(context, method, callback, state)
        {
            this.RequestInfo = new RequestInfo(context);
            this.Options = options;
            this.SerializerInstance = new Serializer(this.RequestInfo, options);

            if (null == queries)
            {
                #region changed entries
                this.ChangedEntries = context.EntityTracker.Entities.Cast<Descriptor>()
                                      .Union(context.EntityTracker.Links.Cast<Descriptor>())
                                      .Union(context.EntityTracker.Entities.SelectMany(e => e.StreamDescriptors).Cast<Descriptor>())
                                      .Where(o => o.IsModified && o.ChangeOrder != UInt32.MaxValue)
                                      .OrderBy(o => o.ChangeOrder)
                                      .ToList();

                foreach (Descriptor e in this.ChangedEntries)
                {
                    e.ContentGeneratedForSave = false;
                    e.SaveResultWasProcessed = 0;
                    e.SaveError = null;

                    if (e.DescriptorKind == DescriptorKind.Link)
                    {
                        object target = ((LinkDescriptor)e).Target;
                        if (null != target)
                        {
                            Descriptor f = context.EntityTracker.GetEntityDescriptor(target);
                            if (EntityStates.Unchanged == f.State)
                            {
                                f.ContentGeneratedForSave = false;
                                f.SaveResultWasProcessed = 0;
                                f.SaveError = null;
                            }
                        }
                    }
                }
                #endregion
            }
            else
            {
                this.ChangedEntries = new List<Descriptor>();
            }
        }
        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,
            });
        }
Пример #33
0
        /// <summary>
        /// Overrides the base OnSavingChangesMethod
        /// For each entity, determines if an update is required.
        /// If no update is required, it detaches and reattaches to set the entity back to a "unchanged" state.
        /// Also create the entity that will ACTUALLY be subitted to the database (used in the OnExecuting method).
        /// </summary>
        /// <param name="options">Save changes options.</param>
        protected override void OnSavingChanges(SaveChangesOptions options)
        {
            // Clear the list of entities to be sumbitted
            _deltaEntities.Clear();

            // Mark any entities as unchanged that
            // are only sending the key
            Entity[] updated = GetAttachedEntities().Where(x => x.EntityState == EntityState.Changed).ToArray();

            foreach (Entity target in updated)
            {
                // Ignore updates where nothing has been updated
                Entity unchanged = _originalEntities.Find(x => x.Id == target.Id);
                if (unchanged != null)
                {
                    Entity cloneOfTarget = ShallowClone(target);
                    RemoveUnchangedFields(cloneOfTarget, unchanged);
                    _deltaEntities.Add(cloneOfTarget);

                    // Test to see if it's only the key left... if so ignore the update otherwise you will get a blank audit record
                    if (cloneOfTarget.Attributes.Count == 1)
                    {
                        object attribute = cloneOfTarget.Attributes.First().Value;

                        var id = attribute as Guid?;
                        if (id != null)
                        {
                            if (cloneOfTarget.Id == id.Value)
                            {
                                Detach(target);
                                _deltaEntities.Remove(cloneOfTarget);
                                target.EntityState = EntityState.Unchanged;
                                Attach(target);
                            }
                        }
                    }
                }
            }

            base.OnSavingChanges(options);
        }
Пример #34
0
 internal BaseSaveResult(DataServiceContext context, string method, DataServiceRequest[] queries, SaveChangesOptions options, AsyncCallback callback, object state) : base(context, method, callback, state)
 {
     this.entryIndex         = -1;
     this.RequestInfo        = new System.Data.Services.Client.RequestInfo(context);
     this.Options            = options;
     this.SerializerInstance = new Serializer(this.RequestInfo);
     if (queries == null)
     {
         this.ChangedEntries = (from o in context.EntityTracker.Entities.Cast <Descriptor>().Union <Descriptor>(context.EntityTracker.Links.Cast <Descriptor>()).Union <Descriptor>((from e in context.EntityTracker.Entities select e.StreamDescriptors).Cast <Descriptor>())
                                where o.IsModified && (o.ChangeOrder != uint.MaxValue)
                                orderby o.ChangeOrder
                                select o).ToList <Descriptor>();
         foreach (Descriptor descriptor in this.ChangedEntries)
         {
             descriptor.ContentGeneratedForSave = false;
             descriptor.SaveResultWasProcessed  = 0;
             descriptor.SaveError = null;
             if (descriptor.DescriptorKind == DescriptorKind.Link)
             {
                 object target = ((LinkDescriptor)descriptor).Target;
                 if (target != null)
                 {
                     Descriptor entityDescriptor = context.EntityTracker.GetEntityDescriptor(target);
                     if (EntityStates.Unchanged == entityDescriptor.State)
                     {
                         entityDescriptor.ContentGeneratedForSave = false;
                         entityDescriptor.SaveResultWasProcessed  = 0;
                         entityDescriptor.SaveError = null;
                     }
                 }
             }
         }
     }
     else
     {
         this.ChangedEntries = new List <Descriptor>();
     }
 }
Пример #35
0
 internal BaseSaveResult(DataServiceContext context, string method, DataServiceRequest[] queries, SaveChangesOptions options, AsyncCallback callback, object state) : base(context, method, callback, state)
 {
     this.entryIndex = -1;
     this.RequestInfo = new System.Data.Services.Client.RequestInfo(context);
     this.Options = options;
     this.SerializerInstance = new Serializer(this.RequestInfo);
     if (queries == null)
     {
         this.ChangedEntries = (from o in context.EntityTracker.Entities.Cast<Descriptor>().Union<Descriptor>(context.EntityTracker.Links.Cast<Descriptor>()).Union<Descriptor>((from e in context.EntityTracker.Entities select e.StreamDescriptors).Cast<Descriptor>())
             where o.IsModified && (o.ChangeOrder != uint.MaxValue)
             orderby o.ChangeOrder
             select o).ToList<Descriptor>();
         foreach (Descriptor descriptor in this.ChangedEntries)
         {
             descriptor.ContentGeneratedForSave = false;
             descriptor.SaveResultWasProcessed = 0;
             descriptor.SaveError = null;
             if (descriptor.DescriptorKind == DescriptorKind.Link)
             {
                 object target = ((LinkDescriptor) descriptor).Target;
                 if (target != null)
                 {
                     Descriptor entityDescriptor = context.EntityTracker.GetEntityDescriptor(target);
                     if (EntityStates.Unchanged == entityDescriptor.State)
                     {
                         entityDescriptor.ContentGeneratedForSave = false;
                         entityDescriptor.SaveResultWasProcessed = 0;
                         entityDescriptor.SaveError = null;
                     }
                 }
             }
         }
     }
     else
     {
         this.ChangedEntries = new List<Descriptor>();
     }
 }
Пример #36
0
        public async Task CRUD(SaveChangesOptions saveChangesOptions)
        {
            var entitiesCount = await dataServiceContext.Books.EntitiesCount();

            var book = new Book {
                Id = "Id" + RandomInt(), Title = "OData"
            };

            dataServiceContext.AddObject(book);

            await dataServiceContext.SaveChangesAsync(saveChangesOptions);

            var refreshedBooksCount = await dataServiceContext.Books.EntitiesCount();

            refreshedBooksCount.Should().Be(entitiesCount + 1, "New book was inserted to database");

            string changedTitle = book.Title + " renamed";

            book.Title = changedTitle;
            dataServiceContext.UpdateObject(book);

            await dataServiceContext.SaveChangesAsync(saveChangesOptions);

            var refreshedBook = await GetBookAsync(book.Id);

            refreshedBook.Should().NotBeNull("Book was saved to database");
            refreshedBook.Title.Should().Be(changedTitle, "Existing book's title was updated in the database");

            dataServiceContext.DeleteObject(book);

            await dataServiceContext.SaveChangesAsync(saveChangesOptions);

            refreshedBooksCount = await dataServiceContext.Books.EntitiesCount();

            refreshedBooksCount.Should().Be(entitiesCount, "Existing book was deleted from database");
        }
 public Task<DataServiceResponse> SaveChangesWithRetriesAsync(SaveChangesOptions options, TableRequestOptions requestOptions, OperationContext operationContext)
 {
     return this.SaveChangesWithRetriesAsync(options, requestOptions, operationContext, CancellationToken.None);
 }
 public Task<DataServiceResponse> SaveChangesWithRetriesAsync(SaveChangesOptions options, CancellationToken cancellationToken)
 {
     return AsyncExtensions.TaskFromApm(this.BeginSaveChangesWithRetries, this.EndSaveChangesWithRetries, options, cancellationToken);
 }
 public Task<DataServiceResponse> SaveChangesWithRetriesAsync(SaveChangesOptions options)
 {
     return this.SaveChangesWithRetriesAsync(options, CancellationToken.None);
 }
 public ICancellableAsyncResult BeginSaveChangesWithRetries(SaveChangesOptions options, TableRequestOptions requestOptions, OperationContext operationContext, AsyncCallback callback, object state)
 {
     requestOptions = TableRequestOptions.ApplyDefaults(requestOptions, this.ServiceClient);
     operationContext = operationContext ?? new OperationContext();
     TableCommand<DataServiceResponse, DataServiceResponse> cmd = this.GenerateSaveChangesCommand(options, requestOptions);
     return TableExecutor.BeginExecuteAsync(cmd, requestOptions.RetryPolicy, operationContext, callback, state);
 }
        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;
        }
Пример #42
0
 /// <summary>
 /// Creates a new instance of the Serializer.
 /// </summary>
 /// <param name="requestInfo">the request info.</param>
 /// <param name="options">the save change options.</param>
 internal Serializer(RequestInfo requestInfo, SaveChangesOptions options)
     : this(requestInfo)
 {
     this.options = options;
 }
        /// <summary>Saves the changes with retries implementation.</summary>
        /// <param name="options">The options for saving changes. </param>
        /// <param name="setResult">The action to set result. </param>
        /// <returns>A sequence of tasks to perform the operation. </returns>
        private TaskSequence SaveChangesWithRetriesImpl(
            SaveChangesOptions options, Action<DataServiceResponse> setResult)
        {
            var task = this.SaveChangesAsync(options);

            yield return task;

            setResult(task.Result);
        }
 internal static HttpVerb GetUpdateVerb(SaveChangesOptions options)
 {
     if (options == SaveChangesOptions.ReplaceOnUpdate)
     {
         return HttpVerb.Put;
     }
     else if (options == SaveChangesOptions.PatchOnUpdate)
     {
         return HttpVerb.Patch;
     }
     else
     {
         return HttpVerb.Patch;
     }
 }
Пример #45
0
        public void CreateRelatedEntitesWithDifferentChangesetOptions()
        {
            this.TestClientContext.MergeOption = MergeOption.OverwriteChanges;
            SaveChangesOptions[] options = new SaveChangesOptions[]
            {
                // All modifications share one changeset
                SaveChangesOptions.BatchWithSingleChangeset,

                // Each modification uses seperate changeset
                SaveChangesOptions.BatchWithIndependentOperations
            };

            Airline airline = new Airline()
            {
                Name = "American Delta",
                AirlineCode = "DL",
                TimeStampValue = new byte[] { 0 }
            };

            Flight flight = new Flight()
            {
                ConfirmationCode = "JH58496",
                FlightNumber = "DL589",
                StartsAt = new DateTimeOffset(new DateTime(2014, 2, 10, 15, 00, 0)),
                EndsAt = new DateTimeOffset(new DateTime(2014, 2, 10, 16, 30, 0)),
                AirlineId = "DL",
                SeatNumber = "C32",
                FromId = "KSEA",
                ToId = "ZSSS",
                Airline = airline
            };

            foreach (var option in options)
            {
                this.TestClientContext.ResetDataSource().Execute();

                // This should fail for BatchWithIndependentOperations, as the foreign key restriction breaks.
                this.TestClientContext.AddToFlights(flight);
                this.TestClientContext.AddToAirlines(airline);
                this.TestClientContext.SendingRequest2 += (sender, e) =>
                {
                    e.RequestMessage.SetHeader("Prefer", "odata.continue-on-error");
                };

                DataServiceResponse response1 = this.TestClientContext.SaveChanges(option);

                switch (option)
                {
                    case SaveChangesOptions.BatchWithIndependentOperations:
                        
                        Assert.Equal(200, response1.BatchStatusCode);
                        Assert.True(response1.IsBatchResponse);
                        Assert.Equal(2, response1.Count());
                        var result1 = response1.ToList();
                        // fail for adding flight, but succeed for adding airlire
                        Assert.Equal(500, result1[0].StatusCode);
                        Assert.Equal(201, result1[1].StatusCode);
                        Assert.Equal(0,
                            this.TestClientContext
                                .Flights.Where(f => f.FlightNumber == flight.FlightNumber).ToList().Count);
                        break;
                    case SaveChangesOptions.BatchWithSingleChangeset:
                        Assert.Equal(200, response1.BatchStatusCode);
                        Assert.True(response1.IsBatchResponse);
                        Assert.Equal(2, response1.Count());
                        var result2 = response1.ToList();

                        // Both would succeed
                        Assert.Equal(201, result2[0].StatusCode);
                        Assert.Equal(201, result2[1].StatusCode);

                        Assert.Equal(1,
                            this.TestClientContext
                                .Flights.Where(f => f.FlightNumber == flight.FlightNumber).ToList().Count);
                        break;

                }

                this.TestClientContext.Detach(airline);
                this.TestClientContext.Detach(flight);
            }
        }
        private ExpectedClientRequest CreateStreamUpdateRequest(StreamDescriptorData streamDescriptorData, SaveChangesOptions options)
        {
            var request = this.CreateSaveStreamRequest(streamDescriptorData, streamDescriptorData.EditLink);
            request.Headers[HttpHeaders.IfMatch] = streamDescriptorData.ETag;
            request.Headers[HttpHeaders.Prefer] = null;
            request.Headers[HttpHeaders.DataServiceVersion] = ToClientHeaderFormat(DataServiceProtocolVersion.V4);
            this.SetDefaultAcceptHeader(request, options);
            SetContentTypeHeaderForStream(request, streamDescriptorData);

            string hintString = @"Stream update\r\n{{\r\n  Descriptor = {0}\r\n\r\n}}";
            request.DebugHintString = string.Format(CultureInfo.InvariantCulture, hintString, streamDescriptorData);

            return request;
        }
        private ExpectedClientRequest CreateStreamInsertRequest(DataServiceContextData contextData, StreamDescriptorData streamDescriptorData, SaveChangesOptions options)
        {
            ExceptionUtilities.Assert(streamDescriptorData.Name == null, "Can only be used for media-resources");

            var insertUri = GetEntityInsertUri(contextData, streamDescriptorData.EntityDescriptor);

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

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

            this.SetDefaultAcceptHeader(request, options);
            SetContentTypeHeaderForStream(request, streamDescriptorData);

            string hintString = @"Stream insert\r\n{{\r\n  Descriptor = {0}\r\n\r\n}}";
            request.DebugHintString = string.Format(CultureInfo.InvariantCulture, hintString, streamDescriptorData);

            return request;
        }
        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 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;
        }
 public Task<DataServiceResponse> SaveChangesWithRetriesAsync(SaveChangesOptions options, TableRequestOptions requestOptions, OperationContext operationContext, CancellationToken cancellationToken)
 {
     return AsyncExtensions.TaskFromApm(this.BeginSaveChangesWithRetries, this.EndSaveChangesWithRetries, options, requestOptions, operationContext, cancellationToken);
 }
        internal TableCommand<DataServiceResponse, DataServiceResponse> GenerateSaveChangesCommand(SaveChangesOptions options, TableRequestOptions requestOptions)
        {
            TableCommand<DataServiceResponse, DataServiceResponse> cmd = new TableCommand<DataServiceResponse, DataServiceResponse>();

            if (requestOptions.ServerTimeout.HasValue)
            {
                this.Timeout = (int)requestOptions.ServerTimeout.Value.TotalSeconds;
            }

            cmd.ExecuteFunc = () => this.SaveChanges(options);
            cmd.Begin = (callback, state) => this.BeginSaveChanges(options, callback, state);
            cmd.End = this.EndSaveChanges;
            cmd.ParseResponse = this.ParseDataServiceResponse;
            cmd.ParseDataServiceError = StorageExtendedErrorInformation.ReadDataServiceResponseFromStream;
            cmd.Context = this;
            requestOptions.ApplyToStorageCommand(cmd);

            return cmd;
        }
        /// <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;
        }
 public DataServiceResponse SaveChangesWithRetries(SaveChangesOptions options, TableRequestOptions requestOptions = null, OperationContext operationContext = null)
 {
     requestOptions = TableRequestOptions.ApplyDefaults(requestOptions, this.ServiceClient);
     operationContext = operationContext ?? new OperationContext();
     TableCommand<DataServiceResponse, DataServiceResponse> cmd = this.GenerateSaveChangesCommand(options, requestOptions);
     return TableExecutor.ExecuteSync(cmd, requestOptions.RetryPolicy, operationContext);
 }
 public ICancellableAsyncResult BeginSaveChangesWithRetries(SaveChangesOptions options, AsyncCallback callback, object state)
 {
     return this.BeginSaveChangesWithRetries(options, null /* RequestOptions */, null /* OperationContext */, callback, state);
 }
        private void SetDefaultAcceptHeader(ExpectedClientRequest request, SaveChangesOptions options)
        {
            request.Headers[HttpHeaders.Accept] = string.IsNullOrWhiteSpace(this.ClientRequestAcceptHeader) ? DefaultAccept : this.ClientRequestAcceptHeader;
#if !SILVERLIGHT
            request.Headers[HttpHeaders.AcceptCharset] = DefaultEncoding;
#else
            // Silverlight does not specify AcceptCharset at the top level "because the http stack does not support it"
            request.Headers[HttpHeaders.AcceptCharset] = (options == SaveChangesOptions.Batch) ? DefaultEncoding : null;
#endif
        }
        private ExpectedClientRequest CreateLinkRequest(LinkDescriptorData linkDescriptorData, SaveChangesOptions options)
        {
            var info = linkDescriptorData.SourceDescriptor.LinkInfos.SingleOrDefault(l => l.Name == linkDescriptorData.SourcePropertyName);
            ExpectedClientRequest request = new ExpectedClientRequest() { Uri = BuildLinkUri(linkDescriptorData, info) };

            if (linkDescriptorData.State == EntityStates.Added)
            {
                request.Verb = HttpVerb.Post;

                // 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
                request.Body = new DeferredLink() { UriString = linkDescriptorData.TargetDescriptor.EditLink.OriginalString };
            }
            else if (linkDescriptorData.State == EntityStates.Modified)
            {
                if (linkDescriptorData.TargetDescriptor == null)
                {
                    request.Verb = HttpVerb.Delete;
                }
                else
                {
                    request.Verb = HttpVerb.Put;

                    // 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
                    request.Body = new DeferredLink() { UriString = linkDescriptorData.TargetDescriptor.EditLink.OriginalString };
                }
            }
            else
            {
                ExceptionUtilities.Assert(linkDescriptorData.State == EntityStates.Deleted, "Link descriptor was in unexpected state '{0}'", linkDescriptorData.State);

                string keyString = this.EntityDescriptorValueCalculator.CalculateEntityKey(linkDescriptorData.TargetDescriptor.Entity);
                request.Uri = new Uri(request.Uri.OriginalString + keyString);
                request.Verb = HttpVerb.Delete;
            }

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

            this.SetDefaultAcceptHeader(request, options);

            if (request.Verb != HttpVerb.Delete)
            {
                request.Headers[HttpHeaders.ContentType] = string.IsNullOrWhiteSpace(this.ClientRequestAcceptHeader) ? MimeTypes.ApplicationXml : this.ClientRequestAcceptHeader;
            }
            else
            {
                request.Headers[HttpHeaders.ContentType] = null;
            }

            string hintString = @"Link\r\n{{\r\n  Descriptor = {0}\r\n  Options = {1}\r\n}}";
            request.DebugHintString = string.Format(CultureInfo.InvariantCulture, hintString, linkDescriptorData, options);
            
            return request;
        }
Пример #57
0
 /// <summary>
 /// Saves changes, using the retry policy specified for the service context.
 /// </summary>
 /// <param name="options">Additional options for saving changes.</param>
 /// <returns> A <see cref="DataServiceResponse"/> that represents the result of the operation.</returns>
 public DataServiceResponse SaveChangesWithRetries(SaveChangesOptions options)
 {
     return(TaskImplHelper.ExecuteImplWithRetry <DataServiceResponse>(
                (setResult) => this.SaveChangesWithRetriesImpl(options, setResult),
                RetryPolicy));
 }
 /// <summary>Begins an asynchronous operation to save changes, using the retry policy specified for the service context.</summary>
 /// <param name="options">Additional options for saving changes. </param>
 /// <param name="callback">The callback delegate that will receive notification when the asynchronous operation completes. </param>
 /// <param name="state">A user-defined object that will be passed to the callback delegate. </param>
 /// <returns>An <see cref="IAsyncResult"/> that references the asynchronous operation. </returns>
 public IAsyncResult BeginSaveChangesWithRetries(
     SaveChangesOptions options, AsyncCallback callback, object state)
 {
     return
         TaskImplHelper.BeginImplWithRetry<DataServiceResponse>(
             setResult => this.SaveChangesWithRetriesImpl(options, setResult),
             this.RetryPolicy,
             callback,
             state);
 }
Пример #59
0
 /// <summary>
 /// constructor for BatchSaveResult
 /// </summary>
 /// <param name="context">context</param>
 /// <param name="method">method</param>
 /// <param name="queries">queries</param>
 /// <param name="options">options</param>
 /// <param name="callback">user callback</param>
 /// <param name="state">user state object</param>
 internal BatchSaveResult(DataServiceContext context, string method, DataServiceRequest[] queries, SaveChangesOptions options, AsyncCallback callback, object state)
     : base(context, method, queries, options, callback, state)
 {
     Debug.Assert(Util.IsBatch(options), "the options must have batch  flag set");
     this.Queries          = queries;
     this.streamCopyBuffer = new byte[StreamCopyBufferSize];
 }
 /// <summary>Saves changes, using the retry policy specified for the service context.</summary>
 /// <param name="options">Additional options for saving changes. </param>
 /// <returns>A <see cref="DataServiceResponse"/> that represents the result of the operation. </returns>
 public DataServiceResponse SaveChangesWithRetries(SaveChangesOptions options)
 {
     return
         TaskImplHelper.ExecuteImplWithRetry<DataServiceResponse>(
             setResult => this.SaveChangesWithRetriesImpl(options, setResult), this.RetryPolicy);
 }