Azure Storage 是微软 Azure 云提供的云端存储解决方案,当前支持的存储类型有 Blob、Queue、File 和 Table。其中的 Table 就是本文的主角 Azure Table storage。

Azure Table storage 是一个在云端存储结构化 NoSQL 数据的服务。它不仅存取速度快,而且效费比高。MSDN 上的说法是:成本显著低于传统 SQL!
笔者最近在项目中用 Table storage 实现了一个日志表,在此和大家分享一下 Table storage 的基本用法。

Azure storage account

就概念上来讲,Table storage 只是 Azure 提供的存储服务的一种。其他的存储服务还有 Blob、Queue、File 等。对这些存储服务的访问控制都是通过 storage account 来进行的。所以要想使用 Table storage 需要先创建你的 storage account。具体创建过程不是本文重点,请参考 MSDN。但你需要去了解一下 Access keys,它就是你访问 storage account 的用户名和密码:

创建 Table storage 的对象

在使用 Azure Table storage 的相关对象前,我们需要安装对应的包。其实很简单,只需在 Visual Studio 的 Package Manager Console 中输入:

Install-Package WindowsAzure.Storage

Visual Studio 会自动安装 WindowsAzure.Storage 包及其依赖的所有包,安装完成后的 packages.config 文件看起来像这个样子:

安装完相关的包以后,我们就可以使用其中的类型了。

CloudStorageAccount 类表示一个 Azure storage account,我们得先创建它的实例才能访问属于它的资源。

// 注意连接字符串中的 xxx 和 yyy,分别对应 Access keys 中的 Storage account name 和 key。
CloudStorageAccount storageAccount = CloudStorageAccount.Parse("DefaultEndpointsProtocol=https;AccountName=xxx;AccountKey=yyy"); // CloudTableClient 类是 Windows Azure Table Service 客户端的逻辑表示。我们使用它来配置和执行对 Table storage 的操作。
CloudTableClient cloudTableClient = storageAccount.CreateCloudTableClient();

CloudTable 类表示一张数据表。

// 创建一个实例去引用 Table storage 中的一张表,我们测试用的表名叫 "MyLogTable"。
CloudTable logTable = cloudTableClient.GetTableReference("MyLogTable");
// 如果不确定表是否被创建过,可以调用 CreateIfNotExists 方法。
logTable.CreateIfNotExists();

这样在后面的操作中就可以确保 MyLogTable 表是存在的。

有了 logTable 对象我们就可以向表中插入数据了。但是等等,好像少了点什么。我们开篇第一句中就说明了,Table storage 存储的是结构化的数据,所以我们还要先定义存储的数据的类型。

定义日志类

在定义我们自己的数据类型时,有一个强制性的要求,必须继承自 TableEntity 类型:

internal class MyLogEntity : TableEntity
{
public MyLogEntity() { }
public MyLogEntity(string pkey, string rkey)
{
this.PartitionKey = pkey;
this.RowKey = rkey;
} public DateTime LogDate { get; set; }
public string LogMessage { get; set; }
public string ErrorType { get; set; }
}

在我们的设计中,PartitionKey 用来存放产生日志的年份和月份(例如201607),RowKey 用来存放产生日志的天和时分秒毫秒(例如160934248492)。日志数据主要是 LogDate,LogMessage 和 ErrorType。

把数据插入到 Table storage

终于可以向表中插入数据了,试一下先:

DateTime now = DateTime.Now;
string partitionKey = now.ToString("yyyyMM");
string rowKey = now.ToString("ddHHmmssffff");
MyLogEntity logEntity = new MyLogEntity(partitionKey, rowKey);
logEntity.LogDate = now;
logEntity.LogMessage = "test message";
logEntity.ErrorType = "error";
// TableOperation 类表示对一个表进行的操作,可以插入一行或多行数据,删除数据,更新数据等。
TableOperation insertOperation = TableOperation.Insert(logEntity);
logTable.Execute(insertOperation);

看起来还不错,我们用 Visual Studio 自带的 Cloud Explorer 查看一下 MyLogTable 中的内容:

OK,数据已经成功插入到 MyLogTable 表中。接下来我们看看如何批量的插入数据。

TableBatchOperation batchOperation = new TableBatchOperation();
for (int i = ; i < ; i++)
{
DateTime now = DateTime.Now;
string partitionKey = now.ToString("yyyyMM");
string rowKey = now.ToString("ddHHmmssffff");
MyLogEntity logEntity = new MyLogEntity(partitionKey, rowKey);
logEntity.LogDate = now;
logEntity.LogMessage = "test message" + i.ToString();
logEntity.ErrorType = (i%) == ? "error" : "warning";
batchOperation.Insert(logEntity);
Thread.Sleep();
}
logTable.ExecuteBatch(batchOperation);

