Amazon DynamoDB - 适用于 Unity 的 AWS Mobile SDK

AWS SDK for .NET 现在随附适用于 Unity 的 AWS Mobile SDK。本指南引用适用于 Unity 的 Mobile SDK 的存档版本。有关更多信息,请参阅什么是适用于 Unity 的 AWS Mobile SDK?

Amazon DynamoDB

Amazon DynamoDB 是一项快速、高度可扩展、高度可用且经济实惠的非关系数据库服务。DynamoDB 消除了传统上对数据存储可扩展性的限制,同时保留了低延迟性和可预测的性能。有关 DynamoDB 的信息,请参阅 Amazon DynamoDB

适用于 Unity 的 AWS Mobile SDK 为您使用 DynamoDB 提供了高级库。您也可以直接针对低级 DynamoDB API 发出请求,但在大多数情况下,建议您使用高级库。AmazonDynamoDBClient 是高级库中一个特别有用的部分。使用此类,您可以执行创建、读取、更新和删除 (CRUD) 操作和执行查询。

注意

本文档中的一些示例使用文本框变量 ResultText 来显示跟踪输出。

集成 Amazon DynamoDB

要在 Unity 应用程序中使用 DynamoDB,需要将 Unity SDK 添加到您的项目中。如果您尚未添加,则下载适用于 Unity 的 SDK,并按照设置适用于 Unity 的 AWS Mobile SDK 中的说明操作。我们建议您使用 Amazon Cognito Identity 为您的应用程序提供临时的 AWS 凭证。这些凭证允许您的应用程序访问 AWS 服务和资源。

要在应用程序中使用 DynamoDB,必须设置正确的权限。以下 IAM 策略允许用户删除、获取、放置、扫描和更新特定的用 ARN 标识的 DynamoDB 表中的项目:

{ "Statement": [{ "Effect": "Allow", "Action": [ "dynamodb:DeleteItem", "dynamodb:GetItem", "dynamodb:PutItem", "dynamodb:Scan", "dynamodb:UpdateItem" ], "Resource": "arn:aws:dynamodb:us-west-2:123456789012:table/MyTable" }] }

此策略应当应用到分配给 Cognito 身份池的角色,但您需要用您的 DynamoDB 表的正确 ARN 来替换 Resource 值。Cognito 自动为您的新身份池创建一个角色,您可以在 IAM 控制台中将策略应用于此角色。

应根据您的应用程序的需要添加或删除允许的操作。要了解有关 IAM 策略的更多信息,请参阅使用 IAM。要了解更多有关 DynamoDB 特定策略的信息,请参阅使用 IAM 控制对 DynamoDB 资源的访问

创建 DynamoDB 表

现在,我们已设置了权限和凭证,接下来,我们为应用程序创建一个 DynamoDB 表。要创建表,请转至 DynamoDB 控制台并执行以下步骤:

  1. 单击创建表

  2. 输入 Bookstore 作为表名。

  3. 选择 Hash 作为主键类型。

  4. 选择数字并输入哈希属性名称的 id。单击 Continue

  5. 再次单击 Continue 以跳过添加索引步骤。

  6. 将读取容量设置为 10,将写入容量设置为 5。单击 Continue

  7. 输入通知电子邮件,然后单击 Continue 来创建吞吐量警报。

  8. 单击 Create。DynamoDB 将创建您的数据库。

创建 DynamoDB 客户端

我们需要一个客户端来让应用程序与 DynamoDB 表交互。可以创建一个默认的 DynamodDB 客户端,如下所示:

var credentials = new CognitoAWSCredentials(IDENTITY_POOL_ID, RegionEndpoint.USEast1); AmazonDynamoDBClient client = new AmazonDynamoDBClient(credentials); DynamoDBContext Context = new DynamoDBContext(client);

AmazonDynamoDBClient 类是 DynamoDB API 的入口点。该类提供实例方法,用于创建、描述、更新和删除表以及其他操作。上下文在客户端之上又增加了一个抽象层,使您能够使用对象持久化模型等其他功能。

描述表

要获取 DynamoDB 表的描述,可以使用以下代码:

