2013-03-19 50 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

相關問題