Im really new to Windows Azure development and have a requirement to store some data in a windows azure storage table.
This table will really only exist to provide a quick lookup mechanism to some files which are located on azure storage drive.
Therefore I was planning on populating this table at application start up (ie in web application global application start up)
Rather than trying to maintain this table for changes the changes that could occur to the drive while the application is not running. Or as this drive is just a vhd of resources, we may well occasionally upload a new vhd.
So rather than the hassle of trying to maintain this. it is sufficient that this table be rebuild upon each application start.
I started to put together some code to check if the table already exists , and if it does delete it, and then recreate a new table.
var storageAccount = CloudStorageAccount.Parse(ConfigurationManager.ConnectionStrings["AzureStorage"].ConnectionString);
var tableClient = storageAccount.CreateCloudTableClient();
var rmsTable = tableClient.GetTableReference("ResourceManagerStorage");
rmsTable.DeleteIfExists();
rmsTable.Create();
I had expected this would not work. And I get the following error:
The remote server returned an error: (409) Conflict.
HTTP/1.1 409 Conflict
Cache-Control: no-cache
Transfer-Encoding: chunked
Server: Windows-Azure-Table/1.0 Microsoft-HTTPAPI/2.0
x-ms-request-id: c6baf92e-de47-4a6d-82b3-4faec637a98c
x-ms-version: 2012-02-12
Date: Tue, 19 Mar 2013 17:26:25 GMT
166
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<error xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
<code>TableBeingDeleted</code>
<message xml:lang="en-US">The specified table is being deleted. Try operation later.
RequestId:c6baf92e-de47-4a6d-82b3-4faec637a98c
Time:2013-03-19T17:26:26.2612698Z</message>
</error>
0
What is the correct way of doing this? Is there an event which can be subscribed to to let you know when the table as been deleted? ANy other suggestions on the best way to implement this?
From MSDN: "Note that deleting a table is likely to take at least 40 seconds to complete. If an operation is attempted against the table while it was being deleted, the service returns status code 409 (Conflict), with additional error information indicating that the table is being deleted."
The only way to deal with this is to create a table with a different name. This could be as simple as appending a timestamp or GUID to your name. Just be careful to clean up your garbage.
If you need to use the same table name you can use an extension method:
public static class StorageExtensions
{
#region Non-async
public static bool SafeCreateIfNotExists(this CloudTable table, TimeSpan? timeout, TableRequestOptions requestOptions = null, OperationContext operationContext = null)
{
Stopwatch sw = Stopwatch.StartNew();
if (timeout == null) timeout = TimeSpan.FromSeconds(41); // Assuming 40 seconds max time, and then some.
do
{
if (sw.Elapsed > timeout.Value) throw new TimeoutException("Table was not deleted within the timeout.");
try
{
return table.CreateIfNotExists(requestOptions, operationContext);
}
catch (StorageException e) when(IsTableBeingDeleted(e))
{
Thread.Sleep(1000);
}
} while (true);
}
#endregion
#region Async
public static async Task<bool> SafeCreateIfNotExistsAsync(this CloudTable table, TimeSpan? timeout, TableRequestOptions requestOptions = null, OperationContext operationContext = null, CancellationToken cancellationToken = default)
{
Stopwatch sw = Stopwatch.StartNew();
if (timeout == null) timeout = TimeSpan.FromSeconds(41); // Assuming 40 seconds max time, and then some.
do
{
if (sw.Elapsed > timeout.Value) throw new TimeoutException("Table was not deleted within the timeout.");
try
{
return await table.CreateIfNotExistsAsync(requestOptions, operationContext, cancellationToken).ConfigureAwait(false);
}
catch (StorageException e) when(IsTableBeingDeleted(e))
{
// The table is currently being deleted. Try again until it works.
await Task.Delay(1000);
}
} while (true);
}
#endregion
private static bool IsTableBeingDeleted(StorageException e)
{
return
e.RequestInformation.HttpStatusCode == 409
&&
e.RequestInformation.ExtendedErrorInformation.ErrorCode.Equals( TableErrorCodeStrings.TableBeingDeleted );
}
}
WARNING! Be careful when you use this approach, because it blocks the thread. And it can go to the dead loop if third-party service (Azure) keeps generating these errors. The reason for this could be table locking, subscription expiration, service unavailability, etc.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With