[Azure] C# + Microsoft.Azure.Cosmos.Table v1+ Azure Storage Table - 建立 Table,刪除 Table,建立(修改)資料,列出資料,刪除資料,刪除資料 by PartitionKey
最近有需要要用到 Azure Storage Table,有鑑於
https://www.nuget.org/packages/WindowsAzure.Storage/ 這套已經要被棄用了,所以我找了一下,竟然找不到 library
,他都是導向 https://www.nuget.org/packages/Microsoft.Azure.Cosmos.Table ,之後我就把
ConnectionString 放入操作了一下,竟然可以用,真的是太令人驚訝了,所以接下來的幾篇文章我們來探索一下。
前置作業 首先你要 安裝 nuget
https://www.nuget.org/packages/Microsoft.Azure.Cosmos.Table ,這邊我撰寫案例是用 .net core
3.1;在 Azure Portal 開一個 儲存體帳戶,並且在左側的存取金鑰中拿到 Connection String.
1. 建立 table
//https://docs.microsoft.com/en-us/rest/api/storageservices/Delete-Table?redirectedfrom=MSDN | |
//delete may use 40s , create after deleting should be waiting for 40s. | |
var storageAccount = CloudStorageAccount.Parse(_ConnectionString); | |
var tableClient = storageAccount.CreateCloudTableClient(new TableClientConfiguration()); | |
var table = tableClient.GetTableReference(tableName); | |
if (table.CreateIfNotExists()) | |
{ | |
Console.WriteLine("SUCCESS !!"); | |
} | |
else | |
{ | |
Console.WriteLine("ALREADY EXISTED."); | |
} | |
這邊需要注意的,如果你刪除這張表,你又馬上在建立,會出現 Exception
Unhandled exception. Microsoft.Azure.Cosmos.Table.StorageException: Conflict
at Microsoft.Azure.Cosmos.Table.RestExecutor.TableCommand.Executor.ExecuteAsync[T](RESTCommand`1 cmd, IRetryPolicy policy, OperationContext operationContext, CancellationToken callerCancellationToken)
at Microsoft.Azure.Cosmos.Table.RestExecutor.TableCommand.Executor.<>c__DisplayClass0_0`1.<ExecuteSync>b__0()
at Microsoft.Azure.Cosmos.Table.RestExecutor.Utils.RestUtility.RunWithoutSynchronizationContext[T](Func`1 actionToRun)
at Microsoft.Azure.Cosmos.Table.RestExecutor.TableCommand.Executor.ExecuteSync[T](RESTCommand`1 cmd, IRetryPolicy policy, OperationContext operationContext)
at Microsoft.Azure.Cosmos.Table.RestExecutor.TableRestExecutor.ExecuteTableOperation[TResult](TableOperation operation, CloudTableClient client, CloudTable table, TableRequestOptions requestOptions, OperationContext
operationContext)
at Microsoft.Azure.Cosmos.Table.TableOperation.Execute(CloudTableClient client, CloudTable table, TableRequestOptions requestOptions, OperationContext operationContext)
at Microsoft.Azure.Cosmos.Table.CloudTable.Create(TableRequestOptions requestOptions, OperationContext operationContext, String serializedIndexingPolicy, Nullable`1 throughput, Nullable`1 defaultTimeToLive)
at Microsoft.Azure.Cosmos.Table.CloudTable.CreateIfNotExists(TableRequestOptions requestOptions, OperationContext operationContext, String serializedIndexingPolicy, Nullable`1 throughput, Nullable`1 defaultTimeToLive)
at TestAzureStorageTable2020.Program.CreateTable(String tableName) in C:\Users\donma\source\repos\TestAzureStorageTable2020\TestAzureStorageTable2020\Program.cs:line 72
at TestAzureStorageTable2020.Program.Main(String[] args) in C:\Users\donma\source\repos\TestAzureStorageTable2020\TestAzureStorageTable2020\Program.cs:line 40
Request Information
RequestID:7b683220-d002-0066-7622-e31c6e000000
RequestDate:Tue, 05 Jan 2021 05:21:49 GMT
StatusMessage:Conflict
ErrorCode:
ErrorMessage:The specified table is being deleted. Try operation later.
這邊注意,大概需要 40 秒的時間給 Azure CD ?
2.刪除 Table
var storageAccount = CloudStorageAccount.Parse(_ConnectionString); | |
var tableClient = storageAccount.CreateCloudTableClient(new TableClientConfiguration()); | |
var res = tableClient.GetTableReference(tableName).DeleteIfExists(); | |
if (res) | |
{ | |
Console.WriteLine("SUCCESS !!"); | |
} | |
else | |
{ | |
Console.WriteLine("NO EXISTED TABLE."); | |
} | |
3.建立資料,這邊有點點跟SQL 想法不同,首先你建立一個物件,必須要繼承 Microsoft.Azure.Cosmos.Table.TableEntity, 這時候因為繼承關係,你就會 擁有這些 Property
ETag
獲取或設置實體的ETag。將此值設置為“ *”,以作為更新操作的一部分強制覆蓋實體。
PartitionKey
分區Key
RowKey
在我的理解,它是在 PartitionKey 下的 Key
Timestamp
時間戳,通常這是 Azure Storage Table 寫入時會自動寫入的
繼承 Microsoft.Azure.Cosmos.Table.TableEntity 後 就可以寫入
var tableClient = CloudStorageAccount.Parse(_ConnectionString).CreateCloudTableClient(new TableClientConfiguration()); | |
var table = tableClient.GetTableReference("table1"); | |
for (var i = 1; i <= 100; i++) | |
{ | |
var sampleObject = new User("CLASSA", "DATAKEY" + i) | |
{ | |
Name = "DONMA" + i, | |
Age = i, | |
Create = new DateTime(2010, 1, 1).AddDays(i) | |
}; | |
var upsertOperation = TableOperation.InsertOrReplace(sampleObject); | |
var result = table.Execute(upsertOperation); | |
Console.WriteLine("PartitionKey:" + (result.Result as User).PartitionKey + "," + | |
"RowKey:" + (result.Result as User).RowKey + "," + | |
"ETag:" + result.Etag); | |
} | |
public class User : Microsoft.Azure.Cosmos.Table.TableEntity | |
{ | |
public string Name { get; set; } | |
public int Age { get; set; } | |
public DateTime Create { get; set; } | |
public List<User> Friends { get; set; } | |
public User() { | |
Friends = new List<User>(); | |
} | |
public User(string classId, string userId) | |
{ | |
PartitionKey = classId; | |
RowKey = userId; | |
Friends = new List<User>(); | |
} | |
} | |
這裡我的 PartitionKey 都是設定成 CLASSA , RowKey 則為 DATAKEY1~DATAKEY100
4. 列出所有資料
var tableClient = CloudStorageAccount.Parse(_ConnectionString).CreateCloudTableClient(new TableClientConfiguration()); | |
var table = tableClient.GetTableReference("table1"); | |
var queryResult = table.ExecuteQuery(new TableQuery<User>(), null); | |
var count = 0; | |
foreach (var data in queryResult) | |
{ | |
Console.WriteLine(JsonConvert.SerializeObject(data)); | |
count++; | |
} | |
Console.WriteLine("--"); | |
Console.WriteLine("DATA COUNT:" + count); | |
5.刪除單一檔案,案例為 PartitionKey : CLASSA , RowKey : DATAKEY11
var tableClient = CloudStorageAccount.Parse(_ConnectionString).CreateCloudTableClient(new TableClientConfiguration()); | |
var table = tableClient.GetTableReference("table1"); | |
try | |
{ | |
var deleteReult = table.Execute(TableOperation.Delete(new TableEntity { RowKey = "DATAKEY11", PartitionKey = "CLASSA", ETag = "*" })); | |
Console.WriteLine("SUCCESS"); | |
} | |
catch (Exception ex) | |
{ | |
Console.WriteLine("Error:" + ex.Message); | |
} | |
6. 刪除資料 by PartitionKey ,撈出所有 PartitionKey 為 CLASSA ,的資料後刪除所有,這邊是先撈取再刪除,撈取時候使用 GenerateFilterCondition 只撈取 PartitionKey , RowKey 減少回傳量,之後再使用 TableBatchOperation , ExecuteBatch 進行批次刪除
var tableClient = CloudStorageAccount.Parse(_ConnectionString).CreateCloudTableClient(new TableClientConfiguration()); | |
var table = tableClient.GetTableReference("table1"); | |
var queryAllRowKeysByPK = new TableQuery().Where(TableQuery.GenerateFilterCondition("PartitionKey", | |
QueryComparisons.Equal, "CLASSA")).Select(new[] { "RowKey" }); | |
var entities = table.ExecuteQuery(queryAllRowKeysByPK); | |
var batch = new TableBatchOperation(); | |
foreach (var wannaDeleteData in entities) | |
{ | |
batch.Add(TableOperation.Delete(wannaDeleteData)); | |
} | |
try | |
{ | |
table.ExecuteBatch(batch); | |
Console.WriteLine("SUCCESS"); | |
} | |
catch (Exception ex) | |
{ | |
Console.WriteLine("Error:" + ex.Message); | |
} | |
reference:
https://docs.microsoft.com/en-us/rest/api/storageservices/Delete-Table?redirectedfrom=MSDN
https://raflrx.wordpress.com/2017/09/29/batch-delete-entities-in-azure-table-storage/
https://stackoverflow.com/questions/26326413/delete-all-azure-table-records
https://stackoverflow.com/questions/168901/count-the-items-from-a-ienumerablet-without-iterating
https://stackoverflow.com/questions/62945338/azure-c-sharp-function-how-to-read-from-table-storage
https://docs.microsoft.com/en-us/rest/api/storageservices/Delete-Table?redirectedfrom=MSDN