user1477388
user1477388

Reputation: 21440

Output Multiple Objects to CosmosDB with Azure Function (Isolated Process)

I cannot seem to find any documentation on how to output multiple documents to Azure CosmosDB from an Azure Function isolated process.

I understand "Because .NET isolated projects run in a separate worker process, bindings can't take advantage of rich binding classes, such as ICollector, IAsyncCollector, and CloudBlockBlob." Ref. https://learn.microsoft.com/en-us/azure/azure-functions/dotnet-isolated-process-guide#bindings

However, I am assuming there must still be a way to insert multiple records in a single execution of my timer function.

In the following code, I can easily insert a single record, but how can I adapt this code to insert an array or list of records?

I found this article but it doesn't seem to articulate how I can apply this code within the context of a timer function.

[Function("MyFunction")]
public async Task<MultiResponse> Run([TimerTrigger("0 */1 * * * *")] MyInfo myTimer)
{
    var result = await _dataService.GetData();

    return new MultiResponse()
    {
        Document = new MyDocument
        {
            id = System.Guid.NewGuid().ToString(),
            message = "hello world"
        }
    };
}
public class MultiResponse
{
    [CosmosDBOutput("MyDatabase", "MyCollection",
        ConnectionStringSetting = "CosmosDbConnectionString", CreateIfNotExists = true)]
    public MyDocument Document { get; set; }
}
public class MyDocument
{
    public string id { get; set; }
    public string message { get; set; }
}

Upvotes: 2

Views: 1301

Answers (2)

Peter Tuton
Peter Tuton

Reputation: 71

As per the documentation, to return multiple documents return "T[] where T is JSON serializable type".

So, to adapt your code, return an array of MyDocument JSON serializable objects, as follows:

[Function("MyFunction")]
[CosmosDBOutput("MyDatabase", "MyCollection", ConnectionStringSetting = "CosmosDbConnectionString", CreateIfNotExists = true)]
public async Task<MyDocument[]> Run(
    [TimerTrigger("0 */1 * * * *")] MyInfo myTimer)
{
    // Initialize the response as a new List of MyDocuments
    List<MyDocument> responseDocuments = myDocuments = new();

    // Run your code to create your documents...
    MyDocument doc1 = new MyDocument
    {
        id = System.Guid.NewGuid().ToString(),
        message = "hello world from document 1"
    }
    responseDocuments.Add(doc1);

    MyDocument doc2 = new MyDocument
    {
        id = System.Guid.NewGuid().ToString(),
        message = "hello world from document 2"
    }
    responseDocuments.Add(doc2);

    // Return the List of MyDocuments as an array
    return responseDocuments.ToArray();
}
    
public class MyDocument
{
    [JsonPropertyName("id")]
    public string id { get; set; }
    [JsonPropertyName("message")]
    public string message { get; set; }
}

Upvotes: 0

user1477388
user1477388

Reputation: 21440

Instead of using the output binding method which appears to be lacking in support in the isolated process, I was able to successfully use the SDK directly to insert the docs!

Ref. https://github.com/Azure/azure-cosmos-dotnet-v3

NUGET package:

Install-Package Microsoft.Azure.Cosmos

Code sample:

CosmosClient client = new CosmosClient("https://mycosmosaccount.documents.azure.com:443/", "mysupersecretkey");
Database database = await client.CreateDatabaseIfNotExistsAsync("MyDatabaseName");
Container container = await database.CreateContainerIfNotExistsAsync(
    "MyContainerName",
    "/partitionKeyPath",
    400);

// Create an item
dynamic testItem = new { id = "MyTestItemId", partitionKeyPath = "MyTestPkValue", details = "it's working", status = "done" };
ItemResponse<dynamic> createResponse = await container.CreateItemAsync(testItem);

Upvotes: 1

Related Questions