Windows Azure 存储扩展






4.97/5 (12投票s)
.NET 库,用于管理和查询 Windows Azure 存储中的实体。包含 LINQ to Azure Table 提供程序。
引言
Windows Azure Storage Extensions 是一个 .NET 库,用于管理和查询 Windows Azure Storage 中的实体。它构建在 Windows Azure SDK v2.0 之上,提供了异步接口(基于任务的异步模式)以及通过 TableSet 上下文使用 POCO 实体实现的LINQ to Azure Table 查询。
目录
背景
目前,Windows Azure SDK v1.x 及其 LINQ to Azure Table 提供程序已被标记为过时。其后继者 Windows Azure SDK v2.0 是从头开始编写的,并进行了一些重大更改,其中包括新的查询机制。其实现存在以下不足。
使用 TableQuery 进行查询
现在,如果我们不想使用旧的 WCF Data Services,我们需要编写像下面这样丑陋的代码来构造到 Azure Tables 的查询。
string filter = TableQuery.GenerateFilterCondition(
"RowKey", QueryComparisons.GreaterThanOrEqual, "5");
TableQuery<TableEntity> query = new TableQuery<TableEntity>().Where(filter).Take(5);
var entities = myTable.ExecuteQuery(query);
POCO 对象继承 TableEntity 的要求
要使用 POCO 实体,我们应该使用 TableEntity
基类:
public class SampleEntity : TableEntity
{
public int SampleProperty { get; set; }
}
除了提供具有 PartitionKey
、RowKey
、Timestamp
和 ETag
属性的 ITableEntity
接口外,它还使用缓慢的反射进行实体序列化/反序列化。
低抽象级别
对我这样的软件工程师来说,Azure Storage Library v2.0 似乎是对 Azure Tables REST API 的一个过于低级的抽象。例如,当我想使用 DTO 实体时,我必须记住 PartitionKey
是用户标识符,实际上它没有实际意义,我们应该使用某种实体映射器。查询也是一项过于复杂的任务。
Windows Azure Storage Extensions
Windows Azure Storage Extensions 库提供以下功能。
POCO
实体属性和字段应通过一个或两个 PartitionKey 和 RowKey 属性进行标记,以定义复合表键。还可以使用 Timestamp、ETag、Property 和 Ignore 属性。
Attribute | 描述 | 约束 |
---|---|---|
PartitionKey |
定义分区键属性。 | 仅限于字符串属性。 |
RowKey |
定义行键属性。 | 仅限于字符串属性。 |
ETag |
定义 etag 属性。 |
仅限于字符串属性。 |
时间戳 |
用于接收表实体时间戳。 | 仅限于 DateTime 或 DateTimeOffset 属性。 |
属性 |
用于通过 Name 属性定义自定义表属性名称。 |
|
Ignore |
用于跳过属性的序列化/反序列化。 |
表实体管理
通用 TableSet
上下文提供同步和异步(TAP)方法来管理实体。
- 同步:
Add
、AddOrUpdate
、Update
和Remove
。 - 异步:
AddAsync
、AddOrUpdateAsync
、UpdateAsync
和RemoveAsync
。
为避免 Azure 存储中的组操作限制,所有实体都按分区键排序,并合并成 100 个实体的组。可以通过 TableSet
的 ExecutionMode
属性配置此类批量操作的请求执行。允许的值
Sequential
并行
默认 ExecutionMode
为 Sequential
。
LINQ to Azure Tables
TableSet
上下文实现了 IQueryable 接口,用于使用LINQ 表达式。提供程序支持以下同步 LINQ 方法
- First
- FirstOrDefault
- Single
- SingleOrDefault
- Take
- 其中
为了利用字符串属性的筛选功能,它支持以下方法:
您也可以使用Contains 方法。在这种情况下,每个集合项的查询语句将使用 OData or
运算符连接。
注意:要创建自定义查询,您应该参考下一篇文章混合 LINQ 提供程序和 LINQ to Objects。
异步 LINQ 查询
此外,TableSet
可用于异步查询,这些查询由 LINQ 扩展(TAP)提供支持,采用EF 6 Async 风格。可用方法
FirstAsync
FirstOrDefaultAsync
SingleAsync
SingleOrDefaultAsync
TakeAsync
ToListAsync
LINQ 投影
LINQ 投影支持存在一个限制 - 投影类应该是引用类型。
基于任务的扩展方法
该库包含以下 Windows Azure SDK 类的基于 TAP 的扩展
CloudBlobClient
CloudBlobContainer
CloudTableClient
CloudTable
要使用它,只需在同步方法名称后添加 Async 后缀即可,如下所示:
blobs = cloudBlobContainer.ListBlobs();
blobs = await cloudBlobContainer.ListBlobsAsync();
任务取消
所有基于 TAP 的方法都接受可选的 CancellationToken
参数以进行任务取消。
下载
通过 NuGet
要通过 Windows Azure Storage Extensions nuget 包安装该库,请执行以下命令:
PM> Install-Package WindowsAzure.StorageExtensions
通过 Git
要通过 git 获取该库的源代码,只需键入:
git clone git://github.com/dtretyakov/WindowsAzure.git
cd ./WindowsAzure
示例
您可以下载由 ASP.NET MVC4 和 Web API 驱动的 SPA 示例。它使用 Azure Table Storage 作为持久化存储,因此在运行该示例之前,请启动Azure Storage Emulator 或在 Web.config 中配置正确的连接字符串。
此示例中一个有趣的部分是 IssuesController
中的 Get 方法。在运行时,SPA 将 OData 查询发送到 WebAPI IssuesController
,后者通过利用 Queryable
属性将其转换为对 TableSet
上下文的 LINQ 查询,而 TableSet
上下文又将 LINQ 表达式转换为 Azure Storage Table 服务的 OData 过滤器。
代码示例
定义新类
public sealed class Country
{
[PartitionKey]
public string Continent { get; set; }
[RowKey]
public string Name { get; set; }
public long Population { get; set; }
public double Area { get; set; }
public DateTime Formed { get; set; }
}
创建新的表上下文
var storageAccount = CloudStorageAccount.DevelopmentStorageAccount;
var tableClient = storageAccount.CreateCloudTableClient();
var countryTable = new TableSet<Country>(tableClient);
添加新实体
var resultSync = countryTable.Add(country);
var resultAsync = await countryTable.AddAsync(country);
更新实体
resultSync.Area += 333333;
resultSync = countryTable.Update(resultSync);
resultAsync.Population *= 2;
resultAsync = await countryTable.UpdateAsync(resultAsync);
删除实体:
countryTable.Remove(resultSync);
await countryTable.RemoveAsync(resultAsync);
查询实体
var query = countryTable.Where(
p => p.Formed > new DateTime(1950, 1, 1) &&
(p.PresidentsCount < 10 || p.Population < 10000000 && p.IsExists));
var result = query.ToList();
result = await query.ToListAsync();
或使用字符串筛选方法
var countryStartingWithF = await countryTable.FirstAsync(
p => p.Name.CompareTo("F") >= 0 && p.Name.CompareTo("G") < 0);
使用 LINQ 投影
var projection = from country in countryTable
where country.Area > 400000
select new { country.Continent, country.Name };
var entities = projection.ToList();
entities = await projection.ToListAsync();
在 LINQ 查询中使用 Contains 方法
var countryNames = new List<string> { "Germany", "Finland" };
var countries = countryTable.Where(p => countryNames.Contains(p.Name)).ToList();
兴趣点
该库的源代码可在 github.com/dtretyakov/windowsazure 上找到。Windows Azure Storage Extensions 的核心组件包括:
表上下文