这次我们把 TableOperation 类换成了 TableBatchOperation 类,然后一次插入十条数据。去检查一下结果,OK 十条数据全部插入成功!
下面让我们把循环中的 10 改成 200 试试:

怎么收到一个 InvalidOperationException 呢?看看红框中的内容,原来批量操作是有一些限制的:
1.    每个批量操作的数据上限是 100 条记录。
2.    每个批量操作中的数据都必须保持相同的 partition key。
请大家在使用批量操作时务必注意这些限制条件!

查询操作

对于日志数据的操作,最重要的就是查询。我们通过几个具体的用例来介绍 Table storage 的查询操作。

查询所有的记录

这是最简单的查询方法,一般是想要导出全部数据时才会这么干:

TableQuery<MyLogEntity> query = new TableQuery<MyLogEntity>();
foreach (MyLogEntity entity in logTable.ExecuteQuery(query))
{
Console.WriteLine("{0}\t{1}\t{2}\t{3}", entity.PartitionKey, entity.RowKey, entity.LogMessage, entity.ErrorType);
}

查询某年的某个月的记录

要查询某个月的所有记录也是比较容易的,因为我们设计的 PartitionKey 就代表了某个月份:

TableQuery<MyLogEntity> query = new TableQuery<MyLogEntity>().Where(
TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, ""));
foreach (MyLogEntity entity in logTable.ExecuteQuery(query))
{
//...
}

请注意 TableQuery.GenerateFilterCondition 方法,我们创建了一个过滤条件:PartitionKey 等于 "201607"。这个查询会把所有 PartitionKey 为 "201607" 的记录都找到!

查询某一条记录

如果我们已经知道了一条记录的 PartitionKey 和 RowKey,就可以通过这两个条件直接查询到这条记录的详情:

TableQuery<MyLogEntity> query = new TableQuery<MyLogEntity>().Where(
TableQuery.CombineFilters(
TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, ""),
TableOperators.And,
TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.Equal, "")));
foreach (MyLogEntity entity in logTable.ExecuteQuery(query))
{
//...
}

这次我们使用了组合条件。虽然这里只使用了条件运算操作 TableOperators.And 和 QueryComparisons.Equal,你完全可以尝试其它的条件类型。唯一要注意的是:对于 PartitionKey 和 RowKey,QueryComparisons 的操作对象都是字符串。

我们还需要更多的查询条件,比如查询某一天产生的所有日志。在 MyLogTable 表中,这需要查询以 "xx" 字符串开头的 RowKey。我会单独在一篇文章中和大家分享相关内容,因为它并不像看起来的那么简单。
接下来我们介绍如何更新和删除日志表中的数据,当然这么做并不恰当,我们这里只是借用日志表介绍更新和删除操作而已。

更新记录

TableOperation retrieveOperation = TableOperation.Retrieve<MyLogEntity>("", "");
TableResult retrievedResult = logTable.Execute(retrieveOperation);
MyLogEntity updateEntity = (MyLogEntity)retrievedResult.Result; if (updateEntity != null)
{
updateEntity.LogMessage = "new log message";
TableOperation updateOperation = TableOperation.Replace(updateEntity);
logTable.Execute(updateOperation);
}

这次我们先用 TableOperation.Retrieve 方法获得一条数据的详情,然后更新它的 LogMessage 属性,最后使用 TableOperation.Replace 方法把新的内容更新的到 Table storage 中。

删除记录

实际上删除一条记录和更新一条记录一样麻烦,不同点是把 TableOperation.Replace 方法换成 TableOperation.Delete 方法:

TableOperation retrieveOperation = TableOperation.Retrieve<MyLogEntity>("", "");
TableResult retrievedResult = logTable.Execute(retrieveOperation);
MyLogEntity deleteEntity = (MyLogEntity)retrievedResult.Result;
if (deleteEntity != null)
{
TableOperation deleteOperation = TableOperation.Delete(deleteEntity);
logTable.Execute(deleteOperation);
}

删除表

删除表和创建表一样简单(可比删除一条记录容易多了):

logTable.DeleteIfExists();

总结

本文通过对一个日志表的操作介绍了 Azure Table storage 的一个典型应用场景和基本的使用方法。从操作的代码上看和传统的 sql 表操作差别还是挺大的。希望对朋友们了解 Azure Table storage 能有所帮助。

