Azure-webjobs-sdk: Azure Function v2 cannot bind to Table

Created on 2 Feb 2018  路  9Comments  路  Source: Azure/azure-webjobs-sdk

Azure Function v2 cannot bind to Table

Repro steps

  1. Create a new Function app
  2. Choose v2
  3. Add class with the following:
using Microsoft.Azure.WebJobs;
using Microsoft.WindowsAzure.Storage.Table;
using System.Linq;

namespace MyNamespace.Functions
{
    public class TestFunction
    {
        [FunctionName("TestFunction")]
        public static void Run(
            [QueueTrigger("test-queue")]string message,
            [Table("testTable")]IQueryable<TableEntity> query)
        {
        }
    }
}

  1. Start function

Expected behavior

Find and bind to TestFunction

Actual behavior

No job functions found.

[2/2/2018 9:26:04 PM] A ScriptHost error has occurred
[2/2/2018 9:26:04 PM] Microsoft.Azure.WebJobs.Host: Error indexing method 'TestFunction.Run'. Microsoft.Azure.WebJobs.Host: Can't bind Table to type 'System.Linq.IQueryable1[Microsoft.WindowsAzure.Storage.Table.TableEntity]'. [2/2/2018 9:26:04 PM] Error indexing method 'TestFunction.Run' [2/2/2018 9:26:04 PM] Microsoft.Azure.WebJobs.Host: Error indexing method 'TestFunction.Run'. Microsoft.Azure.WebJobs.Host: Can't bind Table to type 'System.Linq.IQueryable1[Microsoft.WindowsAzure.Storage.Table.TableEntity]'.
[2/2/2018 9:26:05 PM] No job functions found. Try making your job classes and methods public. If you're using binding extensions (e.g. ServiceBus, Timers, etc.) make sure you've called the registration method for the extension(s) in your startup code (e.g. config.UseServiceBus(), config.UseTimers(), etc.).
[2/2/2018 9:26:05 PM] Job host started
[2/2/2018 9:26:05 PM] The following 1 functions are in error:
Listening on http://localhost:7071/
Hit CTRL-C to exit...
[2/2/2018 9:26:05 PM] Host lock lease acquired by instance ID '0000000000000000000000007FE69A22'.
[2/2/2018 9:26:05 PM] Run: Microsoft.Azure.WebJobs.Host: Error indexing method 'TestFunction.Run'. Microsoft.Azure.WebJobs.Host: Can't bind Table to type 'System.Linq.IQueryable`1[Microsoft.WindowsAzure.Storage.Table.TableEntity]'.

Related information

Repeating the steps above, but choosing v1 works.
Azure Functions and Web Jobs Tools 15.0.40108.0
Azure.Functions.Cli 1.0.7

Most helpful comment

Just in case that anyone is interested: I posed a question on GitHub recently where binding to tables in v2 functions is being discussed. Until the docs are updated with examples on how to bind to table storage in v2 functions, the GitHub thread might help anyone interested to get started.

All 9 comments

This is a regression. I am able to repro it. Here is the StackTrace: " at Microsoft.Azure.WebJobs.Host.Tables.TableAttributeBindingProvider.d__4.MoveNext() in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Tables\TableAttributeBindingProvider.cs:line 74\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter1.GetResult()\r\n at Microsoft.Azure.WebJobs.Host.Bindings.GenericCompositeBindingProvider1.d__5.MoveNext() in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Bindings\BindingProviders\GenericCompositeBindingProvider.cs:line 56\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter1.GetResult()\r\n at Microsoft.Azure.WebJobs.Host.Bindings.CompositeBindingProvider.<TryCreateAsync>d__2.MoveNext() in C:\\projects\\azure-webjobs-sdk-rqm4t\\src\\Microsoft.Azure.WebJobs.Host\\Bindings\\BindingProviders\\CompositeBindingProvider.cs:line 25\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter1.GetResult()\r\n at Microsoft.Azure.WebJobs.Host.Indexers.FunctionIndexer.d__17.MoveNext() in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Indexers\FunctionIndexer.cs:line 245\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at Microsoft.Azure.WebJobs.Host.Indexers.FunctionIndexer.d__16.MoveNext() in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Indexers\FunctionIndexer.cs:line 160" string

The original issue is about binding to IQueryable<TableEntity>, which is one of the things that has been dropped in V2 because of limitations introduced by version 8.x of the Storage SDK targeting .NET Standard. That functionality will only be re-added if they reintroduce that support. We've been working with the team and that is something they intend to do.

This documentation needs to be updated to reflect those limitations and breaking changes.

Agreed. We'll be investing in 2.0 documentation as we get closer to a beta quality preview.

/cc @tdykstra

The Storage table doc does have a note that says IQueryable isn't supported in 2.0: see the Input binding usage section.

Ah! Just saw that (hadn't really looked at the document before adding you).

Thanks, Tom!

Just in case that anyone is interested: I posed a question on GitHub recently where binding to tables in v2 functions is being discussed. Until the docs are updated with examples on how to bind to table storage in v2 functions, the GitHub thread might help anyone interested to get started.

@MrMikeFloyd Thanks for adding the link here; I'll add a link to the SO thread in the doc.

I forgot about this issue and ran into it again. Thanks to @MrMikeFloyd, I now see I can use CloudTable. I thought I couldn't use Table binding at all! Instead, I was getting the CloudStorageAccount and writing the "necessary" verbose code. Thank you! Much simpler.

Was this page helpful?
0 / 5 - 0 ratings