public async Task <ContainerResponse> CreateContainerIfNotExistsAsync( 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( 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 PREVIEW 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( 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( requestOptions: requestOptions, trace: trace, cancellationToken: cancellationToken)) { totalRequestCharge += readResponseAfterCreate.Headers.RequestCharge; readResponseAfterCreate.Headers.RequestCharge = totalRequestCharge; return(this.ClientContext.ResponseFactory.CreateContainerResponse(container, readResponseAfterCreate)); } }
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)); } }