练习 - 创建新项
回想一下,你可以使用 Azure Cosmos DB .NET SDK 在容器中创建项。 对于此项目,产品容器包含每个类别的各个产品项和特殊类别项。 在此应用程序中需要处理两种情况:
- 如果某个类别为空,则可以单独创建该类别的项。 没有要创建的相关产品项。
- 但是,如果某个类别包含相关产品,则需要同时创建类别项和相关产品项。
现在,有两个关键要求:
- 以单个操作的形式单独创建项
- 使用事务性批处理创建多个相关项
完成本练习后,项目将具有在容器中单独或批量创建项的逻辑。
将单个项添加到容器
在 Azure Cosmos DB 中,可以在容器中创建、替换或更新插入项。 创建项要求该项具有唯一标识符。 替换项要求该项已存在。 更新插入是两全其美的方法,它将检查唯一标识符,然后替换或创建项。 在本项目中,你希望能够多次运行应用而不会出错,这使得更新插入成为一个明确的选择。 对于第一个项,我们将创建没有关联产品的类别。 在这里,你将使用手动创建的类别实现单个更新插入操作。
再次打开 Program.cs 文件。
使用以下值创建一个名为
goggles
的新 Category 实例:属性 值 id ef7fa0f1-0e9d-4435-aaaf-a778179a94ad
categoryId gear-snow-goggles
Category goggles = new( Id: "ef7fa0f1-0e9d-4435-aaaf-a778179a94ad", CategoryId: "gear-snow-goggles" );
使用与前面创建的 Category 实例的
categoryId
属性相同的值创建新的 PartitionKey 实例。PartitionKey gogglesKey = new("gear-snow-goggles");
使用 UpsertItemAsync 方法创建或替换传递给要创建项的对象和分区键值的项。
Category result = await container.UpsertItemAsync(goggles, gogglesKey);
将
result
的各种属性打印到控制台,包括:项的唯一标识符和项的类型。Console.WriteLine($"[New item created]:\t{result.Id}\t(Type: {result.Type})");
使用以下值创建一个名为
helmets
的新 Category 实例:属性 值 id 91f79374-8611-4505-9c28-3bbbf1aa7df7
categoryId gear-climb-helmets
Category helmets = new( Id: "91f79374-8611-4505-9c28-3bbbf1aa7df7", CategoryId: "gear-climb-helmets" );
使用与前面创建的 Category 实例的
categoryId
属性相同的值创建新的 PartitionKey 实例。PartitionKey helmetsKey = new("gear-climb-helmets");
使用 UpsertItemAsync 方法创建或替换项。 传入要创建项的对象和分区键值。 返回 ItemResponse<T> 类型的对象。
ItemResponse<Category> response = await container.UpsertItemAsync(helmets, helmetsKey);
将
response
的各种属性打印到控制台,包括:基础项的唯一标识符、基础项的类型以及 RU 中的请求费用。Console.WriteLine($"[New item created]:\t{response.Resource.Id}\t(Type: {response.Resource.Type})\t(RUs: {response.RequestCharge})");
保存 Program.cs 文件。
以事务性批处理的形式实现多个操作
现在,请考虑要创建多个产品以及一个类别的场景。 如果已创建产品,但类别不存在,那么这些产品并不十分有用。 在创建多个项的情况下,你可以使用事务将多个“点”操作组合在一起,以便它们作为单个内聚单元都成功或失败。 返回到我们的场景,我们需要创建一个包含一些帐篷产品的户外帐篷类别。 我们已有一个没有任何产品项的单个类别项。 最终结果如下:
Azure Cosmos DB 中的各项按其特定分区键组织的示意图。 该图说明了五个项如何属于“帐篷”分区键值,而只有一个项属于“头盔”。
在本节中,我们将创建一个事务性批处理,以同时创建 tents
类别和相关产品。
在 Program.cs 中,使用以下值创建一个名为
tents
的新 Category 实例:Property 值 id 5df21ec5-813c-423e-9ee9-1a2aaead0be4
categoryId gear-camp-tents
Category tents = new( Id: "5df21ec5-813c-423e-9ee9-1a2aaead0be4", CategoryId: "gear-camp-tents" );
使用这些值创建四个 Product 类型的实例。
属性 cirroa
kuloar
mammatin
nimbolo
Id e8dddee4-9f43-4d15-9b08-0d7f36adcac8
e6f87b8d-8cd7-4ade-a005-14d3e2fbd1aa
f7653468-c4b8-47c9-97ff-451ee55f4fd5
6e3b7275-57d4-4418-914d-14d1baca0979
CategoryId gear-camp-tents
gear-camp-tents
gear-camp-tents
gear-camp-tents
名称 Cirroa Tent
Kuloar Tent
Mammatin Tent
Nimbolo Tent
价格 490.00
530.00
0.00
330.00
Archived false
false
true
false
数量 15
8
0
35
Product cirroa = new( Id: "e8dddee4-9f43-4d15-9b08-0d7f36adcac8", CategoryId: "gear-camp-tents" ){ Name = "Cirroa Tent", Price = 490.00m, Archived = false, Quantity = 15 };
Product kuloar = new( Id: "e6f87b8d-8cd7-4ade-a005-14d3e2fbd1aa", CategoryId: "gear-camp-tents" ){ Name = "Kuloar Tent", Price = 530.00m, Archived = false, Quantity = 8 };
Product mammatin = new( Id: "f7653468-c4b8-47c9-97ff-451ee55f4fd5", CategoryId: "gear-camp-tents" ){ Name = "Mammatin Tent", Price = 0.00m, Archived = true, Quantity = 0 };
Product nimbolo = new( Id: "6e3b7275-57d4-4418-914d-14d1baca0979", CategoryId: "gear-camp-tents" ){ Name = "Nimbolo Tent", Price = 330.00m, Archived = false, Quantity = 35 };
现在,使用
gear-camp-tents
值创建一个新的 PartitionKey 实例。PartitionKey tentsKey = new("gear-camp-tents");
使用 CreateTransactionalBatch(PartitionKey) 方法创建范围限定为
gear-camp-tents
分区键值的新事务性批处理。 使用 Fluent 语法,添加五个更新插入操作,以在容器中为类别和所有相关产品创建所需的项。TransactionalBatch batch = container.CreateTransactionalBatch(tentsKey) .UpsertItem<Category>(tents) .UpsertItem<Product>(cirroa) .UpsertItem<Product>(kuloar) .UpsertItem<Product>(mammatin) .UpsertItem<Product>(nimbolo);
向控制台输出一条消息,指示我们正在启动批处理操作。
Console.WriteLine("[Batch started]");
使用
TransactionalBatch.ExecuteAsync
方法执行批处理并返回特殊响应类型。using TransactionalBatchResponse batchResponse = await batch.ExecuteAsync();
使用 for 循环,循环访问响应中的所有项。 首先,使用
Item
基类作为泛型将每个项转换为TransactionalBatchOperationResult
类型。 然后,打印响应对象的唯一标识符和类型。for (int i = 0; i < batchResponse.Count; i++) { TransactionalBatchOperationResult<Item> batchResult = batchResponse.GetOperationResultAtIndex<Item>(i); Console.WriteLine($"[New item created]:\t{batchResult.Resource.Id}\t(Type: {batchResult.Resource.Type})"); }
向控制台输出另一条消息,指示批处理已完成。 在此消息中包含整个批处理的请求费用。
Console.WriteLine($"[Batch completed]:\t(RUs: {batchResponse.RequestCharge})");
保存 Program.cs 文件。
检查你的工作
现在,应用将创建多个项,且设计为具有足够的弹性,以便多次运行,而不会引发异常。 在这里,你将运行应用程序,并检查输出中六个新创建的项是否都有唯一标识符。
在终端中运行 .NET 应用程序:
dotnet run
观察运行应用程序的输出。 输出应匹配此处的示例:
... [New item created]: ef7fa0f1-0e9d-4435-aaaf-a778179a94ad (Type: Category) [New item created]: 91f79374-8611-4505-9c28-3bbbf1aa7df7 (Type: Category) (RUs: 10.29) [Batch started] [New item created]: 5df21ec5-813c-423e-9ee9-1a2aaead0be4 (Type: Category) [New item created]: e8dddee4-9f43-4d15-9b08-0d7f36adcac8 (Type: Product) [New item created]: e6f87b8d-8cd7-4ade-a005-14d3e2fbd1aa (Type: Product) [New item created]: f7653468-c4b8-47c9-97ff-451ee55f4fd5 (Type: Product) [New item created]: 6e3b7275-57d4-4418-914d-14d1baca0979 (Type: Product) [Batch completed]: (RUs: 36.76)
提示
本示例输出中显示的 RU 可能与输出不同。