public async Task <UpsertOutcome> UpsertAsync(ResourceWrapper resource, WeakETag weakETag, bool allowCreate, bool keepHistory, CancellationToken cancellationToken) { int?eTag = weakETag == null ? (int?)null : (int.TryParse(weakETag.VersionId, out var parsedETag) ? parsedETag : -1); // Set the etag to a sentinel value to enable expected failure paths when updating with both existing and nonexistent resources. var resourceMetadata = new ResourceMetadata( resource.CompartmentIndices, resource.SearchIndices?.ToLookup(e => _searchParameterTypeMap.GetSearchValueType(e)), resource.LastModifiedClaims); using (SqlConnectionWrapper sqlConnectionWrapper = await _sqlConnectionWrapperFactory.ObtainSqlConnectionWrapperAsync(cancellationToken, true)) using (SqlCommandWrapper sqlCommandWrapper = sqlConnectionWrapper.CreateSqlCommand()) using (var stream = new RecyclableMemoryStream(_memoryStreamManager)) { CompressedRawResourceConverter.WriteCompressedRawResource(stream, resource.RawResource.Data); stream.Seek(0, 0); PopulateUpsertResourceCommand(sqlCommandWrapper, resource, resourceMetadata, allowCreate, keepHistory, eTag, stream); try { var newVersion = (int?)await sqlCommandWrapper.ExecuteScalarAsync(cancellationToken); if (newVersion == null) { // indicates a redundant delete return(null); } resource.Version = newVersion.ToString(); return(new UpsertOutcome(resource, newVersion == 1 ? SaveOutcomeType.Created : SaveOutcomeType.Updated)); } catch (SqlException e) { switch (e.Number) { case SqlErrorCodes.PreconditionFailed: throw new PreconditionFailedException(string.Format(Core.Resources.ResourceVersionConflict, weakETag?.VersionId)); case SqlErrorCodes.NotFound: if (weakETag != null) { throw new ResourceNotFoundException(string.Format(Core.Resources.ResourceNotFoundByIdAndVersion, resource.ResourceTypeName, resource.ResourceId, weakETag.VersionId)); } goto default; case SqlErrorCodes.MethodNotAllowed: throw new MethodNotAllowedException(Core.Resources.ResourceCreationNotAllowed); default: _logger.LogError(e, "Error from SQL database on upsert"); throw; } } } }
public async Task <UpsertOutcome> UpsertAsync(ResourceWrapper resource, WeakETag weakETag, bool allowCreate, bool keepHistory, CancellationToken cancellationToken) { await _model.EnsureInitialized(); int etag = 0; if (weakETag != null && !int.TryParse(weakETag.VersionId, out etag)) { throw new ResourceConflictException(weakETag); } var resourceMetadata = new ResourceMetadata( resource.CompartmentIndices, resource.SearchIndices?.ToLookup(e => _searchParameterTypeMap.GetSearchValueType(e)), resource.LastModifiedClaims); using (var connection = new SqlConnection(_configuration.ConnectionString)) { await connection.OpenAsync(cancellationToken); using (var command = connection.CreateCommand()) using (var stream = new RecyclableMemoryStream(_memoryStreamManager)) using (var gzipStream = new GZipStream(stream, CompressionMode.Compress)) using (var writer = new StreamWriter(gzipStream, ResourceEncoding)) { writer.Write(resource.RawResource.Data); writer.Flush(); stream.Seek(0, 0); V1.UpsertResource.PopulateCommand( command, resourceTypeId: _model.GetResourceTypeId(resource.ResourceTypeName), resourceId: resource.ResourceId, eTag: weakETag == null ? null : (int?)etag, allowCreate: allowCreate, isDeleted: resource.IsDeleted, updatedDateTime: resource.LastModified, keepHistory: keepHistory, requestMethod: resource.Request.Method, rawResource: stream, tableValuedParameters: _upsertResourceTvpGenerator.Generate(resourceMetadata)); try { var newVersion = (int?)await command.ExecuteScalarAsync(cancellationToken); if (newVersion == null) { // indicates a redundant delete return(null); } resource.Version = newVersion.ToString(); return(new UpsertOutcome(resource, newVersion == 1 ? SaveOutcomeType.Created : SaveOutcomeType.Updated)); } catch (SqlException e) { switch (e.Number) { case SqlErrorCodes.NotFound: throw new MethodNotAllowedException(Resources.ResourceCreationNotAllowed); case SqlErrorCodes.PreconditionFailed: throw new ResourceConflictException(weakETag); default: _logger.LogError(e, "Error from SQL database on upsert"); throw; } } } } }
public async Task <UpsertOutcome> UpsertAsync(ResourceWrapper resource, WeakETag weakETag, bool allowCreate, bool keepHistory, CancellationToken cancellationToken) { await _model.EnsureInitialized(); int etag = 0; if (weakETag != null && !int.TryParse(weakETag.VersionId, out etag)) { throw new ResourceConflictException(weakETag); } var resourceMetadata = new ResourceMetadata( resource.CompartmentIndices, resource.SearchIndices?.ToLookup(e => _searchParameterTypeMap.GetSearchValueType(e)), resource.LastModifiedClaims); // Insert an Observation record to CDS DynamicsCrmFhirDataStore crmFhirDataStoreObj = new DynamicsCrmFhirDataStore(); try { // Dynamics Crm code // write to Cds crmFhirDataStoreObj.PutCdsObservationData(resource.RawResource.Data); } catch (Exception ex) { Console.WriteLine(ex); return(null); } // Gets all data(top 20) from CDS var cdsObservationData = crmFhirDataStoreObj.GetCdsObservationData("all"); // Store above inserted data to blob string storageConnection = "DefaultEndpointsProtocol=https;AccountName=clusterstudiostorage;AccountKey=0WY56Pft4WN3GIUfjhGGpGMewvtUO55AMULDOiCj/s1IviuEd4kMbHNYi83mgnZm/N6ZGShdpot0i44uDMJgNA==;EndpointSuffix=core.windows.net"; CloudStorageAccount cloudStorageAccount = CloudStorageAccount.Parse(storageConnection); CloudBlobClient blobClient = cloudStorageAccount.CreateCloudBlobClient(); CloudBlobContainer blobContainer = blobClient.GetContainerReference("database"); blobContainer.CreateIfNotExists(); string errorBlobName = "CDSData/" + System.DateTime.Now.ToString("yyyy-MM-dd-hh-mm") + "_a.Json"; var exceptionblob = blobContainer.GetBlockBlobReference(errorBlobName); exceptionblob.UploadTextAsync(cdsObservationData.ToString()).GetAwaiter().GetResult(); // search with a particulara record for example records with cold var cdsObservationSearchData = crmFhirDataStoreObj.GetCdsObservationData("cold"); // Store above searched data to blob blobContainer.CreateIfNotExists(); string searchBlobName = "CDSData/" + System.DateTime.Now.ToString("yyyy-MM-dd-hh-mm") + "_s.Json"; var searchBlob = blobContainer.GetBlockBlobReference(searchBlobName); searchBlob.UploadTextAsync(cdsObservationSearchData.ToString()).GetAwaiter().GetResult(); using (var connection = new SqlConnection(_configuration.ConnectionString)) { await connection.OpenAsync(cancellationToken); using (var command = connection.CreateCommand()) using (var stream = new RecyclableMemoryStream(_memoryStreamManager)) using (var gzipStream = new GZipStream(stream, CompressionMode.Compress)) using (var writer = new StreamWriter(gzipStream, ResourceEncoding)) { writer.Write(resource.RawResource.Data); writer.Flush(); stream.Seek(0, 0); V1.UpsertResource.PopulateCommand( command, baseResourceSurrogateId: ResourceSurrogateIdHelper.LastUpdatedToResourceSurrogateId(resource.LastModified.UtcDateTime), resourceTypeId: _model.GetResourceTypeId(resource.ResourceTypeName), resourceId: resource.ResourceId, eTag: weakETag == null ? null : (int?)etag, allowCreate: allowCreate, isDeleted: resource.IsDeleted, keepHistory: keepHistory, requestMethod: resource.Request.Method, rawResource: stream, tableValuedParameters: _upsertResourceTvpGenerator.Generate(resourceMetadata)); try { var newVersion = (int?)await command.ExecuteScalarAsync(cancellationToken); if (newVersion == null) { // indicates a redundant delete return(null); } resource.Version = newVersion.ToString(); return(new UpsertOutcome(resource, newVersion == 1 ? SaveOutcomeType.Created : SaveOutcomeType.Updated)); } catch (SqlException e) { switch (e.Number) { case SqlErrorCodes.NotFound: throw new MethodNotAllowedException(Core.Resources.ResourceCreationNotAllowed); case SqlErrorCodes.PreconditionFailed: throw new ResourceConflictException(weakETag); default: _logger.LogError(e, "Error from SQL database on upsert"); throw; } } } } }
public async Task <UpsertOutcome> UpsertAsync(ResourceWrapper resource, WeakETag weakETag, bool allowCreate, bool keepHistory, CancellationToken cancellationToken) { int etag = 0; if (weakETag != null && !int.TryParse(weakETag.VersionId, out etag)) { // Set the etag to a sentinel value to enable expected failure paths when updating with both existing and nonexistent resources. etag = -1; } var resourceMetadata = new ResourceMetadata( resource.CompartmentIndices, resource.SearchIndices?.ToLookup(e => _searchParameterTypeMap.GetSearchValueType(e)), resource.LastModifiedClaims); using (SqlConnectionWrapper sqlConnectionWrapper = _sqlConnectionWrapperFactory.ObtainSqlConnectionWrapper(true)) using (SqlCommandWrapper sqlCommandWrapper = sqlConnectionWrapper.CreateSqlCommand()) using (var stream = new RecyclableMemoryStream(_memoryStreamManager)) using (var gzipStream = new GZipStream(stream, CompressionMode.Compress)) using (var writer = new StreamWriter(gzipStream, ResourceEncoding)) { writer.Write(resource.RawResource.Data); writer.Flush(); stream.Seek(0, 0); VLatest.UpsertResource.PopulateCommand( sqlCommandWrapper, baseResourceSurrogateId: ResourceSurrogateIdHelper.LastUpdatedToResourceSurrogateId(resource.LastModified.UtcDateTime), resourceTypeId: _model.GetResourceTypeId(resource.ResourceTypeName), resourceId: resource.ResourceId, eTag: weakETag == null ? null : (int?)etag, allowCreate: allowCreate, isDeleted: resource.IsDeleted, keepHistory: keepHistory, requestMethod: resource.Request.Method, rawResource: stream, tableValuedParameters: _upsertResourceTvpGeneratorVLatest.Generate(resourceMetadata)); try { var newVersion = (int?)await sqlCommandWrapper.ExecuteScalarAsync(cancellationToken); if (newVersion == null) { // indicates a redundant delete return(null); } resource.Version = newVersion.ToString(); return(new UpsertOutcome(resource, newVersion == 1 ? SaveOutcomeType.Created : SaveOutcomeType.Updated)); } catch (SqlException e) { switch (e.Number) { case SqlErrorCodes.PreconditionFailed: throw new PreconditionFailedException(string.Format(Core.Resources.ResourceVersionConflict, weakETag?.VersionId)); case SqlErrorCodes.NotFound: if (weakETag != null) { throw new ResourceNotFoundException(string.Format(Core.Resources.ResourceNotFoundByIdAndVersion, resource.ResourceTypeName, resource.ResourceId, weakETag.VersionId)); } goto default; case SqlErrorCodes.MethodNotAllowed: throw new MethodNotAllowedException(Core.Resources.ResourceCreationNotAllowed); default: _logger.LogError(e, "Error from SQL database on upsert"); throw; } } } }
public async Task <UpsertOutcome> UpsertAsync( ResourceWrapper resource, WeakETag weakETag, bool allowCreate, bool keepHistory, CancellationToken cancellationToken, bool requireETagOnUpdate = false) { int?eTag = weakETag == null ? null : (int.TryParse(weakETag.VersionId, out var parsedETag) ? parsedETag : -1); // Set the etag to a sentinel value to enable expected failure paths when updating with both existing and nonexistent resources. var resourceMetadata = new ResourceMetadata( resource.CompartmentIndices, resource.SearchIndices?.ToLookup(e => _searchParameterTypeMap.GetSearchValueType(e)), resource.LastModifiedClaims); using (SqlConnectionWrapper sqlConnectionWrapper = await _sqlConnectionWrapperFactory.ObtainSqlConnectionWrapperAsync(cancellationToken, true)) using (SqlCommandWrapper sqlCommandWrapper = sqlConnectionWrapper.CreateSqlCommand()) using (var stream = new RecyclableMemoryStream(_memoryStreamManager)) { _compressedRawResourceConverter.WriteCompressedRawResource(stream, resource.RawResource.Data); stream.Seek(0, 0); PopulateUpsertResourceCommand(sqlCommandWrapper, resource, resourceMetadata, allowCreate, keepHistory, requireETagOnUpdate, eTag, stream, _coreFeatures.SupportsResourceChangeCapture); try { var newVersion = (int?)await sqlCommandWrapper.ExecuteScalarAsync(cancellationToken); if (newVersion == null) { // indicates a redundant delete return(null); } resource.Version = newVersion.ToString(); SaveOutcomeType saveOutcomeType; if (newVersion == 1) { saveOutcomeType = SaveOutcomeType.Created; } else { saveOutcomeType = SaveOutcomeType.Updated; resource.RawResource.IsMetaSet = false; } return(new UpsertOutcome(resource, saveOutcomeType)); } catch (SqlException e) { switch (e.Number) { case SqlErrorCodes.PreconditionFailed: if (weakETag != null) { // The backwards compatibility behavior of Stu3 is to return 409 Conflict instead of a 412 Precondition Failed if (_modelInfoProvider.Version == FhirSpecification.Stu3) { throw new ResourceConflictException(weakETag); } throw new PreconditionFailedException(string.Format(Core.Resources.ResourceVersionConflict, weakETag.VersionId)); } goto default; case SqlErrorCodes.NotFound: if (weakETag != null) { throw new ResourceNotFoundException(string.Format(Core.Resources.ResourceNotFoundByIdAndVersion, resource.ResourceTypeName, resource.ResourceId, weakETag.VersionId)); } goto default; case SqlErrorCodes.MethodNotAllowed: throw new MethodNotAllowedException(Core.Resources.ResourceCreationNotAllowed); case SqlErrorCodes.TimeoutExpired: throw new RequestTimeoutException(Resources.ExecutionTimeoutExpired); case 50400: // TODO: Add this to SQL error codes in AB#88286 // The backwards compatibility behavior of Stu3 is to return 412 Precondition Failed instead of a 400 Bad Request if (_modelInfoProvider.Version == FhirSpecification.Stu3) { throw new PreconditionFailedException(string.Format(Core.Resources.IfMatchHeaderRequiredForResource, resource.ResourceTypeName)); } throw new BadRequestException(string.Format(Core.Resources.IfMatchHeaderRequiredForResource, resource.ResourceTypeName)); default: _logger.LogError(e, "Error from SQL database on upsert"); throw; } } } }