Azure Function v2 cannot bind to Table
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)
{
}
}
}
Find and bind to TestFunction
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]'.
Repeating the steps above, but choosing v1 works.
Azure Functions and Web Jobs Tools 15.0.40108.0
Azure.Functions.Cli 1.0.7
This is a regression. I am able to repro it. Here is the StackTrace: " at Microsoft.Azure.WebJobs.Host.Tables.TableAttributeBindingProvider.1.GetResult()\r\n at Microsoft.Azure.WebJobs.Host.Bindings.GenericCompositeBindingProvider1.1.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.
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.
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.