{"id":1889,"date":"2022-03-22T09:00:32","date_gmt":"2022-03-22T16:00:32","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/azure-sdk\/?p=1889"},"modified":"2022-03-22T09:54:54","modified_gmt":"2022-03-22T16:54:54","slug":"whats-new-in-the-azure-functions-tables-extension-for-net-beta","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/azure-sdk\/whats-new-in-the-azure-functions-tables-extension-for-net-beta\/","title":{"rendered":"What&#8217;s new in the Azure Functions Tables extension for .NET **Beta**"},"content":{"rendered":"<p>Previously, the Azure Tables bindings for .NET were available as part of the <a href=\"https:\/\/www.nuget.org\/packages\/Microsoft.Azure.WebJobs.Extensions.Storage\">Microsoft.Azure.WebJobs.Extensions.Storage<\/a> package (version 4 and earlier). Version 5 of the <a href=\"https:\/\/www.nuget.org\/packages\/Microsoft.Azure.WebJobs.Extensions.Storage\/5.0.0\">storage extensions<\/a> package no longer contains the Tables bindings. Instead, the Tables bindings are available in a new package called <a href=\"https:\/\/www.nuget.org\/packages\/Microsoft.Azure.WebJobs.Extensions.Tables\/1.0.0-beta.2\">Microsoft.Azure.WebJobs.Extensions.Tables<\/a>, which is now in beta. Like the other new Azure Functions extensions for Storage, Event Hubs, and Service Bus, the new Tables extension supports integration with <a href=\"https:\/\/www.nuget.org\/packages\/Azure.Identity\">Azure.Identity<\/a>.<\/p>\n<h2>Configuration<\/h2>\n<p>To authenticate, provide an endpoint, a connection string, or a shared key. This configuration is set in the <strong>Application settings<\/strong> section of your function app in the Azure portal. For more information on configuring application settings for Functions apps, see <a href=\"https:\/\/docs.microsoft.com\/azure\/azure-functions\/functions-how-to-use-azure-function-app-settings?tabs=portal\">Manage your function app<\/a>.<\/p>\n<h2>Identity<\/h2>\n<p>To use Azure Active Directory authentication, you must provide an endpoint. You can optionally provide additional credential information. To use <a href=\"https:\/\/docs.microsoft.com\/azure\/active-directory\/managed-identities-azure-resources\/overview\">Managed Identity<\/a>, specify the following settings:<\/p>\n<table>\n<thead>\n<tr>\n<th>Name<\/th>\n<th>Value<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>MyConnection__endpoint<\/code><\/td>\n<td><code>https:\/\/...table.core.windows.net<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>MyConnection__credential<\/code><\/td>\n<td><code>managedidentity<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>MyConnection__clientId<\/code><\/td>\n<td><code>{user-assigned client id}<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>If no credential information is provided, the <a href=\"https:\/\/docs.microsoft.com\/dotnet\/api\/overview\/azure\/identity-readme#defaultazurecredential\"><code>DefaultAzureCredential<\/code><\/a> is used.<\/p>\n<h2>Connection string<\/h2>\n<p>To use connection string authentication, assign the connection string value directly to the connection setting. You can do one of the following things:<\/p>\n<ul>\n<li>Define a custom connection setting. For example, <code>MyConnection<\/code>.<\/li>\n<li>Use the default connection setting, <code>AzureWebJobsStorage<\/code>.<\/li>\n<\/ul>\n<table>\n<thead>\n<tr>\n<th>Name<\/th>\n<th>Value<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>MyConnection<\/code><\/td>\n<td><code>DefaultEndpointsProtocol=https;AccountName=...;AccountKey=...;EndpointSuffix=core.windows.net<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2>Shared key<\/h2>\n<p>To use shared key authentication, the endpoint, account key, and account name are required:<\/p>\n<table>\n<thead>\n<tr>\n<th>Name<\/th>\n<th>Value<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>MyConnection__endpoint<\/code><\/td>\n<td><code>https:\/\/...table.core.windows.net<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>MyConnection__credential__accountName<\/code><\/td>\n<td><code>{account name}<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>MyConnection__credential__accountKey<\/code><\/td>\n<td><code>{account key}<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2>Usage<\/h2>\n<p>Unlike some of the other Azure Functions extensions, the Tables Functions extension doesn&#8217;t support triggering. It supports reading, updating, and writing entries to a table; you&#8217;ll need the function to be triggered by something else. In the following examples, we demonstrate using an <code>HttpTrigger<\/code> in our functions. Also note that unlike the previous version of the Tables bindings, there are no longer separate attributes for input and output binding. Instead, the behavior is dependent on the arguments passed to the <code>[Table]<\/code> attribute.<\/p>\n<h2>Input binding<\/h2>\n<p>When binding to a single entity, you must specify the table name, partition key, and row key in the <code>[Table]<\/code> attribute.<\/p>\n<h3>Binding using <code>TableEntity<\/code><\/h3>\n<pre><code class=\"language-c#\">public class InputSingle\r\n{\r\n    [FunctionName(\"InputSingle\")]\r\n    public static void Run(\r\n        [HttpTrigger(AuthorizationLevel.Anonymous, \"GET\")] HttpRequest request,\r\n        [Table(\"MyTable\", \"&lt;PartitionKey&gt;\", \"&lt;RowKey&gt;\")] TableEntity entity, ILogger log)\r\n    {\r\n        log.LogInformation($\"PK={entity.PartitionKey}, RK={entity.RowKey}, Text={entity[\"Text\"]}\");\r\n    }\r\n}<\/code><\/pre>\n<h3>Binding using a custom model<\/h3>\n<p>When you use a custom model, the binding is based on the property name and type of the members. Because <code>PartitionKey<\/code> and <code>RowKey<\/code> are always included in a table entity, you&#8217;re able to bind to them as named properties. Additionally, you can implement <code>ITableEntity<\/code>, which makes it easier to define the available properties correctly. For example:<\/p>\n<pre><code class=\"language-c#\">public class MyEntity : ITableEntity\r\n{\r\n    \/\/ ITableEntity properties\r\n    public string PartitionKey { get; set; }\r\n    public string RowKey { get; set; }\r\n    public DateTimeOffset? Timestamp { get; set; }\r\n    public ETag ETag { get; set; }\r\n\r\n    \/\/ custom property\r\n    public string Text { get; set; }\r\n}<\/code><\/pre>\n<pre><code class=\"language-c#\">public class InputSingleModel\r\n{\r\n    [FunctionName(\"InputSingleModel\")]\r\n    public static void Run(\r\n        [HttpTrigger(AuthorizationLevel.Anonymous, \"GET\")] HttpRequest request,\r\n        [Table(\"MyTable\", \"&lt;PartitionKey&gt;\", \"&lt;RowKey&gt;\")] MyEntity entity, ILogger log)\r\n    {\r\n        log.LogInformation($\"PK={entity.PartitionKey}, RK={entity.RowKey}, Text={entity.Text}\");\r\n    }\r\n}<\/code><\/pre>\n<p>It&#8217;s also possible to define a complex property. For example, see the following <code>MyModel<\/code>-typed property:<\/p>\n<pre><code class=\"language-c#\">public class MyEntity\r\n{\r\n    public string PartitionKey { get; set; }\r\n    public string RowKey { get; set; }\r\n    public string Text { get; set; }\r\n    public MyModel Model { get; set; }\r\n}<\/code><\/pre>\n<p>With this model defined, the extension will attempt to deserialize the table entities &#8220;Model&#8221; JSON into the strongly typed <code>MyModel<\/code> object.<\/p>\n<h3>Update entity<\/h3>\n<p>You can also update entities when using the input binding. When updating an entity, you aren&#8217;t able to modify the <code>RowKey<\/code> or <code>PartitionKey<\/code>. You can, however, update any other attribute of the entity. If your function modifies the entity, the extension will attempt to update the entity in the table.<\/p>\n<h2>Output binding<\/h2>\n<p>To use the output binding, specify only the table name in the <code>[Table]<\/code> attribute.<\/p>\n<h3>Create a new entity using <code>TableEntity<\/code><\/h3>\n<pre><code class=\"language-C#\">public class OutputSingle\r\n{\r\n    [FunctionName(\"OutputSingle\")]\r\n    public static void Run(\r\n        [HttpTrigger(AuthorizationLevel.Anonymous, \"GET\")] HttpRequest request,\r\n        [Table(\"MyTable\")] out TableEntity entity)\r\n    {\r\n        entity = new TableEntity(\"&lt;PartitionKey&gt;\", \"&lt;RowKey&gt;\")\r\n        {\r\n            [\"Text\"] = \"Hello\"\r\n        };\r\n    }\r\n}<\/code><\/pre>\n<h3>Create a new entity using a custom model<\/h3>\n<pre><code class=\"language-C#\">public class MyEntity\r\n{\r\n    public string PartitionKey { get; set; }\r\n    public string RowKey { get; set; }\r\n    public string Text { get; set; }\r\n}<\/code><\/pre>\n<pre><code class=\"language-C#\">public class OutputSingleModel\r\n{\r\n    [FunctionName(\"OutputSingleModel\")]\r\n    public static void Run(\r\n        [HttpTrigger(AuthorizationLevel.Anonymous, \"GET\")] HttpRequest request,\r\n        [Table(\"MyTable\")] out MyEntity entity)\r\n    {\r\n        entity = new MyEntity()\r\n        {\r\n            PartitionKey = \"&lt;PartitionKey&gt;\",\r\n            RowKey = \"&lt;RowKey&gt;\",\r\n            Text = \"Hello\"\r\n        };\r\n    }\r\n}<\/code><\/pre>\n<h2>Conclusion<\/h2>\n<p>More examples, including binding to multiple entities, can be found in the project&#8217;s <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-net\/blob\/main\/sdk\/tables\/Microsoft.Azure.WebJobs.Extensions.Tables\/README.md\">README<\/a>. We hope you&#8217;ll try out the new extensions and <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-net\/issues\/new\/choose\">provide feedback<\/a>!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Azure Functions Tables extension now are available in a new Beta package called Microsoft.Azure.WebJobs.Extensions.Tables. Like the other new Azure Functions extensions for Storage, Event Hubs, and Service Bus, the new Tables extension supports integration with Azure.Identity.<\/p>\n","protected":false},"author":55909,"featured_media":1890,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[701,765,842,746],"class_list":["post-1889","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-azure-sdk","tag-net","tag-azure-functions","tag-beta","tag-tables"],"acf":[],"blog_post_summary":"<p>Azure Functions Tables extension now are available in a new Beta package called Microsoft.Azure.WebJobs.Extensions.Tables. Like the other new Azure Functions extensions for Storage, Event Hubs, and Service Bus, the new Tables extension supports integration with Azure.Identity.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/posts\/1889","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/users\/55909"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/comments?post=1889"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/posts\/1889\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/media\/1890"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/media?parent=1889"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/categories?post=1889"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/tags?post=1889"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}