一,引言

  今天我们就不多说废话了,直接进入正题,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

二,正文

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的更多相关文章

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

    一,引言 上一篇文章我们在.NET 项目中添加了 “WindowsAzure.Storage” 的 NuGet 包进行操作Table 数据,但是使用的 “WindowsAzure.Storage”  ...

  2. Azure Storage 系列(六)使用Azure Queue Storage

    一,引言 在之前介绍到 Azure Storage 第一篇文章中就有介绍到 Azure Storage 是 Azure 上提供的一项存储服务,Azure 存储包括 对象.文件.磁盘.队列和表存储.这里 ...

  3. Azure Storage 系列(七)使用Azure File Storage

    一,引言 今天我们开始介绍 Storage 中的最后一个类型的存储----- File Storage(文件存储),Azure File Storage 在云端提供完全托管的文件共享,这些共享项可通过 ...

  4. [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 ...

  5. Windows Azure入门教学系列 (四):使用Blob Storage

    本文将会介绍如何使用Blob Storage.Blob Storage可以看做是云端的文件系统.与桌面操作系统上不同,我们是通过REST API来进行对文件的操作.有关REST API的详细信息,请参 ...

  6. Windows Azure入门教学系列 (七):使用REST API访问Storage Service

    本文是Windows Azure入门教学的第七篇文章. 本文将会介绍如何使用REST API来直接访问Storage Service. 在前三篇教学中,我们已经学习了使用Windows Azure S ...

  7. Windows Azure入门教学系列 (六):使用Table Storage

    本文是Windows Azure入门教学的第六篇文章. 本文将会介绍如何使用Table Storage.Table Storage提供给我们一个云端的表格结构.我们可以把他想象为XML文件或者是一个轻 ...

  8. [转]Windows Azure入门教学系列 (六):使用Table Storage

    本文转自:http://blogs.msdn.com/b/azchina/archive/2010/03/11/windows-azure-table-storage.aspx 本文是Windows ...

  9. PCIE_DMA实例四:xapp1052在Xilinx 7系列(KC705/VC709)FPGA上的移植

    PCIE_DMA实例四:xapp1052在Xilinx 7系列(KC705/VC709)FPGA上的移植 一:前言 这段时间有个朋友加微信请求帮忙调试一块PCIe采集卡.该采集卡使用xilinx xc ...

随机推荐

  1. Linux学习笔记之配置网络

    1.打开VMware Workstation虚拟机 2.在VMware下安装虚拟ubunt系统后配置网络,如图所示配置,即可. 3.检查笔记本所使用的网段 ①按 “win + R ”键,并输入“cmd ...

  2. 节点操作 - DOM编程

    1. 获取节点 1.1 直接获取节点 父子关系: element.parentNode element.firstChild/element.lastChild element.firstElemen ...

  3. 2020-07-10:sql如何调优?

    福哥答案2020-07-10:此答案来自群成员: SQL提高查询效率的几点建议 1.如果要用子查询,那就用EXISTS替代IN.用NOT EXISTS替代NOT IN.因为EXISTS引入的子查询只是 ...

  4. flask-migrate 处理sqlite数据库报错Constraint must have a name 的解决方案

    环境:flask+python+sqlite,我想给某个表里某个字段加unique属性 执行 python manage.py db migrate 没报错,执行 python manage.py d ...

  5. css如何让子元素在父元素中水平垂直居中

    方法一: display:flex <!DOCTYPE html> <html lang="en"> <head> <meta chars ...

  6. CallStub相关

    CallStub相关 调用入口 share/vm/runtime/stubRoutines.hpp // Calls to Java SimonNote: 函数指针结合typedef类型定义 type ...

  7. 【luogu1709】小B的询问 - 莫队

    题目描述 小B有一个序列,包含N个1~K之间的整数.他一共有M个询问,每个询问给定一个区间[L..R],求Sigma(c(i)^2)的值,其中i的值从1到K,其中c(i)表示数字i在[L..R]中的重 ...

  8. 前端 go.js 流程图基于vue开发项目案例

    一.流程图效果 最近一段时间在研究go.js,它是一款前端开发画流程图的一个插件,也是一个难点,要说为什么是难点,首先,它是依赖画布canvas知识开发.其次,要依赖于内部API开发需求,开发项目需求 ...

  9. 实践案例丨教你一键构建部署发布前端和Node.js服务

    如何使用华为云服务一键构建部署发布前端和Node.js服务 构建部署,一直是一个很繁琐的过程 作为开发,最害怕遇到版本发布,特别是前.后端一起上线发布,项目又特别多的时候. 例如你有10个项目,前后端 ...

  10. Kettle基本使用

    Kettle基本使用 Kettle的几个子程序的功能和启动方式 Spoon.bat 图形界面方式启动作业和转换设计器. Pan.bat 命令行方式执行转换. Kitchen.bat   命令行方式执行 ...