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 Blob Storage 存储系列:

1,Azure Storage 系列(一)入门简介

2,Azure Storage 系列(二) .NET Core Web 项目中操作 Blob 存储

3,Azure Storage 系列(三)Blob 参数设置说明

4,Azure Storage 系列(四)在.Net 上使用Table Storage

5,Azure Storage 系列(五)通过Azure.Cosmos.Table 类库在.Net 上使用 Table Storage  

6,Azure Storage 系列(六)使用Azure Queue 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 = "135012689@qq.com", 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 = "1350126740@qq.com", TelNum = "13000000001" });
23             userList.Add(new UserInfo("lisi", "610124199012223652") { Email = "1350126741@qq.com", TelNum = "13000000002" });
24             userList.Add(new UserInfo("lisi", "610124199012223653") { Email = "1350126742@qq.com", 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 = "135012689@qq.com", 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,今天的分享到此结束,撒花🎉🎉🎉🎉🎉🎉!

三,结尾

  今天,我们通过代码(已遗弃的类库)演示了一下如何操作 Tables 数据,已经创建/删除 Table,下一篇继续讲解 Table 是如果进行操作的,但是会换一套微软推荐的 “Microsoft.Azure.Cosmos.Table”,我们也要跟上微软的脚步,与时俱进。

github:https://github.com/yunqian44/Azure.Storage.git

作者:Allen 

版权:转载请在文章明显位置注明作者及出处。如发现错误,欢迎批评指正。

posted @ 2020-09-09 21:04  Grant_Allen  阅读(712)  评论(13编辑  收藏