TableSet<T>
类是 Azure Storage Table 的抽象。它实现了 IQueryable<T>
和 ITableSet<T>
接口。它通过 CloudTable
类在内部执行对 Azure Storage Tables 的单个和批量请求,并利用 TableEntityConverter<T>
使用 POCO 对象序列化。
表实体转换器
TableEntityConverter<T>
实现 ITableEntityConverter<T>
接口。它使用编译的表达式树来最快地访问 POCO 字段和属性。内部它将 POCO 对象转换为 DynamicTableEntity
,反之亦然。TableEntityConverter
对于 POCO、TableEntity
和 new
运算符的性能比较结果(毫秒)如下:
转换 | 10M | 50M |
---|---|---|
DynamicTableEntity 转 Object |
8501 | 43,690 |
DynamicTableEntity 转 POCO |
17,826 | 89,907 |
DynamicTableEntity 转 TableEntity |
54,158 | 276,421 |
Object 转 DynamicTableEntity |
10,693 | 51,485 |
POCO 转 DynamicTableEntity |
15,528 | 78,368 |
TableEntity 转 DynamicTableEntity |
41,471 | 218,935 |
测试可在:EntityConverterTests.cs 中找到。
表查询提供程序
TableQueryProvider<T>
实现 IQueryProvider
和 IAsyncQueryProvider
接口。它提供将 LINQ 表达式转换为Azure Storage Table OData 过滤器,并能够同步和异步执行它们。
基于任务的扩展方法
Windows Azure SDK v2.0 为我们提供了基于 APM 的接口和 ICancellableAsyncResult
用于操作取消。 .NET 4.0 及更高版本使用其他基于 TAP 的异步编程模型。因此,Windows Azure Storage Extensions 为大部分 Windows Azure SDK 类提供了 APM 到 TAP 的包装器。该库在内部使用这些扩展来执行到 Azure Storage Tables 的异步请求。
反馈
非常欢迎您在GitHub 项目页面上提出您的建议和意见。
历史
- 0.1.0 - 2012 年 12 月 16 日:Alpha 版本。
- 0.7.0 - 2013 年 4 月 12 日:首个稳定版本。
- 0.7.2 - 2013 年 4 月 22 日:添加了 LINQ 投影、实体分区。
- 0.7.3 - 2013 年 4 月 27 日:序列化性能改进,
ITableSet
的方法再次提供IEnumerable
。 - 0.7.4 - 2013 年 5 月 10 日:添加了 Contains 方法;LINQ 到 OData 转换器的性能优化。
- 0.7.6 - 2013 年 5 月 20 日:性能优化和代码稳定。
- 0.7.7 - 2013 年 8 月 10 日:代码稳定。