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 存储系列:
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>();
完整代码


- public class TableService : ITableService
- {
- private readonly CloudStorageAccount _cloudStorageClient;
- public TableService(CloudStorageAccount cloudStorageClient)
- {
- _cloudStorageClient = cloudStorageClient;
- }
- #region 01,添加表数据+async Task AddEntity(UserInfo user)
- /// <summary>
- /// 添加表数据
- /// </summary>
- /// <param name="user">用户数据</param>
- /// <returns></returns>
- 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);
- }
- #endregion
- #region 02,批量添加用户表数据+async Task BatchAddEntities(List<UserInfo> users)
- /// <summary>
- /// 批量添加用户表数据
- /// </summary>
- /// <param name="users">用户数据</param>
- /// <returns></returns>
- 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);
- }
- #endregion
- #region 03,删除表操作根据表名+async Task DeleteTable(string tableName)
- /// <summary>
- /// 删除表操作根据表名
- /// </summary>
- /// <param name="tableName">表命</param>
- /// <returns></returns>
- public async Task DeleteTable(string tableName)
- {
- var cloudTableClient = _cloudStorageClient.CreateCloudTableClient();
- var cloudTable = cloudTableClient.GetTableReference(tableName);
- await cloudTable.DeleteIfExistsAsync();
- }
- #endregion
- #region 04,删除用户数据根据用户条件+async Task DeleteEntity(UserInfo user)
- /// <summary>
- /// 删除用户数据根据用户条件
- /// </summary>
- /// <param name="user">用户条件</param>
- /// <returns></returns>
- 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);
- }
- }
- #endregion
- #region 05,查询用户根据条件+async IAsyncEnumerable<UserInfo> QueryUsers(string filter)
- /// <summary>
- /// 查询用户根据条件
- /// </summary>
- /// <param name="filter">条件</param>
- /// <returns></returns>
- 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;
- }
- }
- #endregion
- #region 06,更新用户表数据根据新的用户数据+async Task UpdateEntity(UserInfo user)
- /// <summary>
- /// 更新用户表数据根据新的用户数据
- /// </summary>
- /// <param name="user">新用户数据</param>
- /// <returns></returns>
- 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);
- }
- }
- #endregion
- }
TableService.cs


- public interface ITableService
- {
- Task AddEntity(UserInfo user);
- Task BatchAddEntities(List<UserInfo> users);
- IAsyncEnumerable<UserInfo> QueryUsers(string filter);
- Task UpdateEntity(UserInfo user);
- Task DeleteEntity(UserInfo user);
- Task DeleteTable(string tableName);
- }
ITableService.cs


- [Route("Table")]
- public class TableExplorerController : Controller
- {
- private readonly ITableService _tableService;
- public TableExplorerController(ITableService tableService)
- {
- this._tableService = tableService;
- }
- [HttpPost("AddUser")]
- public async Task<ActionResult> AddEntity([FromBody]UserInfo user)
- {
- await _tableService.AddEntity(new UserInfo("zhangsan", "") { Email = "135012689@qq.com", TelNum = "" });
- return Ok();
- }
- [HttpPost("AddBatchUser")]
- public async Task<ActionResult> AddEntities([FromBody]List<UserInfo> users)
- {
- List<UserInfo> userList = new List<UserInfo>();
- userList.Add(new UserInfo("lisi", "") { Email = "1350126740@qq.com", TelNum = "" });
- userList.Add(new UserInfo("lisi", "") { Email = "1350126741@qq.com", TelNum = "" });
- userList.Add(new UserInfo("lisi", "") { Email = "1350126742@qq.com", TelNum = "" });
- await _tableService.BatchAddEntities(userList);
- return Ok();
- }
- [HttpGet("Users")]
- public ActionResult QueryUsers()
- {
- var filter = TableQuery.CombineFilters(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, "zhangsan"), TableOperators.And, TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.Equal, ""));
- return Ok(_tableService.QueryUsers(filter));
- }
- [HttpPut("UpdateUser")]
- public async Task<ActionResult> UpdateUser([FromBody]UserInfo user)
- {
- await _tableService.UpdateEntity(new UserInfo("zhangsan", "") { Email = "135012689@qq.com", TelNum = "" });
- return Ok();
- }
- [HttpDelete("DeleteEntity")]
- public async Task<ActionResult> DeleteEntity([FromBody]UserInfo user)
- {
- await _tableService.DeleteEntity(new UserInfo("lisi", ""));
- return Ok();
- }
- [HttpDelete("{tableName}")]
- public async Task<ActionResult> DeleteTable(string tableName)
- {
- await _tableService.DeleteTable(tableName);
- return Ok();
- }
- }
TableExplorerController.cs


