Azure Storage 系列(四)在.Net 上使用Table Storage
一,引言
今天我們就不多說廢話了,直接進入正題,Azure Table Storage。開始內容之前,我們先介紹一下Azure Table Storage.
1,什麼是Azure Table Storage
答:Azure Table Storage 是儲存結構化的 NoSql 資料的服務,通過無架構設計提供鍵/屬性儲存。 因為表儲存無架構,因此可以很容易地隨著應用程式需求的發展使資料適應儲存。 對於許多型別的應用程式來說,訪問表儲存資料速度快且經濟高效,在資料量相似的情況下,其成本通常比傳統 SQL 要低(官方解釋)。簡單來說,Azure Table Srorage 可以直接將實體,實體物件存入表結構中,和一般的關係型資料庫的 Table 很像,包含了列名和行資料,但是它不能提供像SQL中 inner join 方法,也是不能管理 Foreign Key。
--------------------我是分割線--------------------
Azure Storage 儲存系列:
1,Azure Storage 系列(一)入門簡介
2,Azure Storage 系列(二) .NET Core Web 專案中操作 Blob 儲存
3,Azure Storage 系列(三)Blob 引數設定說明
4,Azure Storage 系列(四)在.Net 上使用Table Storage
二,正文
1,新增對 Table Storage 的 “增,刪,改,查” 方法
1.1,安裝 Azure.TableStorage 相關的 Nuget 包,
NuGet:WindowsAzure.Storage(此包已被啟用,推薦使用 “Microsoft.Azure.Cosmos.Table”,今天作為演示,就暫時使用當前已經遺棄的包)
Install-Package WindowsAzure.Storage -Version 9.3.3
從9.4.0版本開始,此庫已分為多個部分並被替換。大家可以通過當前連結進行檢視當前庫的狀態:https://www.nuget.org/packages/WindowsAzure.Storage
1.2,建立 ITableService 介面,和 TableService 實現類,以及新增相應的對 Table 操作的方法
新增Table資料操作
public async Task AddEntity(UserInfo user) { var cloudTableClient = _cloudStorageClient.CreateCloudTableClient(); var cloudTable = cloudTableClient.GetTableReference("USERINFO"); await cloudTable.CreateIfNotExistsAsync(); var tableOperation = TableOperation.Insert(user); await cloudTable.ExecuteAsync(tableOperation); }
批量新增 Table 表資料
public async Task BatchAddEntities(List<UserInfo> users) { var cloudTableClient = _cloudStorageClient.CreateCloudTableClient(); var cloudTable = cloudTableClient.GetTableReference("USERINFO"); await cloudTable.CreateIfNotExistsAsync(); var tableBatchOperation = new TableBatchOperation(); foreach (UserInfo item in users) { tableBatchOperation.Insert(item); } await cloudTable.ExecuteBatchAsync(tableBatchOperation); }
修改 Table 表資料
public async Task UpdateEntity(UserInfo user) { var cloudTableClient = _cloudStorageClient.CreateCloudTableClient(); var cloudTable = cloudTableClient.GetTableReference("USERINFO"); var queryOperation = TableOperation.Retrieve<UserInfo>(user.PartitionKey, user.RowKey); var tableResult = await cloudTable.ExecuteAsync(queryOperation); if (tableResult.Result is UserInfo userInfo) { user.ETag = userInfo.ETag; var deleteOperation = TableOperation.Replace(user); await cloudTable.ExecuteAsync(deleteOperation); } }
查詢Table 表資料
public async IAsyncEnumerable<UserInfo> QueryUsers(string filter) { var cloudTableClient = _cloudStorageClient.CreateCloudTableClient(); var cloudTable = cloudTableClient.GetTableReference("USERINFO"); TableQuery<UserInfo> query = new TableQuery<UserInfo>().Where(filter); var users = await cloudTable.ExecuteQuerySegmentedAsync<UserInfo>(query, null); foreach (var item in users) { yield return item; } }
刪除 Table 表資料
public async Task DeleteEntity(UserInfo user) { var cloudTableClient = _cloudStorageClient.CreateCloudTableClient(); var cloudTable = cloudTableClient.GetTableReference("USERINFO"); var queryOperation = TableOperation.Retrieve<UserInfo>(user.PartitionKey, user.RowKey); var tableResult = await cloudTable.ExecuteAsync(queryOperation); if (tableResult.Result is UserInfo userInfo) { var deleteOperation = TableOperation.Delete(userInfo); await cloudTable.ExecuteAsync(deleteOperation); } }
刪除 Table 表
public async Task DeleteTable(string tableName) { var cloudTableClient = _cloudStorageClient.CreateCloudTableClient(); var cloudTable = cloudTableClient.GetTableReference(tableName); await cloudTable.DeleteIfExistsAsync(); }
1.3,新增對 TableService ,CloudStorageAccount 的注入
services.AddSingleton(x => new CloudStorageAccount(new StorageCredentials("cnbateblogaccount", "FU01h022mn1JjONp+ta0DAXOO7ThK3diYhsdsdm0Hpg891n9nycsTLGZF83nJpGvTIZvsdsdVCVFhGOfV0wndOOQ=="), true)); services.AddSingleton<ITableService, TableService>();
完整程式碼
1 public class TableService : ITableService 2 { 3 private readonly CloudStorageAccount _cloudStorageClient; 4 public TableService(CloudStorageAccount cloudStorageClient) 5 { 6 _cloudStorageClient = cloudStorageClient; 7 } 8 9 #region 01,新增表資料+async Task AddEntity(UserInfo user) 10 /// <summary> 11 /// 新增表資料 12 /// </summary> 13 /// <param name="user">使用者資料</param> 14 /// <returns></returns> 15 public async Task AddEntity(UserInfo user) 16 { 17 var cloudTableClient = _cloudStorageClient.CreateCloudTableClient(); 18 var cloudTable = cloudTableClient.GetTableReference("USERINFO"); 19 await cloudTable.CreateIfNotExistsAsync(); 20 21 var tableOperation = TableOperation.Insert(user); 22 await cloudTable.ExecuteAsync(tableOperation); 23 } 24 #endregion 25 26 #region 02,批量新增使用者表資料+async Task BatchAddEntities(List<UserInfo> users) 27 /// <summary> 28 /// 批量新增使用者表資料 29 /// </summary> 30 /// <param name="users">使用者資料</param> 31 /// <returns></returns> 32 public async Task BatchAddEntities(List<UserInfo> users) 33 { 34 var cloudTableClient = _cloudStorageClient.CreateCloudTableClient(); 35 var cloudTable = cloudTableClient.GetTableReference("USERINFO"); 36 await cloudTable.CreateIfNotExistsAsync(); 37 38 var tableBatchOperation = new TableBatchOperation(); 39 foreach (UserInfo item in users) 40 { 41 tableBatchOperation.Insert(item); 42 } 43 44 await cloudTable.ExecuteBatchAsync(tableBatchOperation); 45 } 46 #endregion 47 48 #region 03,刪除表操作根據表名+async Task DeleteTable(string tableName) 49 /// <summary> 50 /// 刪除表操作根據表名 51 /// </summary> 52 /// <param name="tableName">表命</param> 53 /// <returns></returns> 54 public async Task DeleteTable(string tableName) 55 { 56 var cloudTableClient = _cloudStorageClient.CreateCloudTableClient(); 57 var cloudTable = cloudTableClient.GetTableReference(tableName); 58 await cloudTable.DeleteIfExistsAsync(); 59 } 60 #endregion 61 62 #region 04,刪除使用者資料根據使用者條件+async Task DeleteEntity(UserInfo user) 63 /// <summary> 64 /// 刪除使用者資料根據使用者條件 65 /// </summary> 66 /// <param name="user">使用者條件</param> 67 /// <returns></returns> 68 public async Task DeleteEntity(UserInfo user) 69 { 70 var cloudTableClient = _cloudStorageClient.CreateCloudTableClient(); 71 var cloudTable = cloudTableClient.GetTableReference("USERINFO"); 72 73 var queryOperation = TableOperation.Retrieve<UserInfo>(user.PartitionKey, user.RowKey); 74 75 var tableResult = await cloudTable.ExecuteAsync(queryOperation); 76 if (tableResult.Result is UserInfo userInfo) 77 { 78 var deleteOperation = TableOperation.Delete(userInfo); 79 await cloudTable.ExecuteAsync(deleteOperation); 80 } 81 } 82 #endregion 83 84 #region 05,查詢使用者根據條件+async IAsyncEnumerable<UserInfo> QueryUsers(string filter) 85 /// <summary> 86 /// 查詢使用者根據條件 87 /// </summary> 88 /// <param name="filter">條件</param> 89 /// <returns></returns> 90 public async IAsyncEnumerable<UserInfo> QueryUsers(string filter) 91 { 92 var cloudTableClient = _cloudStorageClient.CreateCloudTableClient(); 93 var cloudTable = cloudTableClient.GetTableReference("USERINFO"); 94 95 TableQuery<UserInfo> query = new TableQuery<UserInfo>().Where(filter); 96 97 var users = await cloudTable.ExecuteQuerySegmentedAsync<UserInfo>(query, null); 98 foreach (var item in users) 99 { 100 yield return item; 101 } 102 } 103 #endregion 104 105 #region 06,更新使用者表資料根據新的使用者資料+async Task UpdateEntity(UserInfo user) 106 /// <summary> 107 /// 更新使用者表資料根據新的使用者資料 108 /// </summary> 109 /// <param name="user">新使用者資料</param> 110 /// <returns></returns> 111 public async Task UpdateEntity(UserInfo user) 112 { 113 var cloudTableClient = _cloudStorageClient.CreateCloudTableClient(); 114 var cloudTable = cloudTableClient.GetTableReference("USERINFO"); 115 116 var queryOperation = TableOperation.Retrieve<UserInfo>(user.PartitionKey, user.RowKey); 117 118 var tableResult = await cloudTable.ExecuteAsync(queryOperation); 119 if (tableResult.Result is UserInfo userInfo) 120 { 121 user.ETag = userInfo.ETag; 122 var deleteOperation = TableOperation.Replace(user); 123 await cloudTable.ExecuteAsync(deleteOperation); 124 } 125 } 126 #endregion 127 }TableService.cs
1 public interface ITableService 2 { 3 Task AddEntity(UserInfo user); 4 5 Task BatchAddEntities(List<UserInfo> users); 6 7 IAsyncEnumerable<UserInfo> QueryUsers(string filter); 8 9 Task UpdateEntity(UserInfo user); 10 11 Task DeleteEntity(UserInfo user); 12 13 Task DeleteTable(string tableName); 14 15 }ITableService.cs
1 [Route("Table")] 2 public class TableExplorerController : Controller 3 { 4 private readonly ITableService _tableService; 5 6 public TableExplorerController(ITableService tableService) 7 { 8 this._tableService = tableService; 9 } 10 11 [HttpPost("AddUser")] 12 public async Task<ActionResult> AddEntity([FromBody]UserInfo user) 13 { 14 await _tableService.AddEntity(new UserInfo("zhangsan", "610124199012223650") { Email = "[email protected]", TelNum = "13000000000" }); 15 return Ok(); 16 } 17 18 [HttpPost("AddBatchUser")] 19 public async Task<ActionResult> AddEntities([FromBody]List<UserInfo> users) 20 { 21 List<UserInfo> userList = new List<UserInfo>(); 22 userList.Add(new UserInfo("lisi", "610124199012223651") { Email = "[email protected]", TelNum = "13000000001" }); 23 userList.Add(new UserInfo("lisi", "610124199012223652") { Email = "[email protected]", TelNum = "13000000002" }); 24 userList.Add(new UserInfo("lisi", "610124199012223653") { Email = "[email protected]", TelNum = "13000000003" }); 25 await _tableService.BatchAddEntities(userList); 26 return Ok(); 27 } 28 29 [HttpGet("Users")] 30 public ActionResult QueryUsers() 31 { 32 var filter = TableQuery.CombineFilters(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, "zhangsan"), TableOperators.And, TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.Equal, "610124199012223650")); 33 34 return Ok(_tableService.QueryUsers(filter)); 35 } 36 37 [HttpPut("UpdateUser")] 38 public async Task<ActionResult> UpdateUser([FromBody]UserInfo user) 39 { 40 await _tableService.UpdateEntity(new UserInfo("zhangsan", "610124199012223650") { Email = "[email protected]", TelNum = "15000000000" }); 41 return Ok(); 42 } 43 44 [HttpDelete("DeleteEntity")] 45 public async Task<ActionResult> DeleteEntity([FromBody]UserInfo user) 46 { 47 await _tableService.DeleteEntity(new UserInfo("lisi", "610124199012223651")); 48 return Ok(); 49 } 50 51 [HttpDelete("{tableName}")] 52 public async Task<ActionResult> DeleteTable(string tableName) 53 { 54 await _tableService.DeleteTable(tableName); 55 return Ok(); 56 } 57 }TableExplorerController.cs
1 public class UserInfo:TableEntity 2 { 3 public UserInfo() 4 { 5 6 } 7 8 public UserInfo(string userName, string IdCardNum) 9 { 10 this.PartitionKey = userName; 11 this.RowKey = IdCardNum; 12 13 } 14 15 public string Email { get; set; } 16 17 public string TelNum { get; set; } 18 }UserInfo.cs
2,執行專案,通過介面方式呼叫是否可以對 Table 表資料進行操作
2.1 新增使用者資料
我們在 postman 中呼叫新增使用者表資料介面(控制器中預設構造了使用者資訊,所以我這邊沒有在Body中新增引數)
我們可以看到,在Azure Portal 上已經創建出一個叫 “USERINFO” 的表資訊(注意,大家不要疑惑,可以看看上面新增使用者的Service方法,我這裡有兩行程式碼)
var cloudTable = cloudTableClient.GetTableReference("USERINFO"); await cloudTable.CreateIfNotExistsAsync();
獲取 “USERINFO” 表的引用例項,如果當前例項不儲存就建立 “USERINFO” 表
接下來,我們看看 "USERINFO" 表中剛剛新增進去的資料,這時候我們就要藉助 VS 的 "Cloud Expoere“ 的工具了
VS 點選 ”檢視=》Cloud Expoere“
點選當前 ”賬號管理“ 找到與之對應的自己的Azure 訂閱相關聯的賬號
點選 ”cnbateblogaccount“ 的 Azure Storage 賬號,找到剛剛建立好的 ”USERINFO“ Azure Table,右鍵點選”開啟“
我們可以看到新增到 ”USERINFO“ 表中的資料 (注意,Timestamp欄位的時間問題,這裡是因為Azure Table Storage 採用的是標準時間,換算到中國時間 就得在原有時間基礎上+8)
2.2 批量新增使用者資料
注意:批量新增 Table 資料的話,這些批量資料的 “PartitionKey” 必須是相同的
輸入批量新增使用者資料的連結,點選 “Send”
我們繼續回到 VS 的Cloud Explorer 檢視 “USERINFO” Table 的表資訊
額外話題,剛才提到批量新增 Table 表資料,有提到這些資料的 “PartitionKey” 必須一致。Azure Table Storage 對批處理操作做了一些限制
1,單個批處理中的所有實體必須具有相同的分割槽鍵
2,單個批處理操作只能包含100個實體。
3,查詢使用者資料
注意,我這裡使用兩個查詢條件聯合進行查詢,分別是 “PartitionKey” 和 “RowKey” 作為查詢的 Key,通過 “Partition” 等於 “zhangsan” 和 “RowKey” 等於 “610124199012113650”
輸入查詢使用者表資料介面,點選 “Send” 進行呼叫介面
同時,我們可以看到將查詢條件對應的資料查詢出來了
4,更新表資料
注意,目前的更新操作時根據 “PartitionKey” 和 “RowKey” 進行檢索資料,將新的使用者資料進行替換操作,記得將舊的表資料中的 “ETag” 也要進行賦值到新的物件中,再執行替換操作
注意,我們此時更新操作主要更新的是 “TelNum” 欄位
輸入查詢使用者表資料介面,點選 “Send” 進行呼叫介面,返回狀態碼 200
同時我們再重新整理 Table 中的資料,成功的 PartitionKey 等於 “zhangsan”,RowKey 等於 “610124199012223650” 的資料的 TelNum 從 13000000000 改為 “15000000000”
5,刪除 Table 表資料
我們嘗試刪除 “PartitionKey” 等於 “lisi”,“RowKey” 等於 “610124199012223651”的資料
也是根據條件先查詢到當前資料,再判斷是否儲存,如果存在 就執行刪除操作
在 postman 輸入刪除實體操作的介面連結,然後點選 “Sand”
接下來,我們繼續檢視當前 Table 中的資料,以及沒有 “PartitionKey” 等於 “lisi”,“RowKey” 等於 “610124199012223651”的資料了。
6,刪除 Table 表
接下來,我們就要將整個 "SUERINFO" 表刪除的操作
繼續在 postman 上呼叫刪除 Table 操作的介面地址
當前 Table Storage 已經找不到 “USERINFO” 的 Table 資訊了
我們再上Azue Portal 上找一找,看看是否把 “USERINFO” 表刪除了
對應的 cnbatebogaccount 儲存賬戶下的 Tables 中已經沒有了任何表了
OK,今天的分享到此結束,撒花