September 21st, 2021

Announcing the Preview Release for Azure Tables for Go

Sean Kane
Software Engineer

We’re excited to announce that the Azure Tables library’s first beta for Go is now in preview release. The Azure Table service stores NoSQL data in the cloud with a key/attribute store schema-less design. The Table storage service can be used to store flexible data sets, such as, user data for web applications, address books, device information, or other types of metadata.

The new libraries follow our Azure SDK Guidelines, making for an idiomatic, consistent, approachable, diagnosable, and dependable library. The new libraries use the language-specific Azure Core packages for handling requests, errors, and credentials.

Note: The Azure Tables libraries are capable of targeting both Azure Storage Table and Azure Cosmos DB Table API endpoints.

SDK Availability

The Azure Tables libraries can be downloaded using:

go get github.com/Azure/azure-sdk-for-go/sdk/data/aztables

This blog post assumes you have a working developer environment for Go 1.16 and above and you already have an Azure Storage or Cosmos Table account. “`

Creating the clients

There are two clients for interacting with the service. The ServiceClient can be used for account-level interactions (creating tables, setting and getting access policies) and the Client is used for table-level interactions (create or delete an entity, query, or list entities). You can create clients with an account key, Shared Access Signature, or using a connection string, all of which can be found in the Azure portal. Throughout the examples, the handle(err) function is used to demonstrate where you can insert your own error handling logic.

cred, err := aztables.NewSharedKeyCredential("myAccountName", "myAccountKey")
handle(err)
options := &aztables.ClientOptions{} //Optional configuration of the Transporter, Retry policies, Telemetry options, or PerCallOptions
client, err := aztables.NewClient("https://myAccountName.table.core.windows.net/myTableName", cred, options)
handle(err)
// ServiceClients can be created in a very similar manner:
serviceClient, err := aztables.NewServiceClient("https://myAccountName.table.core.windows.net", cred, options)
handle(err)

// You can also use a connection string to create a ServiceClient
serviceClient, err := aztables.NewServiceClientFromConnectionString("my-connection-string", azcore.AnonymousCredential(), options)
handle(err)

Create a table and add an entity to it

Table names can be any alphanumeric string between 3 and 63 characters. A table can be created from either the Client or the ServiceClient, the following snippets will show how to create one from a Client.

An Entity can contain up to 255 properties, with the three system properties of PartitionKey, RowKey, and Timestamp. The first two properties must be provided on all entities and the Timestamp property will be modified by the service. For more information, see the service documentation. Entities can only be inserted and queried from the Client. Entities are returned via JSON allowing customers to use normal JSON marshaling and unmarshaling techniques (map[string]interface{}, map[string]json.RawMessage, or a specific struct instance). The aztables library also provides an EDMEntity struct (and EDMGUID, EDMBinary, EDMInt64, EDMDateTime types) to make it easier to parse an entity to an object and to dynamically discover the object’s fields and data types at runtime.

There are three ways to create an entity: a custom entity, using aztables.Entity, and using aztables.EdmEntity.

cred, err := aztables.NewSharedKeyCredential("myAccountName", "myAccountKey")
handle(err)
client, err := aztables.NewClient("https://myAccountName.table.core.windows.net/myTableName", cred, nil)
handle(err)

resp, err := client.Create(context.Background())
handle(err)

myEntity3 := aztables.EDMEntity{
    Entity: aztables.Entity{
        PartitionKey: "pencils",
        RowKey: "id-003",
    },
    Properties: map[string]interface{}{
        "Product": "Ticonderoga Pencils",
        "Price": 5.00,
        "Count": aztables.EDMInt64(12345678901234),
        "ProductGUID": aztables.EDMGUID("some-guid-value"),
        "DateReceived": aztables.EDMDateTime(time.Date{....}),
        "ProductCode": aztables.EDMBinary([]byte{"somebinaryvalue"})
    }
}

marshalled3, err := json.Marshal(myEntity3)
handle(err)

resp, err := client.AddEntity(context.Background(), marshalled3, nil)
handle(err)

Querying Table Entities

The Client allows the user to create custom queries using OData filters. Check out the service documentation for more information about creating filters.

cred, err := aztables.NewSharedKeyCredential("myAccountName", "myAccountKey")
handle(err)
client, err := aztables.NewClient("https://myAccountName.table.core.windows.net/myTableName", cred, nil)
handle(err)

filter := "PartitionKey eq 'markers' or RowKey eq 'id-001'"
options := &ListEntitiesOptions{
    Filter: &filter,
    Select: to.StringPtr("RowKey,Value,Product,Available"),
    Top: to.Int32Ptr(15),
}

pager := client.List(options)
for pager.NextPage(context.Background()) {
    resp := pager.PageResponse()
    fmt.Printf("Received: %v entitiesn", len(resp.Entities))

    for _, entity := range resp.Entities {
        var myEntity aztables.EDMEntity
        err = json.Unmarshal(entity, &myEntity)
        handle(err)

        fmt.Printf("Received: %v, %v, %v, %vn", myEntity.Properties["RowKey"], myEntity.Properties["Value"], myEntity.Properties["Product"], myEntity.Properties["Available"])
    }
}

err := pager.Err()
handle(err)

Batch Transactions

The Table service allows multiple entity operations (create, delete, update, and upsert) to be made in a single request using transactional batch operations. The transaction is an “all-or-nothing” approach, if there’s a failure in one of the operations, the entire operation will fail. A transaction can do a combination of create, delete, update, and upsert operations.

Note: All operations within a transaction must target the same partition key. A row key can only be specified once in a transaction.

cred, err := aztables.NewSharedKeyCredential("myAccountName", "myAccountKey")
handle(err)
client, err := aztables.NewClient("https://myAccountName.table.core.windows.net/myTableName", cred, nil)
handle(err)

batch := make([]aztables.TableTransactionAction, 4)

type ProductEntity struct {
    aztables.Entity
    Product string
    Price float32
    Brand string
}

myentity1 := ProductEntity{
    aztables.Entity: aztables.Entity{
        PartitionKey: "Marker",
        RowKey: "id-001",
    },
    Product: "Crayola Markers",
    Price: 1.99,
    Brand: "Crayola",
}
marshalled1, err := json.Marshal(myEntity1)
handle(err)
batch[0] = aztables.TransactionAction{ActionType: aztables.Add, Entity: marshalled1}

myentity2 := ProductEntity{
    aztables.Entity: aztables.Entity{
        PartitionKey: "Pencil",
        RowKey: "id-002",
    },
    Product: "Classic Pencils",
    Price: .99,
    Brand: "Ticonderoga",
}
marshalled2, err := json.Marshal(myEntity2)
handle(err)
batch[1] = aztables.TransactionAction{ActionType: aztables.Delete, Entity: marshalled2}

myentity3 := ProductEntity{
    aztables.Entity: aztables.Entity{
        PartitionKey: "Pen",
        RowKey: "id-003",
    },
    Product: "Pilot G2",
    Price: 4.99,
    Brand: "Pilot",
}
marshalled3, err := json.Marshal(myEntity3)
handle(err)
batch[2] = aztables.TransactionAction{ActionType: aztables.InsertMerge, Entity: marshalled3}

myentity4 := ProductEntity{
    aztables.Entity: aztables.Entity{
        PartitionKey: "Eraser",
        RowKey: "id-004",
    },
    Product: "Expo Eraser",
    Price: 3.49,
    Brand: "Expo",
}
marshalled4, err := json.Marshal(myEntity4)
handle(err)
batch[3] = aztables.TransactionAction{ActionType: aztables.UpdateReplace, Entity: marshalled4}

resp, err := client.SubmitTransaction(context.Background(), batch, nil)
handle(err)

Conclusion

We hope this post was a valuable technical introduction to the Azure Table service and what you can use today to build and ship rich experiences. We welcome feedback and suggestions, to submit an issue visit our GitHub repository

References

Azure SDK Blog Contributions

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. Contact us at azsdkblog@microsoft.com and we’ll set you up as a guest blogger.

Azure SDK Links

Author

Sean Kane
Software Engineer

Software Engineer on the Azure SDK for Go Team

0 comments

Discussion are closed.