{"id":497,"date":"2020-09-15T10:00:36","date_gmt":"2020-09-15T17:00:36","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/azure-sdk\/?p=497"},"modified":"2020-09-16T09:04:48","modified_gmt":"2020-09-16T16:04:48","slug":"azure-tables-client-libraries","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/azure-sdk\/azure-tables-client-libraries\/","title":{"rendered":"Introducing the new Azure Tables Client Libraries"},"content":{"rendered":"<p>If you&#8217;ve been an Azure developer for some time, you most likely have encountered the <a href=\"https:\/\/azure.microsoft.com\/services\/storage\/tables\/\">Azure Table storage<\/a> service. For those not familiar, it is a service that stores large amounts of structured NoSQL data in the cloud, providing a key\/attribute store with a schema-less design. For many years, it has been the primary choice in Azure providing these capabilities with rock solid stability and extremely cost effectively.<\/p>\n<p>In recent years, you may have noticed that the original Table storage client SDK migrated away from the suite of storage client libraries across all languages to a Azure Cosmos DB tables package in its respective language. This change corresponded with the introduction of a new <a href=\"https:\/\/docs.microsoft.com\/azure\/cosmos-db\/table-introduction\">Table API in Cosmos DB<\/a> which offers code and API compatibility with the existing storage service API while offering a seamless on-ramp to a set of premium features such as:<\/p>\n<ul>\n<li>Single-digit millisecond latency for reads and writes, backed with &lt;10 ms latency for reads and writes at the 99th percentile, at any scale, anywhere in the world.<\/li>\n<li>Dedicated reserved throughput per table that&#8217;s backed by SLAs. Accounts have no upper limit on throughput and support >10 million operations\/s per table. <\/li>\n<li>Turnkey global distribution from one to any number of regions. Support for automatic and manual failovers at any time, anywhere in the world. Multi-master capability to let any region accept write operations.<\/li>\n<li>Automatic and complete indexing on all properties by default, with no index management.<\/li>\n<\/ul>\n<p>You may be wondering, how is this related to the <a href=\"https:\/\/aka.ms\/azsdk\/intro\">new Azure SDKs<\/a>? Well, I&#8217;m proud to announce that the new Tables client&#8217;s first beta is being released this month for the following languages: &#8211; <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-net\/tree\/master\/sdk\/tables\/Azure.Data.Tables\">.NET<\/a> &#8211; <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-java\/tree\/master\/sdk\/tables\/azure-data-tables\">Java<\/a> &#8211; <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-python\/tree\/master\/sdk\/tables\/azure-data-tables\">Python<\/a> &#8211; <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-js\/tree\/master\/sdk\/tables\/data-tables\">JavaScript\/TypeScript<\/a><\/p>\n<p>This means that just like all the other clients that are part of the new Azure SDK, you&#8217;ll find that it conforms to our set of <a href=\"https:\/\/aka.ms\/azsdk\/guide\">guidelines<\/a> which ensure it will remain idiomatic, consistent, approachable, diagnosable, and dependable across all languages.<\/p>\n<h2>Let&#8217;s see some examples<\/h2>\n<p>To introduce the new client, we&#8217;ll explore some &#8220;hello world&#8221; examples that walk through some of the more common Table scenarios. Note that these examples, as with nearly all features of the client, can target either an Azure Table storage account or an Azure Cosmos DB account.<\/p>\n<blockquote>\n<p>The only change required is to create the client with the connection string for your preferred service.<\/p>\n<\/blockquote>\n<p><em>For additional information about getting started, such as acquiring an Azure subscription, creating a Table account, or how to authenticate, check out the language specific links above.<\/em><\/p>\n<h3>Creating the table client<\/h3>\n<h4>.NET<\/h4>\n<pre><code class=\"csharp\">TableClient client = new TableClient(\"connectionString\", \"officeSupplies\");\n<\/code><\/pre>\n<h4>Java<\/h4>\n<pre><code class=\"java\">TableClient tableClient = new TableClientBuilder()\n    .connectionString(\"&lt;your-connection-string&gt;\")\n    .tableName(\"officeSupplies\")\n    .buildClient();\n<\/code><\/pre>\n<h4>Python<\/h4>\n<pre><code class=\"python\">table_client = TableClient.from_connection_string(conn_str=\"&lt;connection_string&gt;\", table_name=\"officeSupplies\")\n<\/code><\/pre>\n<h4>JavaScript<\/h4>\n<pre><code class=\"javascript\">const client = TableClient.fromConnectionString(\"connectionString\", \"officeSupplies\");\n<\/code><\/pre>\n<h3>Creating a new table entity and adding it to the table<\/h3>\n<p>Table entities can contain up to 255 properties, including the 3 system properties of <code>PartitionKey<\/code>, <code>RowKey<\/code>, and <code>Timestamp<\/code>. When creating a new entity, you must provide the first two, as the <code>Timestamp<\/code> is only modified by the service. For more information, see the <a href=\"https:\/\/docs.microsoft.com\/rest\/api\/storageservices\/understanding-the-table-service-data-model#system-properties\">service documentation<\/a>.<\/p>\n<h4>.NET<\/h4>\n<pre><code class=\"csharp\">TableEntity entity = new TableEntity(\"markers\", \"01\")\n{\n    { \"Product\", \"Marker Set\" },\n    { \"Price\", 5.00 },\n    { \"Quantity\", 21 }\n};\n\ntableClient.AddEntity(entity);\n<\/code><\/pre>\n<h4>Java<\/h4>\n<pre><code class=\"java\">TableEntity entity = new TableEntity(\"markers\", \"01\")\n    .addProperty(\"Product\", \"Marker Set\")\n    .addProperty(\"Price\", 5.00)\n    .addProperty(\"Quantity\", 21);\n\ntableClient.createEntity(entity);\n<\/code><\/pre>\n<h4>Python<\/h4>\n<pre><code class=\"python\">my_entity = {'PartitionKey':'markers', 'RowKey':'01', 'Product':'Marker Set', 'Price':5.00, 'Quantity':21}\n\nentity = table_client.create_entity(entity=my_entity)\n<\/code><\/pre>\n<h4>JavaScript<\/h4>\n<pre><code class=\"javascript\">const testEntity = {\n      partitionKey: \"markers\",\n      rowKey: \"01\",\n      Product: \"Marker Set\",\n      Price: 5.00,\n      Quantity: 21 }\n  }\n  await client.createEntity(entity)\n<\/code><\/pre>\n<h3>Querying table entities<\/h3>\n<h4>.NET<\/h4>\n<pre><code class=\"csharp\">Pageable&lt;TableEntity&gt; entities = tableClient.Query&lt;TableEntity&gt;(filter: \"PartitionKey eq 'markers'\");\n\n\/\/ Or using a filter expression\nPageable&lt;TableEntity&gt; entities = tableClient.Query&lt;TableEntity&gt;(ent =&gt; ent.PartitionKey == \"markers\");\n\nforeach (TableEntity entity in entities)\n{\n    Console.WriteLine($\"{entity.GetString(\"Product\")}: {entity.GetDouble(\"Price\")}\");\n}\n<\/code><\/pre>\n<h4>Java<\/h4>\n<pre><code class=\"java\">ListEntitiesOptions options = new ListEntitiesOptions()\n    .setFilter(\"PartitionKey eq 'markers'\")\n\nfor (TableEntity entity : tableClient.listEntities(options)) {\n    Map&lt;String, Object&gt; properties = entity.getProperties();\n    System.out.println(String.format(\"%s: %.2f\", properties.get(\"Product\"), properties.get(\"Price\")));\n}\n<\/code><\/pre>\n<h4>Python<\/h4>\n<pre><code class=\"python\">entities = table_client.query_entities(filter=\"PartitionKey eq 'markers'\")\n\nfor entity in entities:\n    print(\"{}: {}\".format(entity['Product'], entity['Price']))\n<\/code><\/pre>\n<h4>JavaScript<\/h4>\n<pre><code class=\"javascript\">const strValue = \"markers\";\nlet entities = client.listEntities({\n    queryOptions: { filter: odata`PartitionKey eq ${strValue}` }\n});\n\nlet i = 1;\nfor await (const entity of entities) {\n    console.log(`${entity.Product}: ${entity.Price}`);\n    i++;\n}\n<\/code><\/pre>\n<p><strong>Special shout out to our 2020 summer interns <a href=\"https:\/\/github.com\/meanjeekim\">@meanjeekim<\/a>, <a href=\"https:\/\/github.com\/eboyd23\">@eboyd23<\/a>, <a href=\"https:\/\/github.com\/LibbaLawrence\">@LibbaLawrence<\/a>, and <a href=\"https:\/\/github.com\/mahdiva\">@mahdiva<\/a> for their amazing work towards getting these clients shipped!<\/strong><\/p>\n<h2>FAQ<\/h2>\n<h3>Where can I find more examples and samples?<\/h3>\n<p>Each project&#8217;s GitHub repository contains a comprehensive set of samples for you to explore (<a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-net\/tree\/master\/sdk\/tables\/Azure.Data.Tables\/samples\">.NET<\/a>, <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-java\/tree\/master\/sdk\/tables\/azure-data-tables\/src\/samples\">Java<\/a>, <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-python\/tree\/master\/sdk\/tables\/azure-data-tables\/samples\">Python<\/a>, and <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-js\/tree\/master\/sdk\/tables\/data-tables\/samples\">JavaScript\/TypeScript<\/a>).<\/p>\n<p>In addition, you can check out the <a href=\"https:\/\/aka.ms\/memealyzer\">Memealyzer<\/a> project which demonstrates usage of many of the new Azure SDK client libraries, including Tables, across multiple languages. It also implements configuration options to seamlessly switch between Azure Storage and Azure Cosmos DB services. <em>Note: If you don&#8217;t see you favorite language implemented yet, the project gladly accepts contributions!<\/em><\/p>\n<h3>Is the Azure Table storage service going away in favor of Cosmos DB&#8217;s table service?<\/h3>\n<p>No, it is not. The new Azure Tables client allows developers to seamlessly migrate from Azure Table storage to Azure Cosmos DB by using the Table API with no code changes and take advantage of premium capabilities. Workloads that don&#8217;t require these capabilities or prioritize a pricing model that is storage-optimized rather than throughput-optimized should continue to target Azure Table storage.<\/p>\n<h3>Where is Cosmos DB Table API not identical with Azure Table storage behavior?<\/h3>\n<p>The behavior differences are documented <a href=\"https:\/\/docs.microsoft.com\/azure\/cosmos-db\/table-api-faq#table-api-vs-table-storage\">here<\/a>.<\/p>\n<p><!-- FOOTER: DO NOT EDIT OR REMOVE --><\/p>\n<h2>Azure SDK Blog Contributions<\/h2>\n<p>Thank you for reading this Azure SDK blog post! We hope that you learned something new and welcome you to share this post. We are open to Azure SDK blog contributions. Please contact us at <a href=\"&#109;&#x61;&#105;&#x6c;&#116;&#x6f;&#58;&#x61;z&#115;&#x64;&#107;&#x62;&#108;&#x6f;&#103;&#x40;&#109;&#105;&#x63;&#114;&#x6f;&#115;&#x6f;&#102;&#x74;&#46;&#x63;o&#109;\">&#x61;z&#115;&#x64;&#107;&#x62;&#108;&#x6f;&#103;&#x40;&#109;&#105;&#x63;&#114;&#x6f;&#115;&#x6f;&#102;&#x74;&#46;&#x63;o&#109;<\/a> with your topic and we&#8217;ll get you setup as a guest blogger.<\/p>\n<h2>Azure SDK Links<\/h2>\n<ul>\n<li>Azure SDK Website: <a href=\"https:\/\/aka.ms\/azsdk\">aka.ms\/azsdk<\/a><\/li>\n<li>Azure SDK Intro (3 minute video): <a href=\"https:\/\/aka.ms\/azsdk\/intro\">aka.ms\/azsdk\/intro<\/a><\/li>\n<li>Azure SDK Intro Deck (PowerPoint deck): <a href=\"https:\/\/aka.ms\/azsdk\/intro\/deck\">aka.ms\/azsdk\/intro\/deck<\/a><\/li>\n<li>Azure SDK Releases: <a href=\"https:\/\/aka.ms\/azsdk\/releases\">aka.ms\/azsdk\/releases<\/a><\/li>\n<li>Azure SDK Blog: <a href=\"https:\/\/aka.ms\/azsdk\/blog\">aka.ms\/azsdk\/blog<\/a><\/li>\n<li>Azure SDK Twitter: <a href=\"https:\/\/twitter.com\/AzureSDK\">twitter.com\/AzureSDK<\/a><\/li>\n<li>Azure SDK Design Guidelines: <a href=\"https:\/\/aka.ms\/azsdk\/guide\">aka.ms\/azsdk\/guide<\/a><\/li>\n<li>Azure SDKs &amp; Tools: <a href=\"https:\/\/azure.microsoft.com\/downloads\">azure.microsoft.com\/downloads<\/a><\/li>\n<li>Azure SDK Central Repository: <a href=\"https:\/\/github.com\/azure\/azure-sdk#azure-sdk\">github.com\/azure\/azure-sdk<\/a><\/li>\n<li>Azure SDK for .NET: <a href=\"https:\/\/github.com\/azure\/azure-sdk-for-net\">github.com\/azure\/azure-sdk-for-net<\/a><\/li>\n<li>Azure SDK for Java: <a href=\"https:\/\/github.com\/azure\/azure-sdk-for-java\">github.com\/azure\/azure-sdk-for-java<\/a><\/li>\n<li>Azure SDK for Python: <a href=\"https:\/\/github.com\/azure\/azure-sdk-for-python\">github.com\/azure\/azure-sdk-for-python<\/a><\/li>\n<li>Azure SDK for JavaScript\/TypeScript: <a href=\"https:\/\/github.com\/azure\/azure-sdk-for-js\">github.com\/azure\/azure-sdk-for-js<\/a><\/li>\n<li>Azure SDK for Android: <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-android\">github.com\/Azure\/azure-sdk-for-android<\/a><\/li>\n<li>Azure SDK for iOS: <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-ios\">github.com\/Azure\/azure-sdk-for-ios<\/a><\/li>\n<li>Azure SDK for Go: <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-go\">github.com\/Azure\/azure-sdk-for-go<\/a><\/li>\n<li>Azure SDK for C: <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-c\">github.com\/Azure\/azure-sdk-for-c<\/a><\/li>\n<li>Azure SDK for C++: <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-cpp\">github.com\/Azure\/azure-sdk-for-cpp<\/a><\/li>\n<\/ul>\n<p><!-- FOOTER: DO NOT EDIT OR REMOVE --><\/p>\n","protected":false},"excerpt":{"rendered":"<p>We just released the new Azure Tables client libraries beta! In this post, we&#8217;ll introduce you to the new libraries and show you how to get started.<\/p>\n","protected":false},"author":38551,"featured_media":506,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[747,738,746],"class_list":["post-497","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-azure-sdk","tag-cosmos","tag-storage","tag-tables"],"acf":[],"blog_post_summary":"<p>We just released the new Azure Tables client libraries beta! In this post, we&#8217;ll introduce you to the new libraries and show you how to get started.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/posts\/497","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\/38551"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/comments?post=497"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/posts\/497\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/media\/506"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/media?parent=497"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/categories?post=497"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/tags?post=497"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}