Azure / azure-functions-dotnet-worker

Azure Functions out-of-process .NET language worker
MIT License
412 stars 176 forks source link

TableInput for single entity returns array with one entity #1233

Closed rickvdbosch closed 1 year ago

rickvdbosch commented 1 year ago

When creating a .NET 7 Function App, using the TableInputAttribute from the Microsoft.Azure.Functions.Worker.Extensions.Tables NuGet package with a tablename, partitionkey and rowkey, the parameter becomes an array with one entity, instead of one entity.

Here's the code I initially tried to run:

[Function("SomeFunction")]
public HttpResponseData Run(
    [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "somefunction/{paramname}")] HttpRequestData req,
    [TableInput("<table-name>", "<partition-key>", "{paramname}")] SomeEntity someEntity)
{
    // Removed to keep it on-topic 😊
}

This results in the message

Cannot convert input parameter 'someEntity' to type 'Namespace.For.Entity.SomeEntity' from type 'System.String'

When I change the parameter to be an object, I see the content is an array since it's a single JSON object surrounded by square brackets ([]). Changing the param that the TableInputAttribute binding is on to be an array (SomeEntity[]) fixes the issue, forcing me to check the length of the array and getting the item at index 0 to get to the one entity.

Is this by design, or is it indeed an issue?

rickvdbosch commented 1 year ago

Here's an update: it looks like I'm getting all the entities in the array. Even though there's both a PartitionKey and a RowKey in the TableInputAttribute.

I didn't run into that one earlier since I was testing with one specific entity at first. Now that I've added more entities, I can see all of the entities coming in. The shortcode parameter contains the expected content.

Here's a screenshot of me debugging the Function locally:

Screenshot of Visual Studio, debugging a Function locally

rickvdbosch commented 1 year ago

Tried some more scenarios today:

Explicitly setting the ConnectionString parameter to the name of a key holding the connection string in app settings does not solve this issue.

When I set a filter like Filter = "RowKey eq '{shortcode}'" it does work, but this defeats the purpose of the RowKey parameter in the attribute. And, of course, this again returns an array of entities containing the one entity I'm looking for (since a filter could return multiple entities).

h-maac commented 1 year ago

I can confirm that this is only reproducible for the recently extracted package

Azure Tables extension Microsoft.Azure.Functions.Worker.Extensions.Tables 1.0.0

@rickvdbosch as a workaround previous version seem to respect the rowKey and is working as expected.

Combined Azure Storage extension Microsoft.Azure.Functions.Worker.Extensions.Storage 4.x (at the time of writing v4.0.4) For reference; please look under Install extension after navigating to either of the pages using the links

To reproduce;

the required code is as simple as it is given in the issue description, using the latest Microsoft.Azure.Functions.Worker.Extensions.Tables pkg. Though a caveat; binding to a SomeEntity as seen above will give a runtime exc due to the issue. So it can either be binded to a collection of SomeEntity, string or object.

aishwaryabh commented 1 year ago

This should be fixed with the GA of sdk type bindings: https://learn.microsoft.com/en-us/azure/azure-functions/functions-bindings-storage-table-input?tabs=isolated-process%2Ctable-api&pivots=programming-language-csharp

scottwhitacre commented 7 months ago

This shouldn't be closed. Look at the comments in the linked issue in the other repo. It's still not working on the newest packages.

markheath commented 6 months ago

I've run into this issue with the latest extension "Microsoft.Azure.Functions.Worker.Extensions.Tables" Version="1.3.0" The workaround is to bind to a TableClient and look up the row yourself but it would be nice to see this fixed