65.9K
CodeProject 正在变化。 阅读更多。
Home

Windows Azure 存储扩展

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.97/5 (12投票s)

2013年4月13日

CPOL

6分钟阅读

viewsIcon

56887

downloadIcon

479

.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 Storage Extensions

背景

目前,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; }  
}

除了提供具有 PartitionKeyRowKeyTimestampETag 属性的 ITableEntity 接口外,它还使用缓慢的反射进行实体序列化/反序列化。

低抽象级别

对我这样的软件工程师来说,Azure Storage Library v2.0 似乎是对 Azure Tables REST API 的一个过于低级的抽象。例如,当我想使用 DTO 实体时,我必须记住 PartitionKey 是用户标识符,实际上它没有实际意义,我们应该使用某种实体映射器。查询也是一项过于复杂的任务。

Windows Azure Storage Extensions

Windows Azure Storage Extensions 库提供以下功能。

POCO

实体属性和字段应通过一个或两个 PartitionKeyRowKey 属性进行标记,以定义复合表键。还可以使用 TimestampETagPropertyIgnore 属性。

Attribute 描述 约束
PartitionKey 定义分区键属性。 仅限于字符串属性。
RowKey 定义行键属性。 仅限于字符串属性。
ETag 定义 etag 属性。 仅限于字符串属性。
时间戳 用于接收表实体时间戳。 仅限于 DateTimeDateTimeOffset 属性。
属性 用于通过 Name 属性定义自定义表属性名称。
Ignore 用于跳过属性的序列化/反序列化。

表实体管理

通用 TableSet 上下文提供同步和异步(TAP)方法来管理实体。

  • 同步AddAddOrUpdateUpdateRemove
  • 异步AddAsyncAddOrUpdateAsyncUpdateAsyncRemoveAsync

为避免 Azure 存储中的组操作限制,所有实体都按分区键排序,并合并成 100 个实体的组。可以通过 TableSetExecutionMode 属性配置此类批量操作的请求执行。允许的值

  • Sequential
  • 并行

默认 ExecutionModeSequential

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 中配置正确的连接字符串。

Example App

此示例中一个有趣的部分是 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 的核心组件包括:

表上下文

ITableSet

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、TableEntitynew 运算符的性能比较结果(毫秒)如下:

转换 10M 50M
DynamicTableEntityObject 8501 43,690
DynamicTableEntityPOCO 17,826 89,907
DynamicTableEntityTableEntity 54,158 276,421
ObjectDynamicTableEntity 10,693 51,485
POCODynamicTableEntity 15,528 78,368
TableEntityDynamicTableEntity 41,471 218,935

测试可在:EntityConverterTests.cs 中找到。

表查询提供程序

TableQueryProvider<T> 实现 IQueryProviderIAsyncQueryProvider 接口。它提供将 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 日:代码稳定。
© . All rights reserved.