Home > OS >  Calling cosmos DB stored procedure in Azure Function
Calling cosmos DB stored procedure in Azure Function

Time:10-04

I have a stored procedure in Azure Cosmos DB that will delete record from my Cosmos DB. I tried to call that stored procedure from my Azure function, but I am getting an error related to json parsing when executing the stored procedure (client.ExecuteStoredProcedureAsync). I already tried changing the partition key to "id" but I still get the same error.

Here is the error message that I got:

"Failed to deserialize stored procedure response or convert it to type 'System.String': Unexpected character encountered while parsing value: {. Path '', line 1, position 1."

Stack trace

at Microsoft.Azure.Documents.Client.StoredProcedureResponse1..ctor(DocumentServiceResponse response, JsonSerializerSettings serializerSettings)\r\n at Microsoft.Azure.Documents.Client.DocumentClient.ExecuteStoredProcedurePrivateAsync[TValue](String storedProcedureLink, RequestOptions options, IDocumentClientRetryPolicy retryPolicyInstance, CancellationToken cancellationToken, Object[] procedureParams)\r\n at Microsoft.Azure.Documents.BackoffRetryUtility1.ExecuteRetryAsync(Func1 callbackMethod, Func3 callShouldRetry, Func1 inBackoffAlternateCallbackMethod, TimeSpan minBackoffForInBackoffCallback, CancellationToken cancellationToken, Action1 preRetryCallback)\r\n at Microsoft.Azure.Documents.ShouldRetryResult.ThrowIfDoneTrying(ExceptionDispatchInfo capturedException)\r\n at Microsoft.Azure.Documents.BackoffRetryUtility1.ExecuteRetryAsync(Func1 callbackMethod, Func3 callShouldRetry, Func1 inBackoffAlternateCallbackMethod, TimeSpan minBackoffForInBackoffCallback, CancellationToken cancellatio nToken, Action1 preRetryCallback)\r\n at FunctionApp2.Function1.Run(HttpRequest req, IAsyncCollector1 documentsOut, ILogger log) in C:\Users\source\repos\FunctionApp2\FunctionApp2\Function1.cs:line 36"

Stored procedure deleteStoreSample:

function bulkDeleteProcedure() {
    var collection = getContext().getCollection();
    var collectionLink = collection.getSelfLink();
    var response = getContext().getResponse();
    var responseBody = {
        deleted: 0,
        continuation: true
    }; 

    query = 'SELECT * FROM c WHERE c.submittedDate > "2002-08-31"';

    // Validate input.
    if (!query) 
         throw new Error("The query is undefined or null.");

    tryQueryAndDelete();

    // Recursively runs the query w/ support for continuation  tokens.
    // Calls tryDelete(documents) as soon as the query returns documents.
    function tryQueryAndDelete(continuation) {
        var requestOptions = {continuation: continuation};

        var isAccepted = collection.queryDocuments(collectionLink, query, requestOptions, function (err, retrievedDocs, responseOptions) {

        if (err) 
            throw err;

        if (retrievedDocs.length > 0) {
            // Begin deleting documents as soon as documents are returned form the query results.
            // tryDelete() resumes querying after deleting; no need to page through continuation tokens.
            //  - this is to prioritize writes over reads given timeout constraints.
            tryDelete(retrievedDocs);
        } else if (responseOptions.continuation) {
            // Else if the query came back empty, but with a continuation token; repeat the query w/ the token.
            tryQueryAndDelete(responseOptions.continuation);
        } else {
            // Else if there are no more documents and no continuation token - we are finished deleting documents.
            responseBody.continuation = false;
            response.setBody(responseBody);
        }
    });

    // If we hit execution bounds - return continuation: true.
    if (!isAccepted) {
        response.setBody(responseBody);
    }
}

// Recursively deletes documents passed in as an array argument.
// Attempts to query for more on empty array.
function tryDelete(documents) {
    if (documents.length > 0) {
        // Delete the first document in the array.
        var isAccepted = collection.deleteDocument(documents[0]._self, {}, function (err, responseOptions) {
            if (err) throw err;

            responseBody.deleted  ;
            documents.shift();
            // Delete the next document in the array.
            tryDelete(documents);
        });

        // If we hit execution bounds - return continuation: true.
        if (!isAccepted) {
            response.setBody(responseBody);
        }
    } else {
        // If the document array is empty, query for more documents.
        tryQueryAndDelete();
    }
}

Azure function:

[FunctionName("Function1")]
public static async Task<IActionResult> Run(
        [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
         [CosmosDB(
    databaseName: "dbName",
    collectionName: "collectionName",
    ConnectionStringSetting = "CosmosDbConnectionString")]IAsyncCollector<dynamic> documentsOut,
        ILogger log)
{
    try
    {
        log.LogInformation("C# HTTP trigger function processed a request.");

        string endpoint = "https://account.documents.azure.com:443/";
        string key = "gixxxx==";

        var client = new DocumentClient(new Uri(endpoint), key);

        Uri uri = UriFactory.CreateStoredProcedureUri("service-order", "ServiceOrder", "deleteStoreSample");
        RequestOptions options = new RequestOptions { PartitionKey = new PartitionKey("/id") };

        var result = await client.ExecuteStoredProcedureAsync<string>(uri, options);

        var response = result.Response;

        return new OkObjectResult(response);
    }
    catch (Exception ex)
    {
        throw ex;
    }
}

CodePudding user response:

I believe the issue is with the following line of code:

RequestOptions options = new RequestOptions { PartitionKey = new PartitionKey("/id") };

You actually need to specify the value of the partition key here and not the attribute name.

Please try changing it to something like:

RequestOptions options = new RequestOptions { PartitionKey = new PartitionKey("partition-key-value") };// Replace "partition-key-value" with actual value
  • Related