Skip to content

Commit a856aab

Browse files
Merge pull request #235815 from pauljewellmsft/pauljewell-tables-update
Update packages and code snippets for tables article
2 parents 1834360 + cf8776e commit a856aab

File tree

1 file changed

+52
-30
lines changed

1 file changed

+52
-30
lines changed

articles/storage/tables/table-storage-design-patterns.md

Lines changed: 52 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -627,13 +627,13 @@ Consider the following points when deciding how to store log data:
627627

628628
## Implementation considerations
629629

630-
This section discusses some of the considerations to bear in mind when you implement the patterns described in the previous sections. Most of this section uses examples written in C# that use the Storage Client Library (version 4.3.0 at the time of writing).
630+
This section discusses some of the considerations to bear in mind when you implement the patterns described in the previous sections. Most of this section uses examples written in C# that use the Storage client library (version 4.3.0 at the time of writing).
631631

632632
## Retrieving entities
633633

634-
As discussed in the section Design for querying, the most efficient query is a point query. However, in some scenarios you may need to retrieve multiple entities. This section describes some common approaches to retrieving entities using the Storage Client Library.
634+
As discussed in the section Design for querying, the most efficient query is a point query. However, in some scenarios you may need to retrieve multiple entities. This section describes some common approaches to retrieving entities using the Storage client library.
635635

636-
### Executing a point query using the Storage Client Library
636+
### Executing a point query using the Storage client library
637637

638638
The easiest way to execute a point query is to use the **GetEntityAsync** method as shown in the following C# code snippet that retrieves an entity with a **PartitionKey** of value "Sales" and a **RowKey** of value "212":
639639

@@ -648,21 +648,19 @@ Notice how this example expects the entity it retrieves to be of type **Employee
648648
You can use LINQ to retrieve multiple entities from the Table service when working with Microsoft Azure Cosmos DB Table Standard Library.
649649

650650
```azurecli
651-
dotnet add package Microsoft.Azure.Cosmos.Table
651+
dotnet add package Azure.Data.Tables
652652
```
653653

654654
To make the below examples work, you'll need to include namespaces:
655655

656656
```csharp
657657
using System.Linq;
658-
using Azure.Data.Table
658+
using Azure.Data.Tables
659659
```
660660

661-
The employeeTable is a CloudTable object that implements a CreateQuery\<ITableEntity>() method, which returns a TableQuery\<ITableEntity>. Objects of this type implement an IQueryable and allow using both LINQ Query Expressions and dot notation syntax.
661+
Retrieving multiple entities can be achieved by specifying a query with a **filter** clause. To avoid a table scan, you should always include the **PartitionKey** value in the filter clause, and if possible the **RowKey** value to avoid table and partition scans. The table service supports a limited set of comparison operators (greater than, greater than or equal, less than, less than or equal, equal, and not equal) to use in the filter clause.
662662

663-
Retrieving multiple entities and be achieved by specifying a query with a **filter** clause. To avoid a table scan, you should always include the **PartitionKey** value in the filter clause, and if possible the **RowKey** value to avoid table and partition scans. The table service supports a limited set of comparison operators (greater than, greater than or equal, less than, less than or equal, equal, and not equal) to use in the filter clause.
664-
665-
The following C# code snippet finds all the employees whose last name starts with "B" (assuming that the **RowKey** stores the last name) in the sales department (assuming the **PartitionKey** stores the department name):
663+
In the following example, `employeeTable` is a [TableClient](/dotnet/api/azure.data.tables.tableclient) object. This example finds all the employees whose last name starts with "B" (assuming that the **RowKey** stores the last name) in the sales department (assuming the **PartitionKey** stores the department name):
666664