Azure 基础:Table storage的更多相关文章

  1. Azure 基础:自定义 Table storage 查询条件

    本文是在 <Azure 基础:Table storage> 一文的基础上介绍如何自定义 Azure Table storage 的查询过滤条件.如果您还不太清楚 Azure Table s ...

  2. 自定义 Azure Table storage 查询过滤条件

    本文是在Azure Table storage 基本用法一文的基础上,介绍如何自定义 Azure Table storage 的查询过滤条件.如果您还不太清楚 Azure Table storage ...

  3. Windows Azure Table storage 之 动态Table类 DynamicTableEntity

    在一般情况下,当我们在.net中使用Azure table storage的时候都会为该表建立一个TableEntity的派生类,如下所示. public class CustomerEntity : ...

  4. Azure 基础:Blob Storage

    Azure Storage 是微软 Azure 云提供的云端存储解决方案,当前支持的存储类型有 Blob.Queue.File 和 Table. 笔者在前文中介绍了 Table Storage 的基本 ...

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

    一,引言 今天我们就不多说废话了,直接进入正题,Azure Table Storage.开始内容之前,我们先介绍一下Azure Table Storage. 1,什么是Azure Table Stor ...

  6. Azure Table storage 基本用法 -- Azure Storage 之 Table

    Azure Storage 是微软 Azure 云提供的云端存储解决方案,当前支持的存储类型有 Blob.Queue.File 和 Table,其中的 Table 就是本文的主角 Azure Tabl ...

  7. Azure Table storage 之改进DynamicTableEntity类为其添加动态语言扩展

    在之前的一篇文章中提到,storage类库中包含一个可以用来动态获取Azure table storage 表结构的类-DynamicTableEntity. 我们可以通过这个类,我们无需为每一个表提 ...

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

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

  9. Windows Azure Table Storage 解决 Guid 查询问题

    在使用 Windows Azure Table Storage 的 CloudTableClient 对Azure 进行数据查询时,会发现在自定义类的Guid类型始终无法去成功查询出数据,对比发现 G ...

随机推荐

  1. keil5之32环境配置

    终于配置好了!!又是经过一下午加晚上的奋战,终于把环境配置好了,多亏了我强大的资料整理能力(哈哈). 真是不容易啊,本来打算放弃的,去问问别人吧.但是想想,还是靠自己吧,靠谁都不如靠自己,真是的,慢慢 ...

  2. CSS元素垂直居中方法总结

    坚持,坚持,坚持... 以上为自我鼓励,哈哈... ------------------------------------------------- 相信没有真正是尝试过的人应该都和我一样,觉得居中 ...

  3. 分享一个随机更改 MAC地址 软件

    有些软件 是根据 MAC地址 来判断 是不是 已经 安装过 这个 软件 (针对 有些软件是 可以 免费 使用的 ) 要想 一直 使用 的话 只需要 修改一下 mac地址 就可以 继续 使用! 在百度中 ...

  4. (知识点)JavaScript原型和原型链

    〇 每个函数都拥有prototype属性,而该属性所储存的就是原型对象 1)原型属性—— 上面我们测试了foo()函数的 1) length属性(length属性除了可以用在数组中,还可以用于记录函数 ...

  5. typedef和define的详细区别

    typedef是一种在计算机编程语言中用来声明自定义数据类型,配合各种原有数据类型来达到简化编程的目的的类型定义关键字. #define是预处理指令.下面让我们一起来看. typedef是C语言语句, ...

  6. Linux 上搭建 git 的服务器

    搭建服务器 假设服务器的名字是 git.example.com. 首先,添加一个叫做git的用户adduser git. 然后如果不存在的话, 为这个用户新建一个主目录mkdir /home/git, ...

  7. python之爬虫学习记录与心得

    之前在寒假的时候,学习了python基础.在慕课网上看的python入门:http://www.imooc.com/learn/177 python进阶:http://www.imooc.com/le ...

  8. OC语言中如何在便利构造器中利用便利初始化进行初始化

    因为利用便利初始化在便利构造器中进行初始化,所以要利用便利初始化的声明及实现部分,可与前篇做比较: 1. 主函数部分: 2. 接口部分: 3. 实现部分: 4. 打印结果: 感兴趣的朋友们可自己与前面 ...

  9. 无分类编址(CIDR)构成超网

    CIDR(无分类域间路由选择) CIDR最主要有两个以下特点: 消除传统的A,B,C地址和划分子网的概念,更有效的分配IPv4的地址空间,CIDR使IP地址又回到无分类的两级编码.记法:IP地址::= ...

  10. Visual Studio 2017 针对移动开发的新特性介绍

    欢迎大家持续关注葡萄城控件技术团队博客,更多更好的原创文章尽在这里~~ Visual Studio是世界上最好的IDE之一,如果是 .NET世界,那就没有之一了(^_^),而最近推出的Visual S ...