2016-11-18 69 views
0

我發送某個服務的查詢並取回結果。我想知道我過去是否已經得到相同的「答案」。所以,我打算使用Azure Table作爲緩存機制。Azure存儲表 - 插入批次行並檢查它們是否存在

我做這個小POC:

TableBatchOperation batchOperation = new TableBatchOperation(); 
CachedUrl customer1 = new CachedUrl(Guid.Empty, "test1"); 
CachedUrl customer2 = new CachedUrl(Guid.Empty, "test2"); 
batchOperation.Insert(customer1); 
batchOperation.Insert(customer2); 
table.ExecuteBatch(batchOperation); 

當我運行在第一時間將此代碼,它的正常工作。在這最後,我在桌上有兩排。

問題出在第二次運行。當我執行此代碼:

TableBatchOperation batchOperation = new TableBatchOperation(); 
CachedUrl customer1 = new CachedUrl(Guid.Empty, "test1"); 
CachedUrl customer2 = new CachedUrl(Guid.Empty, "test2"); 
CachedUrl customer3 = new CachedUrl(Guid.Empty, "test3"); 
batchOperation.Insert(customer1); 
batchOperation.Insert(customer2); 
batchOperation.Insert(customer3); 
table.ExecuteBatch(batchOperation); 

customer3附加)

期望得到是說一個消息:

  • customer1表 - 存在
  • customer2 - exists
  • customer3 - 添加

我其實得到的是這個異常(在ExecuteBatch()法):

索取資料請求ID:5116ee8a-0002-0024-7ac1-415787000000 RequestDate:星期五,2016年11月18日17:33:08 GMT狀態消息:0:指定實體 已存在。 ErrorCode:EntityAlreadyExists

服務器發現#1實體存在,因此,跳過整個任務。

我該如何得到預期的答案?

天真的解決方案,是嘗試添加所有N個項目,一個接一個。但是這個解決方案是最慢的一個(N個HTTP請求,而不是1個請求)。

回答

0

這是預期的行爲。只要該批次中的任何實體出現故障,整批就會失敗。

您可以使用的一種可能是使用InsertOrReplace方法而不是Insert。這將更新實體,如果它存在,否則插入實體。

documentation

添加一個TableOperation到插入 指定的實體到一個表,如果實體不存在的TableBatchOperation;如果 實體確實存在,則其內容將被提供的 實體替換。

+0

?通過這種方式,在執行命令後,我無法知道這些項目是新添加的還是剛剛被替換的... – No1Lives4Ever

+0

我不相信有方法可以判斷實體是被替換還是隻是被激活。也許表格存儲不適合你正在嘗試做的事情。你考慮過其他選擇嗎? –

2

Azure表存儲批處理操作是原子操作,因此預計將在第一次失敗操作時返回。批處理操作可能包含1000個操作,表服務在檢測到第一個故障後繼續執行所有操作的點並不多。

存儲異常返回批處理中失敗操作的實際索引以及與此相關的錯誤。

在失敗操作的指數下方的例子是0和錯誤是EntityAlreadyExists:

:指定的實體已經存在。 ErrorCode:EntityAlreadyExists

您可以編寫一個重試邏輯,捕獲StorageException,解析錯誤,如果錯誤爲EntityAlreadyExists,則從批處理中刪除具有該索引的操作並重新提交批處理操作。

見Azure存儲異常解析器我的NuGet實現從StorageException對象提取失敗的操作和其他有用的信息的索引像HttpStatusCode你:https://www.nuget.org/packages/AzureStorageExceptionParser/

爲了避免多次來回通話對於每個失敗的操作,以下是一個替代解決方案,您可以探索:

每次向表中插入實體時,還會插入第二個實體,其中只包含行鍵的一個屬性。讓我們調用這個第二個實體RowKeyTracker實體。它將與原始實體具有相同的分區鍵,以便您可以執行批處理操作。它將有一個唯一的行鍵,以便查詢它,並且它將具有一個屬性,該屬性是該分區的附加行鍵。如果RowKeyTracker實體已經存在,則每次插入新實體時,只需將新行鍵添加到該分區鍵的行鍵屬性中,反之亦然;當刪除實體時,也可以繼續,並從RowKeyTracker中刪除該行鍵實體。

因此,您可以使用此行密鑰跟蹤器實體,通過先查詢它是否已經插入該分區的行密鑰。

您可以使用如何`InsertOrReplace`可以解決我的問題,這種方法與第一種方法(試)相結合,有一個更強大的解決方案

相關問題