resultText.text +=("\n*** Retrieving table information ***\n"); var request = new DescribeTableRequest { TableName = @"ProductCatalog" }; Client.DescribeTableAsync(request, (result) => { if (result.Exception != null) { resultText.text += result.Exception.Message; Debug.Log(result.Exception); return; } var response = result.Response; TableDescription description = response.Table; resultText.text += ("Name: " + description.TableName + "\n"); resultText.text += ("# of items: " + description.ItemCount + "\n"); resultText.text += ("Provision Throughput (reads/sec): " + description.ProvisionedThroughput.ReadCapacityUnits + "\n"); resultText.text += ("Provision Throughput (reads/sec): " + description.ProvisionedThroughput.WriteCapacityUnits + "\n"); }, null); }

在此示例中,我们创建了一个客户端和一个 DescribeTableRequest 对象,将表的名称赋给 TableName 属性,然后将请求对象传递给 AmazonDynamoDBClient 对象上的 DescribeTableAsync 方法。DescribeTableAsync 还采用将在异步操作完成时调用的委托。

注意

AmazonDynamoDBClient 上的所有异步方法都采用异步操作完成时调用的委托。

保存对象

要将对象保存到 DynamoDB,请使用 AmazonDynamoDBClient 对象的 SaveAsync<T> 方法,其中 T 是要保存的对象的类型。

我们将我们的数据库称为“书店”,围绕这个主题,我们将实施一个数据模型,用于记录图书相关的属性。以下是定义我们的数据模型的类。

[DynamoDBTable("ProductCatalog")] public class Book { [DynamoDBHashKey] // Hash key. public int Id { get; set; } [DynamoDBProperty] public string Title { get; set; } [DynamoDBProperty] public string ISBN { get; set; } [DynamoDBProperty("Authors")] // Multi-valued (set type) attribute. public List<string> BookAuthors { get; set; } }

当然,就真正的书店应用程序而言,一些事项(如作者和价格等)需要附加字段。Book 类使用 [DynamoDBTable] 属性进行修饰,这将定义将写入的类型为 Book 的数据库表对象。Book 类的每个实例的键都使用 [DynamoDBHashKey] 属性进行标识。属性使用 [DynamoDBProperty] 属性进行标识,它们指定将写入属性的数据库表中的列。借助现成模型,我们可以编写一些方法来创建、检索、更新和删除 Book 对象。

创建书籍

private void PerformCreateOperation() { Book myBook = new Book { Id = bookID, Title = "object persistence-AWS SDK for.NET SDK-Book 1001", ISBN = "111-1111111001", BookAuthors = new List<string> { "Author 1", "Author 2" }, }; // Save the book. Context.SaveAsync(myBook,(result)=>{ if(result.Exception == null) resultText.text += @"book saved"; }); }

检索书籍

private void RetrieveBook() { this.displayMessage += "\n*** Load book**\n"; Context.LoadAsync<Book>(bookID, (AmazonDynamoResult<Book> result) => { if (result.Exception != null) { this.displayMessage += ("LoadAsync error" +result.Exception.Message); Debug.LogException(result.Exception); return; } _retrievedBook = result.Response; this.displayMessage += ("Retrieved Book: " + "\nId=" + _retrievedBook.Id + "\nTitle=" + _retrievedBook.Title + "\nISBN=" + _retrievedBook.ISBN); string authors = ""; foreach(string author in _retrievedBook.BookAuthors) authors += author + ","; this.displayMessage += "\nBookAuthor= "+ authors; this.displayMessage += ("\nDimensions= "+ _retrievedBook.Dimensions.Length + " X " + _retrievedBook.Dimensions.Height + " X " + _retrievedBook.Dimensions.Thickness); }, null); }

更新书籍

private void PerformUpdateOperation() { // Retrieve the book. Book bookRetrieved = null; Context.LoadAsync<Book>(bookID,(result)=> { if(result.Exception == null ) { bookRetrieved = result.Result as Book; // Update few properties. bookRetrieved.ISBN = "222-2222221001"; // Replace existing authors list with this bookRetrieved.BookAuthors = new List<string> { "Author 1", "Author x" }; Context.SaveAsync<Book>(bookRetrieved,(res)=> { if(res.Exception == null) resultText.text += ("\nBook updated"); }); } }); }

删除书籍

private void PerformDeleteOperation() { // Delete the book. Context.DeleteAsync<Book>(bookID,(res)=> { if(res.Exception == null) { Context.LoadAsync<Book>(bookID,(result)=> { Book deletedBook = result.Result; if(deletedBook==null) resultText.text += ("\nBook is deleted"); }); } }); }