2013-03-19 62 views
14

我真的很新的Windows Azure开发,并要求存储在Windows Azure存储表中的一些数据。正确的方式来删除和重新创建一个WIndows Azure存储表=错误409冲突 - 代码:TableBeingDeleted

该表格的真正目的只是为位于Azure存储驱动器上的某些文件提供快速查找机制。

因此我打算在应用填充此表启动(即Web应用程序的全球应用程序启动)

而不是试图维持该表的变化可能发生在驱动器,而应用程序的变化没有运行。或者,因为这个驱动器只是资源的一部分,我们可能偶尔会上传一个新的vhd。

所以,而不是试图维持这一点的麻烦。在每次应用程序启动时重建此表就足够了。

我开始把一些代码放在一起来检查表是否已经存在,以及它是否删除它,然后重新创建一个新表。

var storageAccount = CloudStorageAccount.Parse(ConfigurationManager.ConnectionStrings["AzureStorage"].ConnectionString); 
var tableClient = storageAccount.CreateCloudTableClient(); 
var rmsTable = tableClient.GetTableReference("ResourceManagerStorage"); 
rmsTable.DeleteIfExists(); 
rmsTable.Create(); 

我原本以为这是行不通的。我得到以下错误:

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 

这样做的正确方法是什么?是否有可以订阅的事件,以便在表格被删除时通知您?还有关于实施这个最佳方式的其他建议吗?

回答

25

MSDN:“请注意,删除表可能需要至少40秒才能完成。如果在删除表时尝试对该表执行操作,则该服务会返回状态代码409(冲突)错误信息表明该表正在被删除。“

解决此问题的唯一方法是创建一个不同名称的表。这可能很简单,只需将时间戳或GUID添加到您的姓名即可。小心清理垃圾。

+0

或者,您可以等待并重试,直到创建命令成功 – Igorek 2013-03-19 20:02:22

+2

根据表的大小和许多其他因素,这可能是一个非常长时间。 – IngisKahn 2013-03-19 20:14:50

+0

这是真的,感谢纠正 – Igorek 2013-03-19 20:16:56

12

如果需要使用相同的表名,你可以使用扩展方法:

public static class StorageExtensions 
{ 
    public static bool SafeCreateIfNotExists(this CloudTable table, TableRequestOptions requestOptions = null, OperationContext operationContext = null) 
    { 
     do 
     { 
      try 
      { 
       return table.CreateIfNotExists(requestOptions, operationContext); 
      } 
      catch (StorageException e) 
      { 
       if ((e.RequestInformation.HttpStatusCode == 409) && (e.RequestInformation.ExtendedErrorInformation.ErrorCode.Equals(TableErrorCodeStrings.TableBeingDeleted))) 
        Thread.Sleep(1000);// The table is currently being deleted. Try again until it works. 
       else 
        throw; 
      } 
     } while (true); 
    } 
} 

警告!当你使用这种方法时要小心,因为它会阻塞线程。如果第三方服务(Azure)不断产生这些错误,它可以进入死循环。原因可能是表锁定,订阅到期,服务不可用等。

+3

哇,这不是一个好主意。通常,当逻辑依赖于第三方服务时,我会尽量避免(真)。而(retryCnt> 0)在这里会更好。 – 2015-05-21 17:23:50

+1

当然,你可以通过一些超时参数或硬编码一些超时。但是,你会建议什么价值? 1分钟,2分钟,20分钟? IngisKahn说:“......可能需要至少40秒才能完成。”所以你需要一些很高的价值,你永远不知道如果你等待了一秒钟,这个过程是否会结束。如果服务不可用或存在其他问题,我不能想象MS会返回相同的错误TableErrorCodeStrings.TableBeingDeleted。所以如果有人增加超时我建议一个相当高的价值。 – huha 2015-05-22 07:59:59

+0

你可以使方法异步并用'await Task.Delay(2000)'替换'Thread.Sleep(2000)' - 线程不会被这种方式阻塞。 – UserControl 2018-02-02 17:33:09

相关问题