- public class UserInfo:TableEntity
- {
- public UserInfo()
- {
- }
- public UserInfo(string userName, string IdCardNum)
- {
- this.PartitionKey = userName;
- this.RowKey = IdCardNum;
- }
- public string Email { get; set; }
- public string TelNum { get; set; }
- }
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
版权:转载请在文章明显位置注明作者及出处。如发现错误,欢迎批评指正。
Azure Storage 系列(四)在.Net 上使用Table Storage的更多相关文章
- Azure Storage 系列(五)通过Azure.Cosmos.Table 类库在.Net 上使用 Table Storage
一,引言 上一篇文章我们在.NET 项目中添加了 “WindowsAzure.Storage” 的 NuGet 包进行操作Table 数据,但是使用的 “WindowsAzure.Storage” ...
- Azure Storage 系列(六)使用Azure Queue Storage
一,引言 在之前介绍到 Azure Storage 第一篇文章中就有介绍到 Azure Storage 是 Azure 上提供的一项存储服务,Azure 存储包括 对象.文件.磁盘.队列和表存储.这里 ...
- Azure Storage 系列(七)使用Azure File Storage
一,引言 今天我们开始介绍 Storage 中的最后一个类型的存储----- File Storage(文件存储),Azure File Storage 在云端提供完全托管的文件共享,这些共享项可通过 ...
- [Windows Azure] How to use the Table Storage Service
How to use the Table Storage Service version 1.7 version 2.0 This guide will show you how to perform ...
- Windows Azure入门教学系列 (四):使用Blob Storage
本文将会介绍如何使用Blob Storage.Blob Storage可以看做是云端的文件系统.与桌面操作系统上不同,我们是通过REST API来进行对文件的操作.有关REST API的详细信息,请参 ...
- Windows Azure入门教学系列 (七):使用REST API访问Storage Service
本文是Windows Azure入门教学的第七篇文章. 本文将会介绍如何使用REST API来直接访问Storage Service. 在前三篇教学中,我们已经学习了使用Windows Azure S ...
- Windows Azure入门教学系列 (六):使用Table Storage
本文是Windows Azure入门教学的第六篇文章. 本文将会介绍如何使用Table Storage.Table Storage提供给我们一个云端的表格结构.我们可以把他想象为XML文件或者是一个轻 ...
- [转]Windows Azure入门教学系列 (六):使用Table Storage
本文转自:http://blogs.msdn.com/b/azchina/archive/2010/03/11/windows-azure-table-storage.aspx 本文是Windows ...
- PCIE_DMA实例四:xapp1052在Xilinx 7系列(KC705/VC709)FPGA上的移植
PCIE_DMA实例四:xapp1052在Xilinx 7系列(KC705/VC709)FPGA上的移植 一:前言 这段时间有个朋友加微信请求帮忙调试一块PCIe采集卡.该采集卡使用xilinx xc ...
随机推荐
- 2、Java 基础语法标识符、修饰符、变量、 数组、枚举、关键字
Java 基础语法 一个 Java 程序可以认为是一系列对象的集合,而这些对象通过调用彼此的方法来协同工作.下面简要介绍下类.对象.方法和实例变量的概念. 对象:对象是类的一个实例,有状态和行为.例如 ...
- SQL关联查询
从2张或多张表中,取出有关联的数据 关联查询一共有几种情况: 内连接:INNER JOIN .CROSS JOIN (1)形式一 select 字段列表 from A表 inner join B表 o ...
- 菊长说丨一文读懂MySQL4种事务隔离级别
经常提到数据库的事务,那你知道数据库还有事务隔离的说法吗,事务隔离还有隔离级别,那什么是事务隔离,隔离级别又是什么呢?今天我们就找菊长去,请他帮大家梳理一下这些各具特色的事务隔离级别,咱走着~~~ 点 ...
- java List接口二
一 ArrayList集合 ArrayList集合数据存储的结构是数组结构.元素增删慢,查找快,由于日常开发中使用最多的 功能为查询数据.遍历数据,所以ArrayList是最常用的集合. 许多程序员开 ...
- HTML基础-03
盒子模型 盒子模型(框模型 box model) - 浏览器在渲染页面时,它会将页面中的每一个元素都想象成是一个矩形的盒子. - 想象成盒子以后,对于页面的布局就变成了如何摆放盒子 - 每一个盒子从内 ...
- 调试备忘录-NTC电阻的使用(教程 + 代码)
软件环境:CodeWarrior 11.1 硬件环境:NXP S9KEAZ64A 传感器参数:NTC热敏电阻(R25 = 50k,B25-50 3950) 写在前面 最近做小项目需要用到NTC电阻,因 ...
- three.js 着色器材质内置变量
这篇郭先生说一下three.js着色器的内置变量,分别是 gl_PointSize:在点渲染模式中,控制方形点区域渲染像素大小(注意这里是像素大小,而不是three.js单位,因此在移动相机是,所看到 ...
- 【WC2013】 糖果公园 - 树上莫队
问题描述 Candyland 有一座糖果公园,公园里不仅有美丽的风景.好玩的游乐项目,还有许多免费糖果的发放点,这引来了许多贪吃的小朋友来糖果公园游玩.糖果公园的结构十分奇特,它由 n 个游览点构成, ...
- 图论算法(四)Dijkstra算法
最短路算法(三)Dijkstra算法 PS:因为这两天忙着写GTMD segment_tree,所以博客可能是seg+图论混搭着来,另外segment_tree的基本知识就懒得整理了-- Part 1 ...
- STL函数库的应用第三弹——数据结构(栈)
Part 1:栈是什么 栈(stack)又名堆栈,它是一种运算受限的线性表.限定仅在表尾进行插入和删除操作的线性表. 这一端被称为栈顶,相对地,把另一端称为栈底. 向一个栈插入新元素又称作进栈.入栈或 ...