如何将 C# Azure.Data.Tables SDK 与 Azure Cosmos DB 结合使用

上个月,Azure SDK 团队发布了一个用于 .NET、Java、JS/TS 和 Python 的 Azure 表的新库。此版本使 Table SDK 与其他Azure SDK保持一致,它们使用特定的 Azure Core 包来处理请求、错误和凭据。

Azure Cosmos DB 提供了一个表 API产品,它本质上是增强版的 Azure 表存储!如果您需要全球分布式的表存储服务,Azure Cosmos DB 应该是您的首选。

如果要在 Azure Cosmos DB 表 API 和常规 Azure 表存储之间做出选择,我建议阅读以下文章

在本文中,我将向您展示如何使用新的 Azure.Data.Table C# SDK 对 Azure Cosmos DB 表 API 帐户执行简单的操作。具体来说,我们将回顾:

  • 安装 SDK ?
  • 连接到我们的表格客户端并创建表格?
  • 定义我们的实体?
  • 添加实体➕
  • 执行事务性批处理操作?
  • 查询我们的表❓
  • 删除实体 ❌

让我们深入了解它!

安装 SDK ?

安装 SDK 非常简单。我们可以通过运行以下dotnet命令来做到这一点:

dotnet add package Azure.Data.Tables

如果您更喜欢使用 UI 来安装 NuGet 包,我们可以通过在 Visual Studio 中右键单击我们的 C# 项目,单击管理 NuGet 包并搜索Azure.Data.Tables包来实现:

连接到我们的表格客户端并创建表格?

SDK 为我们提供了两个客户端来与服务交互。TableServiceClient用于在帐户级别与我们的表进行交互

我们这样做是为了创建表、设置访问策略等。

我们也可以使用TableClient。这用于对我们的实体执行操作。我们还可以使用TableClient来创建表,如下所示:

TableClient tableClient = new TableClient(config["StorageConnection"], "Customers");
            await tableClient.CreateIfNotExistsAsync();

为了创建我们的表客户端,我从 Azure 传递了我的存储连接字符串以及我想要与之交互的表的名称。在下面的行中,如果表不存在,我们将创建它。

要获取存储连接字符串,我们可以从连接字符串下的 Cosmos DB 帐户执行此操作:

当我们第一次运行这段代码时,我们可以看到我们的数据资源管理器中已经创建了表:

定义我们的实体?

在表存储中,我们在表中创建需要分区键行键的实体。这些组合在我们的表中必须是唯一的。

实体有一组属性,强类型实体需要从ITableEntity接口扩展,它公开了 Partition Key、Row Key、ETag 和 Timestamp 属性。ETag 和 Timestamp 将由 Cosmos DB 生成,因此我们不需要设置这些。

在本教程中,我将使用上述属性以及两个字符串属性(Email 和 PhoneNumber)来构成CustomerEntity类型。

public class CustomerEntity : ITableEntity
{
    public string PartitionKey { get; set ; }
    public string RowKey { get; set; }
    public string Email { get; set; }
    public string PhoneNumber { get; set; }
    public DateTimeOffset? Timestamp { get; set; }
    public ETag ETag { get; set; }
}

添加实体➕

要将新实体添加到我们的表中,我们需要对其进行实例化并简单地调用.AddEntityAsync()方法来插入它:

CustomerEntity customerEntity = new CustomerEntity()
{
     PartitionKey = "Velida",
     RowKey = "Will",
     PhoneNumber = "0123456789",
     Email = "will@test.com"
};

await tableClient.AddEntityAsync(customerEntity);

回到 Cosmos DB 中的客户表,我们可以看到实体已成功插入。

执行事务性批处理操作?

表服务允许我们在单个批处理请求中进行多个操作。

交易是“全有或全无”,这意味着如果我们批次中的一个操作失败,它们都会失败!事务可以混合执行创建、删除、更新和更新插入操作。

请注意,事务中的所有操作都需要针对相同的分区键。

在下面的代码片段中,我正在创建一个CustomerEntity对象列表,我将作为批量创建操作将其插入到我的表中。

然后,我们创建一个TableTransactionAction类型的新列表,并将我们想要包含在批处理操作中的实体列表添加到其中。然后我们使用.SubmitTransactionAsync()方法提交批处理操作:

string partitionKey = "Velida";
List<CustomerEntity> familyList = new List<CustomerEntity>
{
      new CustomerEntity
      {
            PartitionKey = partitionKey,
            RowKey = "Don",
            PhoneNumber = "0987612345"
      },
      new CustomerEntity
      {
            PartitionKey = partitionKey,
            RowKey = "Jane",
            PhoneNumber = "0987612345"
      },
      new CustomerEntity
      {
            PartitionKey = partitionKey,
            RowKey = "Jan",
            PhoneNumber = "0987601298",
            Email = "jan@test.com"
      }
};

List<TableTransactionAction> addFamilyBatch = new List<TableTransactionAction>();

addFamilyBatch.AddRange(familyList.Select(f => new TableTransactionAction(TableTransactionActionType.Add, f)));

Response<IReadOnlyList<Response>> response = await tableClient.SubmitTransactionAsync(addFamilyBatch);

回到我们的表中,我们可以看到实体已成功插入到我们的表中:

查询我们的表❓

我们可以通过几种方式查询表存储中的数据。下面的代码片段使用 OData 表达式。

使用OData 查询过滤器可能会很痛苦,但 SDK 提供了一个帮助程序库,使它更容易一些。使用.CreateQueryFilter(),我们可以像这样编写 OData 查询:

Pageable<TableEntity> oDataQueryEntities = tableClient.Query<TableEntity>(filter: TableClient.CreateQueryFilter($"PartitionKey eq {partitionKey}"));

foreach (TableEntity entity in oDataQueryEntities)
{
    Console.WriteLine($"{entity.GetString("PartitionKey")}:{entity.GetString("RowKey")}");
}

运行此代码,我们可以看到我们的实体PartitionKeysRowKeys的串联,如下所示:

我们还可以使用 LINQ 表达式来查询我们的表。在这里,我使用 LINQ 查询来检索RowKey值为“Will”的CustomerEntity :

Pageable<CustomerEntity> linqEntities = tableClient.Query<CustomerEntity>(customer => customer.RowKey == "Will");

foreach (var entity in linqEntities)
{
     Console.WriteLine($"{entity.RowKey} {entity.PartitionKey}");
}

当这段代码运行时,我们可以看到我们的实体打印出来了:

删除实体 ❌

从我们的表中删除实体只是一个简单的.DeleteEntityAsync()调用。我们需要做的就是像这样传递我们的ParitionKeyRowKey值:

await tableClient.DeleteEntityAsync(partitionKey, "Will");

检查我们的表,我们可以看到我们的实体已被成功删除:

包起来

希望阅读本文后,您了解使用 Azure.Data.Tables SDK 非常简单。我喜欢 Azure SDK 团队采用的方法,使 SDK 彼此更加一致。

使用 Azure.Data.Tables SDK,我们可以构建适用于 Azure Cosmos DB 表存储和常规表存储的应用程序,因此,如果您发现您正在使用常规表存储构建应用程序并且您正在努力应对规模问题,您无需更改任何代码即可切换到 Cosmos DB!

如果您想了解有关 Azure.Data.Tables 库的更多信息,请查看此博客文章此 GitHub存储库!