Beispiel #1
0
        public async Task <ContainerResponse> CreateContainerIfNotExistsAsync(
            CosmosDiagnosticsContext diagnosticsContext,
            ContainerProperties containerProperties,
            ThroughputProperties throughputProperties,
            RequestOptions requestOptions,
            CancellationToken cancellationToken)
        {
            if (containerProperties == null)
            {
                throw new ArgumentNullException(nameof(containerProperties));
            }

            this.ValidateContainerProperties(containerProperties);

            ContainerCore container = (ContainerCore)this.GetContainer(containerProperties.Id);

            using (ResponseMessage readResponse = await container.ReadContainerStreamAsync(
                       diagnosticsContext: diagnosticsContext,
                       cancellationToken: cancellationToken))
            {
                if (readResponse.StatusCode != HttpStatusCode.NotFound)
                {
                    ContainerResponse retrivedContainerResponse = this.ClientContext.ResponseFactory.CreateContainerResponse(
                        container,
                        readResponse);
                    if (!retrivedContainerResponse.Resource.PartitionKeyPath.Equals(containerProperties.PartitionKeyPath))
                    {
                        throw new ArgumentException(
                                  string.Format(
                                      ClientResources.PartitionKeyPathConflict,
                                      containerProperties.PartitionKeyPath,
                                      containerProperties.Id,
                                      retrivedContainerResponse.Resource.PartitionKeyPath),
                                  nameof(containerProperties.PartitionKey));
                    }

                    return(retrivedContainerResponse);
                }
            }

            this.ValidateContainerProperties(containerProperties);
            using (ResponseMessage createResponse = await this.CreateContainerStreamAsync(
                       diagnosticsContext,
                       containerProperties,
                       throughputProperties,
                       requestOptions,
                       cancellationToken))
            {
                if (createResponse.StatusCode != HttpStatusCode.Conflict)
                {
                    return(this.ClientContext.ResponseFactory.CreateContainerResponse(container, createResponse));
                }
            }

            // This second Read is to handle the race condition when 2 or more threads have Read the database and only one succeeds with Create
            // so for the remaining ones we should do a Read instead of throwing Conflict exception
            using (ResponseMessage readResponseAfterCreate = await container.ReadContainerStreamAsync(
                       diagnosticsContext: diagnosticsContext,
                       cancellationToken: cancellationToken))
            {
                return(this.ClientContext.ResponseFactory.CreateContainerResponse(container, readResponseAfterCreate));
            }
        }
        public async Task <ContainerResponse> CreateContainerIfNotExistsAsync(
            CosmosDiagnosticsContext diagnosticsContext,
            ContainerProperties containerProperties,
            ThroughputProperties throughputProperties,
            RequestOptions requestOptions,
            ITrace trace,
            CancellationToken cancellationToken)
        {
            if (containerProperties == null)
            {
                throw new ArgumentNullException(nameof(containerProperties));
            }

            this.ValidateContainerProperties(containerProperties);

            double        totalRequestCharge = 0;
            ContainerCore container          = (ContainerCore)this.GetContainer(containerProperties.Id);

            using (ResponseMessage readResponse = await container.ReadContainerStreamAsync(
                       diagnosticsContext: diagnosticsContext,
                       requestOptions: requestOptions,
                       trace: trace,
                       cancellationToken: cancellationToken))
            {
                totalRequestCharge = readResponse.Headers.RequestCharge;

                if (readResponse.StatusCode != HttpStatusCode.NotFound)
                {
                    ContainerResponse retrivedContainerResponse = this.ClientContext.ResponseFactory.CreateContainerResponse(
                        container,
                        readResponse);

                    if (containerProperties.PartitionKey.Kind != Documents.PartitionKind.MultiHash)
                    {
                        if (!retrivedContainerResponse.Resource.PartitionKeyPath.Equals(containerProperties.PartitionKeyPath))
                        {
                            throw new ArgumentException(
                                      string.Format(
                                          ClientResources.PartitionKeyPathConflict,
                                          containerProperties.PartitionKeyPath,
                                          containerProperties.Id,
                                          retrivedContainerResponse.Resource.PartitionKeyPath),
                                      nameof(containerProperties.PartitionKey));
                        }
                    }
#if INTERNAL || SUBPARTITIONING
                    else
                    {
                        IReadOnlyList <string> retrivedPartitionKeyPaths = retrivedContainerResponse.Resource.PartitionKeyPaths;
                        IReadOnlyList <string> receivedPartitionKeyPaths = containerProperties.PartitionKeyPaths;

                        if (retrivedPartitionKeyPaths.Count != receivedPartitionKeyPaths.Count || !Enumerable.SequenceEqual(retrivedPartitionKeyPaths, receivedPartitionKeyPaths))
                        {
                            throw new ArgumentException(
                                      string.Format(
                                          ClientResources.PartitionKeyPathConflict,
                                          string.Join(",", containerProperties.PartitionKeyPaths),
                                          containerProperties.Id,
                                          string.Join(",", retrivedContainerResponse.Resource.PartitionKeyPaths)),
                                      nameof(containerProperties.PartitionKey));
                        }
                    }
#endif
                    return(retrivedContainerResponse);
                }
            }

            this.ValidateContainerProperties(containerProperties);
            using (ResponseMessage createResponse = await this.CreateContainerStreamAsync(
                       diagnosticsContext,
                       containerProperties,
                       throughputProperties,
                       requestOptions,
                       trace,
                       cancellationToken))
            {
                totalRequestCharge += createResponse.Headers.RequestCharge;
                createResponse.Headers.RequestCharge = totalRequestCharge;

                if (createResponse.StatusCode != HttpStatusCode.Conflict)
                {
                    return(this.ClientContext.ResponseFactory.CreateContainerResponse(container, createResponse));
                }
            }

            // This second Read is to handle the race condition when 2 or more threads have Read the database and only one succeeds with Create
            // so for the remaining ones we should do a Read instead of throwing Conflict exception
            using (ResponseMessage readResponseAfterCreate = await container.ReadContainerStreamAsync(
                       diagnosticsContext: diagnosticsContext,
                       requestOptions: requestOptions,
                       trace: trace,
                       cancellationToken: cancellationToken))
            {
                totalRequestCharge += readResponseAfterCreate.Headers.RequestCharge;
                readResponseAfterCreate.Headers.RequestCharge = totalRequestCharge;

                return(this.ClientContext.ResponseFactory.CreateContainerResponse(container, readResponseAfterCreate));
            }
        }
        public override async Task <ContainerResponse> CreateContainerIfNotExistsAsync(
            ContainerProperties containerProperties,
            int?throughput = null,
            RequestOptions requestOptions       = null,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            if (containerProperties == null)
            {
                throw new ArgumentNullException(nameof(containerProperties));
            }

            this.ValidateContainerProperties(containerProperties);

            Container       container    = this.GetContainer(containerProperties.Id);
            ResponseMessage readResponse = await container.ReadContainerStreamAsync(
                cancellationToken : cancellationToken);

            if (readResponse.StatusCode != HttpStatusCode.NotFound)
            {
                ContainerResponse retrivedContainerResponse = await this.ClientContext.ResponseFactory.CreateContainerResponseAsync(
                    container,
                    Task.FromResult(readResponse));

                if (!retrivedContainerResponse.Resource.PartitionKeyPath.Equals(containerProperties.PartitionKeyPath))
                {
                    throw new ArgumentException(
                              string.Format(
                                  ClientResources.PartitionKeyPathConflict,
                                  containerProperties.PartitionKeyPath,
                                  containerProperties.Id,
                                  retrivedContainerResponse.Resource.PartitionKeyPath),
                              nameof(containerProperties.PartitionKey));
                }

                return(retrivedContainerResponse);
            }

            this.ValidateContainerProperties(containerProperties);
            ResponseMessage createResponse = await this.CreateContainerStreamAsync(
                containerProperties,
                throughput,
                requestOptions,
                cancellationToken);

            // Merge the previous message diagnostics
            createResponse.DiagnosticsContext.AddDiagnosticsInternal(readResponse.DiagnosticsContext);

            if (readResponse.StatusCode != HttpStatusCode.Conflict)
            {
                return(await this.ClientContext.ResponseFactory.CreateContainerResponseAsync(container, Task.FromResult(createResponse)));
            }

            // This second Read is to handle the race condition when 2 or more threads have Read the database and only one succeeds with Create
            // so for the remaining ones we should do a Read instead of throwing Conflict exception
            ResponseMessage readResponseAfterCreate = await container.ReadContainerStreamAsync(
                cancellationToken : cancellationToken);

            // Merge the previous message diagnostics
            createResponse.DiagnosticsContext.AddDiagnosticsInternal(readResponse.DiagnosticsContext);
            return(await this.ClientContext.ResponseFactory.CreateContainerResponseAsync(container, Task.FromResult(readResponseAfterCreate)));
        }