Azure Blob Storage provides a powerful file storage API for saving files of any size that can then integrate with you application. A common request is being able to store simple metadata with the file and in the past I would create a simple database to store that data. Built-in to Azure Blob Storage is the ability to store metadata for the blobs usins a Key-Value-Pair of strings. This helps reduces software complexity while meeting the demands of metadata for blobs.
Read Metadata
When you are working with Blobs from Azure Blob Storage you can access the Metadata property, but if you try this it will return null. This is because the blob doesn’t fetch the Metadata unless you specifically request it. Consider the following code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Create a client reference to your instance of Azure Blob Storage
string connection = "YOUR_BLOB_STORAGE_CONNECTION_STRING";
CloudStorageAccount account = StorageAccount.Parse(connection);
CloudBlobClient client = account.CreateCloudBlobClient();
// Get your container
CloudBlobContainer container = client.GetContainerReference("my-container");
// Get your blob
CloudBlockBlob blob = container.GetBlockBlobReference("my-file-blob");
// Attempt to read metadata
// This will throw an exception as written
string myProperty = blob["MyProperty"];
To fix the this code, simply add the blob.FetchAttributes()
prior to accessing the Metadata
.
1
2
// NEW CODE
blob.FetchAttributes();
The Metadata
is an IDictionary<string, string>
and you can read properties using the indexer.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Create a client reference to your instance of Azure Blob Storage
string connection = "YOUR_BLOB_STORAGE_CONNECTION_STRING";
CloudStorageAccount account = StorageAccount.Parse(connection);
CloudBlobClient client = account.CreateCloudBlobClient();
// Get your container
CloudBlobContainer container = client.GetContainerReference("my-container");
// Get your blob
CloudBlockBlob blob = container.GetBlockBlobReference("my-file-blob");
// Fetch the metadata
blob.FetchAttributes();
// Attempt to read metadata
string myProperty = blob["MyProperty"]
Save or Update Metadata
Now that you have a basic application that is reading Metadata
from your individual blobs, let’s learn how we can save a new record or update an existing one. The workflow is almost identical to reading the Metadata
, except when you are done updating the IDictionary<string, string>
you need to invoke the save command.
Let’s take the snippet from earlier but we are just going to focus on the blob
and Metadata
.
1
2
3
4
5
6
7
8
// Get your blob
CloudBlockBlob blob = container.GetBlockBlobReference("my-file-blob");
// Fetch the metadata
blob.FetchAttributes();
// Attempt to read metadata
string myProperty = blob["MyProperty"]
Update Existing Property
Our code snippet assumes there is an existing property saved on our blob
called MyProperty
. If we want to change the value of it, we can use the indexer to update the value and then save it.
1
2
// Update MyProperty to "Life Through Code"
blob["MyProperty"] = "Life Through Code";
Once the value has been updated, invoke the Save Command.
1
2
// Invoke the save command on the blob
await blob.SetMetadataAsync();
Putting our entire code together, this is what your update should look like
1
2
3
4
5
6
7
8
9
10
11
// Get your blob
CloudBlockBlob blob = container.GetBlockBlobReference("my-file-blob");
// Fetch the metadata
blob.FetchAttributes();
// Update MyProperty to "Life Through Code"
blob["MyProperty"] = "Life Through Code";
// Invoke the save command on the blob
await blob.SetMetadataAsync();
Add New Property
To add new properties follows a similar workflow to updating existing properties except you need to use the Add(string key, string value)
method. Since Metadata
is an IDictionary<string, string>
you need to tell it to add the property. Once you are done adding your new properties and performing any other actions on your Metadata
, just invoke the Save Command as you did earlier.
Let’s add a new property with a key of BlogName and a value of SkyeThe.Dev
1
2
// Add new Metadata property called "BlogName"
blob.Add("BlogName", "SkyeThe.Dev");
Once we have added our property, just invoke the save command
1
2
// Invoke the save command
await blob.SetMetadataAsync();
Putting it all together
1
2
3
4
5
6
7
8
9
10
11
// Get your blob
CloudBlockBlob blob = container.GetBlockBlobReference("my-file-blob");
// Fetch the metadata
blob.FetchAttributes();
// Add new Metadata property called "BlogName"
blob.Add("BlogName", "SkyeThe.Dev");
// Invoke the save command
await blob.SetMetadataAsync();
Conclusion
Using the Metadata
is a straight forward technique to store additional information on each blob. This may decrease the need for an additional database when data can just be stored at the blob level. While this is a great technique, it is important to remember this is not a database replacement, here are some downsides to this.
- Searching and querying is slow, you are limited to the speed you can search blobs
- Bulk operations can be slow since your code will need to interact with each individual blob
When you are deciding if this is the right approach for your project you will need to weigh out the pros/cons of simplicity and performance. There is never a 1-size fits all for development, but you should have an understanding how to use this feature so you can try it out yourself.
-Happy Coding