2
votes

I'm using Azure Functions and want to use an imperative binding to my Cosmos DB repository.

At first I had defined my output parameter like this in the Run-method:

[DocumentDB("TablesDB", "minified-urls", ConnectionStringSetting = "CosmosConnectionString", CreateIfNotExists = true)] out MinifiedUrl minifiedUrl,

this works great.

But I'd rather use imperative binding, so I can define the values used in the binding dynamically.

First thing I tried was this, which doesn't work, because you need to set the ConnectionStringSetting.

var output = await binder.BindAsync<MinifiedUrl>(new DocumentDBAttribute("TablesDB", "minified-urls"));

So changing this piece of binding to the following should work, at least that's what I thought.

var output = await binder.BindAsync<MinifiedUrl>(new DocumentDBAttribute("TablesDB", "minified-urls")
{
    CreateIfNotExists = true,
    ConnectionStringSetting = "CosmosConnectionString"
});

When you do this, the binder is complaining about a missing Id property and if you fill this Id property you also need to set the PartitionKey.

So in the end this is what I came up with.

var output = await binder.BindAsync<MinifiedUrl>(new DocumentDBAttribute("TablesDB", "minified-urls")
{
    CreateIfNotExists = true,
    ConnectionStringSetting = "CosmosConnectionString",
    Id = Guid.NewGuid().ToString(),
    PartitionKey = DateTime.UtcNow.Year.ToString()
});

Because I want to create a new document inside the repository, the binder is not able to find something, therefore the output variable is null.

So, what I'd like to know is how to proceed? The declarative binding works properly, but I can't figure out how to get this imperative working.

2

2 Answers

3
votes

Your problems come from the fact that runtime interprets your imperative binding as input one. That's because you are requesting the custom type (MinifiedUrl), so it makes sense that this value should be loaded from the database.

To make your binding output, you should request IAsyncCollector type, and then call AddAsync on it:

var output = await binder.BindAsync<IAsyncCollector<MinifiedUrl>>(
    new DocumentDBAttribute("TablesDB", "minified-urls")
    { 
        CreateIfNotExists = true,
        ConnectionStringSetting = "CosmosConnectionString"
    });
await output.AddAsync(new MinifiedUrl(...));
1
votes

Alternatively, do not even bother with output binding to Document Db. I found the output binding programming model and apis a lot less powerful than actual client sdk s of the service you are trying to use (document db in this case).

if you set your Document db end point and key to your app settings, then you can simply instantiate a document db client within your azure function (you need to have the document db nuget) and after that you have the full control over what you want to do without worrying about awkward notation s and attributes for output binding..