Пример #1
0
        private async Task LoadOperationItem(MobileServiceTableOperation operation, OperationBatch batch)
        {
            // only read the item from store if it is not in the operation already
            if (operation.Item == null)
            {
                await TryStoreOperation(async() =>
                {
                    operation.Item = await this.Store.LookupAsync(operation.TableName, operation.ItemId) as JObject;
                }, batch, "Failed to read the item from local store.");

                // Add sync error if item is not found.
                if (operation.Item == null)
                {
                    // Create an item with only id to be able handle error properly.
                    var item      = new JObject(new JProperty(MobileServiceSystemColumns.Id, operation.ItemId));
                    var syncError = new MobileServiceTableOperationError(operation.Id,
                                                                         operation.Version,
                                                                         operation.Kind,
                                                                         null,
                                                                         operation.TableName,
                                                                         item, null, null)
                    {
                        TableKind = this.tableKind,
                        Context   = this.context
                    };
                    await batch.AddSyncErrorAsync(syncError);
                }
            }
        }
        private async Task<bool> ExecuteOperationAsync(MobileServiceTableOperation operation, OperationBatch batch)
        {
            if (operation.IsCancelled || this.CancellationToken.IsCancellationRequested)
            {
                return false;
            }

            operation.Table = await this.context.GetTable(operation.TableName, this.client);

            await this.LoadOperationItem(operation, batch);

            if (this.CancellationToken.IsCancellationRequested)
            {
                return false;
            }

            await TryUpdateOperationState(operation, MobileServiceTableOperationState.Attempted, batch);

            // strip out system properties before executing the operation
            operation.Item = MobileServiceSyncTable.RemoveSystemPropertiesKeepVersion(operation.Item);

            JObject result = null;
            Exception error = null;
            try
            {
                result = await batch.SyncHandler.ExecuteTableOperationAsync(operation);
            }
            catch (Exception ex)
            {
                error = ex;
            }

            if (error != null)
            {
                await TryUpdateOperationState(operation, MobileServiceTableOperationState.Failed, batch);

                if (TryAbortBatch(batch, error))
                {
                    // there is no error to save in sync error and no result to capture
                    // this operation will be executed again next time the push happens
                    return false;
                }
            }

            // save the result if ExecuteTableOperation did not throw
            if (error == null && result.IsValidItem() && operation.CanWriteResultToStore)
            {
                await TryStoreOperation(() => this.Store.UpsertAsync(operation.TableName, result, fromServer: true), batch, "Failed to update the item in the local store.");
            }
            else if (error != null)
            {
                HttpStatusCode? statusCode = null;
                string rawResult = null;
                var iox = error as MobileServiceInvalidOperationException;
                if (iox != null && iox.Response != null)
                {
                    statusCode = iox.Response.StatusCode;
                    Tuple<string, JToken> content = await MobileServiceTable.ParseContent(iox.Response, this.client.SerializerSettings);
                    rawResult = content.Item1;
                    result = content.Item2.ValidItemOrNull();
                }
                var syncError = new MobileServiceTableOperationError(operation.Id,
                                                                        operation.Version,
                                                                        operation.Kind,
                                                                        statusCode,
                                                                        operation.TableName,
                                                                        operation.Item,
                                                                        rawResult,
                                                                        result)
                                                                        {
                                                                            TableKind = this.tableKind,
                                                                            Context = this.context
                                                                        };
                await batch.AddSyncErrorAsync(syncError);
            }

            bool success = error == null;
            return success;
        }
        private async Task <bool> ExecuteOperationAsync(MobileServiceTableOperation operation, OperationBatch batch)
        {
            if (operation.IsCancelled || this.CancellationToken.IsCancellationRequested)
            {
                return(false);
            }

            operation.Table = await this.context.GetTable(operation.TableName, this.client);

            await this.LoadOperationItem(operation, batch);

            if (this.CancellationToken.IsCancellationRequested)
            {
                return(false);
            }

            await TryUpdateOperationState(operation, MobileServiceTableOperationState.Attempted, batch);

            // strip out system properties before executing the operation
            operation.Item = MobileServiceSyncTable.RemoveSystemPropertiesKeepVersion(operation.Item);

            JObject   result = null;
            Exception error  = null;

            try
            {
                result = await batch.SyncHandler.ExecuteTableOperationAsync(operation);
            }
            catch (Exception ex)
            {
                error = ex;
            }

            if (error != null)
            {
                await TryUpdateOperationState(operation, MobileServiceTableOperationState.Failed, batch);

                if (TryAbortBatch(batch, error))
                {
                    // there is no error to save in sync error and no result to capture
                    // this operation will be executed again next time the push happens
                    return(false);
                }
            }

            // save the result if ExecuteTableOperation did not throw
            if (error == null && result.IsValidItem() && operation.CanWriteResultToStore)
            {
                await TryStoreOperation(() => this.Store.UpsertAsync(operation.TableName, result, fromServer: true), batch, "Failed to update the item in the local store.");
            }
            else if (error != null)
            {
                HttpStatusCode?statusCode = null;
                string         rawResult  = null;
                var            iox        = error as MobileServiceInvalidOperationException;
                if (iox != null && iox.Response != null)
                {
                    statusCode = iox.Response.StatusCode;
                    Tuple <string, JToken> content = await MobileServiceTable.ParseContent(iox.Response, this.client.SerializerSettings);

                    rawResult = content.Item1;
                    result    = content.Item2.ValidItemOrNull();
                }
                var syncError = new MobileServiceTableOperationError(operation.Id,
                                                                     operation.Version,
                                                                     operation.Kind,
                                                                     statusCode,
                                                                     operation.TableName,
                                                                     operation.Item,
                                                                     rawResult,
                                                                     result)
                {
                    TableKind = this.tableKind,
                    Context   = this.context
                };
                await batch.AddSyncErrorAsync(syncError);
            }

            bool success = error == null;

            return(success);
        }