private async Task <TableResult> HandleInsertOrMergeAsync(
            TableOperation operation,
            CloudTableClient client,
            CloudTable table,
            TableRequestOptions options,
            OperationContext context)
        {
            Document document = EntityHelpers.GetDocumentFromEntity(operation.Entity, context, options);

            try
            {
                ResourceResponse <Document> response = await client.DocumentClient.CreateDocumentAsync(table.GetCollectionUri(), document);

                context.RequestResults.Add(response.ToRequestResult());
                return(this.GetTableResultFromResponse(operation, response, context, options));
            }
            catch (DocumentClientException exception)
            {
                if (exception.StatusCode != HttpStatusCode.Conflict)
                {
                    throw;
                }
            }

            return(await this.HandleMergeAsync(operation, client, table, options, context));
        }
        private async Task <TableResult> HandleMergeAsync(TableOperation operation, CloudTableClient client, CloudTable table, TableRequestOptions options, OperationContext context)
        {
            ResourceResponse <Document> readResponse = await client.DocumentClient.ReadDocumentAsync(
                UriFactory.CreateDocumentUri(StellarConstants.TableDatabaseName, table.Name, operation.Entity.RowKey),
                new RequestOptions { PartitionKey = new PartitionKey(operation.Entity.PartitionKey) });

            Document mergedDocument = readResponse.Resource;
            Document newDocument    = EntityHelpers.GetDocumentFromEntity(operation.Entity, context, options);

            foreach (KeyValuePair <string, EntityProperty> property in operation.Entity.WriteEntity(context))
            {
                mergedDocument.SetPropertyValue(property.Key, newDocument.GetPropertyValue <object>(property.Key));
            }

            ResourceResponse <Document> updateResponse = await client.DocumentClient.ReplaceDocumentAsync(
                mergedDocument,
                new RequestOptions
            {
                AccessCondition =
                    new Microsoft.Azure.Documents.Client.AccessCondition
                {
                    Type      = AccessConditionType.IfMatch,
                    Condition = readResponse.Resource.ETag
                }
            });

            context.RequestResults.Add(updateResponse.ToRequestResult());
            return(this.GetTableResultFromResponse(operation, updateResponse, context, options));
        }
        private async Task <TableResult> HandleUpsertAsync(TableOperation operation, CloudTableClient client, CloudTable table, TableRequestOptions options, OperationContext context)
        {
            Document document = EntityHelpers.GetDocumentFromEntity(operation.Entity, context, options);
            ResourceResponse <Document> response = await client.DocumentClient.UpsertDocumentAsync(table.GetCollectionUri(), document);

            context.RequestResults.Add(response.ToRequestResult());
            return(this.GetTableResultFromResponse(operation, response, context, options));
        }
        private async Task <TableResult> HandleReplaceAsync(TableOperation operation, CloudTableClient client, CloudTable table, TableRequestOptions options, OperationContext context)
        {
            Document       document       = EntityHelpers.GetDocumentFromEntity(operation.Entity, context, options);
            RequestOptions requestOptions = null;
            Uri            documentUri    = this.GetDocumentUri(operation, table, out requestOptions);

            if (!string.IsNullOrEmpty(operation.Entity.ETag))
            {
                requestOptions.AccessCondition = new Microsoft.Azure.Documents.Client.AccessCondition {
                    Type = AccessConditionType.IfMatch, Condition = operation.Entity.ETag
                };
            }

            ResourceResponse <Document> response = await client.DocumentClient.ReplaceDocumentAsync(documentUri, document, requestOptions);

            context.RequestResults.Add(response.ToRequestResult());
            return(this.GetTableResultFromResponse(operation, response, context, options));
        }
        private async Task <TableResult> HandleInsertAsync(TableOperation operation, CloudTableClient client, CloudTable table, TableRequestOptions options, OperationContext context)
        {
            if (operation.IsTableEntity)
            {
                await client.DocumentClient.CreateDatabaseIfNotExistsAsync(new Database { Id = StellarConstants.TableDatabaseName });

                string collectionName = ((DynamicTableEntity)operation.Entity).Properties[TableConstants.TableName].StringValue;

                RequestOptions requestOptions     = null;
                string         collectionRUConfig = ConfigurationManager.AppSettings["DocumentDbCollectionRU"];
                int            collectionRU       = 0;
                if (!string.IsNullOrEmpty(collectionRUConfig) && int.TryParse(collectionRUConfig, out collectionRU))
                {
                    requestOptions = new RequestOptions {
                        OfferThroughput = collectionRU
                    };
                }

                ResourceResponse <DocumentCollection> response
                    = await client.DocumentClient.CreateDocumentCollectionAsync(
                          UriFactory.CreateDatabaseUri(StellarConstants.TableDatabaseName),
                          new DocumentCollection
                {
                    Id           = collectionName,
                    PartitionKey = new PartitionKeyDefinition()
                    {
                        Paths = { "/" + StellarConstants.PartitionKeyPropertyName }
                    },
                }, requestOptions);

                context.RequestResults.Add(response.ToRequestResult());
                return(EntityHelpers.GetTableResultFromResponse(response, context));
            }
            else
            {
                Document document = EntityHelpers.GetDocumentFromEntity(operation.Entity, context, options);

                ResourceResponse <Document> response = await client.DocumentClient.CreateDocumentAsync(table.GetCollectionUri(), document);

                context.RequestResults.Add(response.ToRequestResult());
                return(this.GetTableResultFromResponse(operation, response, context, options));
            }
        }
        private async Task <TableResult> HandleDeleteAsync(TableOperation operation, CloudTableClient client, CloudTable table, TableRequestOptions options, OperationContext context)
        {
            if (operation.IsTableEntity)
            {
                string collectionName        = ((DynamicTableEntity)operation.Entity).Properties[TableConstants.TableName].StringValue;
                Uri    documentCollectionUri = UriFactory.CreateDocumentCollectionUri(StellarConstants.TableDatabaseName, collectionName);
                ResourceResponse <DocumentCollection> response = await client.DocumentClient.DeleteDocumentCollectionAsync(documentCollectionUri);

                context.RequestResults.Add(response.ToRequestResult());
                return(EntityHelpers.GetTableResultFromResponse(response, context));
            }
            else
            {
                RequestOptions requestOptions;
                Uri            documentUri           = this.GetDocumentUri(operation, table, out requestOptions);
                ResourceResponse <Document> response = await client.DocumentClient.DeleteDocumentAsync(documentUri, requestOptions);

                context.RequestResults.Add(response.ToRequestResult());
                return(this.GetTableResultFromResponse(operation, response, context, options));
            }
        }
        private async Task <TableResult> HandleReadAsync(TableOperation operation, CloudTableClient client, CloudTable table, TableRequestOptions options, OperationContext context)
        {
            try
            {
                if (operation.IsTableEntity)
                {
                    //TODO:  Why do we get the collection name from the Entity instead of the table
                    string collectionName        = ((DynamicTableEntity)operation.Entity).Properties[TableConstants.TableName].StringValue;
                    Uri    documentCollectionUri = UriFactory.CreateDocumentCollectionUri(StellarConstants.TableDatabaseName, collectionName);
                    ResourceResponse <DocumentCollection> response = await client.DocumentClient.ReadDocumentCollectionAsync(documentCollectionUri);

                    context.RequestResults.Add(response.ToRequestResult());
                    return(EntityHelpers.GetTableResultFromResponse(response, context));
                }
                else
                {
                    RequestOptions requestOptions;
                    Uri            documentUri = this.GetDocumentUri(operation, table, out requestOptions);

                    ResourceResponse <Document> response = await client.DocumentClient.ReadDocumentAsync(documentUri, requestOptions);

                    context.RequestResults.Add(response.ToRequestResult());
                    return(this.GetTableResultFromResponse(operation, response, context, options));
                }
            }
            catch (DocumentClientException exception)
            {
                if (exception.StatusCode == HttpStatusCode.NotFound)
                {
                    return(new TableResult
                    {
                        HttpStatusCode = (int)HttpStatusCode.NotFound
                    });
                }

                throw;
            }
        }