667665
```csharp
668666
var employees = employeeTable.Query<EmployeeEntity>(e => (e.PartitionKey == "Sales" && e.RowKey.CompareTo("B") >= 0 && e.RowKey.CompareTo("C") < 0));
@@ -689,7 +687,7 @@ You should always fully test the performance of your application in such scenari
689687

690688
A query against the table service may return a maximum of 1,000 entities at one time and may execute for a maximum of five seconds. If the result set contains more than 1,000 entities, if the query did not complete within five seconds, or if the query crosses the partition boundary, the Table service returns a continuation token to enable the client application to request the next set of entities. For more information about how continuation tokens work, see [Query Timeout and Pagination](/rest/api/storageservices/Query-Timeout-and-Pagination).
691689

692-
If you are using the Table Client Library, it can automatically handle continuation tokens for you as it returns entities from the Table service. The following C# code sample using the Table Client Library automatically handles continuation tokens if the table service returns them in a response:
690+
If you are using the Azure Tables client library, it can automatically handle continuation tokens for you as it returns entities from the Table service. The following C# code sample using the client library automatically handles continuation tokens if the table service returns them in a response:
693691

694692
```csharp
695693
var employees = employeeTable.Query<EmployeeEntity>("PartitionKey eq 'Sales'")
@@ -700,20 +698,50 @@ foreach (var emp in employees)
700698
}
701699
```
702700

703-
The following C# code handles continuation tokens explicitly:
701+
You can also specify the maximum number of entities that are returned per page. The following example shows how to query entities with `maxPerPage`:
704702

705703
```csharp
706-
TableContinuationToken continuationToken = null;
707-
do
704+
var employees = employeeTable.Query<EmployeeEntity>(maxPerPage: 10);
705+
706+
// Iterate the Pageable object by page
707+
foreach (var page in employees.AsPages())
708708
{
709-
var employees = employeeTable.Query<EmployeeEntity>("PartitionKey eq 'Sales'");
710-
foreach (var emp in employees.AsPages())
709+
// Iterate the entities returned for this page
710+
foreach (var emp in page.Values)
711711
{
712712
// ...
713-
continuationToken = emp.ContinuationToken;
714713
}
715-
716-
} while (continuationToken != null);
714+
}
715+
```
716+
717+
In more advanced scenarios, you may want to store the continuation token returned from the service so that your code controls exactly when the next pages is fetched. The following example shows a basic scenario of how the token can be fetched and applied to paginated results:
718+
719+
```csharp
720+
string continuationToken = null;
721+
bool moreResultsAvailable = true;
722+
while (moreResultsAvailable)
723+
{
724+
var page = employeeTable
725+
.Query<EmployeeEntity>()
726+
.AsPages(continuationToken, pageSizeHint: 10)
727+
.FirstOrDefault(); // pageSizeHint limits the number of results in a single page, so we only enumerate the first page
728+
729+
if (page == null)
730+
break;
731+
732+
// Get the continuation token from the page
733+
// Note: This value can be stored so that the next page query can be executed later
734+
continuationToken = page.ContinuationToken;
735+
736+
var pageResults = page.Values;
737+
moreResultsAvailable = pageResults.Any() && continuationToken != null;
738+
739+
// Iterate the results for this page
740+
foreach (var result in pageResults)
741+
{
742+
// ...
743+
}
744+
}
717745
```
718746

719747
By using continuation tokens explicitly, you can control when your application retrieves the next segment of data. For example, if your client application enables users to page through the entities stored in a table, a user may decide not to page through all the entities retrieved by the query so your application would only use a continuation token to retrieve the next segment when the user had finished paging through all the entities in the current segment. This approach has several benefits:
@@ -727,12 +755,6 @@ By using continuation tokens explicitly, you can control when your application r
727755
>
728756
>
729757
730-
The following C# code shows how to modify the number of entities returned inside a segment:
731-
732-
```csharp
733-
employees.max = 50;
734-
```
735-
736758
### Server-side projection
737759

738760
A single entity can have up to 255 properties and be up to 1 MB in size. When you query the table and retrieve entities, you may not need all the properties and can avoid transferring data unnecessarily (to help reduce latency and cost). You can use server-side projection to transfer just the properties you need. The following example retrieves just the **Email** property (along with **PartitionKey**, **RowKey**, **Timestamp**, and **ETag**) from the entities selected by the query.
@@ -752,9 +774,9 @@ Notice how the **RowKey** value is available even though it was not included in
752774

753775
## Modifying entities
754776

755-
The Storage Client Library enables you to modify your entities stored in the table service by inserting, deleting, and updating entities. You can use EGTs to batch multiple inserts, update, and delete operations together to reduce the number of round trips required and improve the performance of your solution.
777+
The Storage client library enables you to modify your entities stored in the table service by inserting, deleting, and updating entities. You can use EGTs to batch multiple inserts, update, and delete operations together to reduce the number of round trips required and improve the performance of your solution.
756778

757-
Exceptions thrown when the Storage Client Library executes an EGT typically include the index of the entity that caused the batch to fail. This is helpful when you are debugging code that uses EGTs.
779+
Exceptions thrown when the Storage client library executes an EGT typically include the index of the entity that caused the batch to fail. This is helpful when you are debugging code that uses EGTs.
758780

759781
You should also consider how your design affects how your client application handles concurrency and update operations.
760782

@@ -973,13 +995,13 @@ The techniques discussed in this section are especially relevant to the discussi
973995
>
974996
>
975997

976-
The remainder of this section describes some of the features in the Storage Client Library that facilitate working with multiple entity types in the same table.
998+
The remainder of this section describes some of the features in the Storage client library that facilitate working with multiple entity types in the same table.
977999

9781000
### Retrieving heterogeneous entity types
9791001

980-
If you are using the Table Client Library, you have three options for working with multiple entity types.
1002+
If you are using the Table client library, you have three options for working with multiple entity types.
9811003

982-
If you know the type of the entity stored with a specific **RowKey** and **PartitionKey** values, then you can specify the entity type when you retrieve the entity as shown in the previous two examples that retrieve entities of type **EmployeeEntity**: [Executing a point query using the Storage Client Library](#executing-a-point-query-using-the-storage-client-library) and [Retrieving multiple entities using LINQ](#retrieving-multiple-entities-using-linq).
1004+
If you know the type of the entity stored with a specific **RowKey** and **PartitionKey** values, then you can specify the entity type when you retrieve the entity as shown in the previous two examples that retrieve entities of type **EmployeeEntity**: [Executing a point query using the Storage client library](#executing-a-point-query-using-the-storage-client-library) and [Retrieving multiple entities using LINQ](#retrieving-multiple-entities-using-linq).
9831005

9841006
The second option is to use the **TableEntity** type (a property bag) instead of a concrete POCO entity type (this option may also improve performance because there is no need to serialize and deserialize the entity to .NET types). The following C# code potentially retrieves multiple entities of different types from the table, but returns all entities as **TableEntity** instances. It then uses the **EntityType** property to determine the type of each entity:
9851007

@@ -1031,7 +1053,7 @@ It is possible to generate a SAS token that grants access to a subset of the ent
10311053
Provided you are spreading your requests across multiple partitions, you can improve throughput and client responsiveness by using asynchronous or parallel queries.
10321054
For example, you might have two or more worker role instances accessing your tables in parallel. You could have individual worker roles responsible for particular sets of partitions, or simply have multiple worker role instances, each able to access all the partitions in a table.
10331055

1034-
Within a client instance, you can improve throughput by executing storage operations asynchronously. The Storage Client Library makes it easy to write asynchronous queries and modifications. For example, you might start with the synchronous method that retrieves all the entities in a partition as shown in the following C# code:
1056+
Within a client instance, you can improve throughput by executing storage operations asynchronously. The Storage client library makes it easy to write asynchronous queries and modifications. For example, you might start with the synchronous method that retrieves all the entities in a partition as shown in the following C# code:
10351057

10361058
```csharp
10371059
private static void ManyEntitiesQuery(TableClient employeeTable, string department)

0 commit comments

Comments
 (0)