

# .NET オブジェクト永続性モデルと DynamoDB の使用
<a name="DotNetSDKHighLevel"></a>

AWS SDK for .NET には、クライアント側クラスを Amazon DynamoDB テーブルにマッピングできるオブジェクト永続性モデルを有効にしています。各オブジェクトインスタンスが、対応するテーブルの項目にマッピングされます。クライアント側オブジェクトをテーブルに保存するために、オブジェクト永続性モデルでは、DynamoDB のエントリポイントとして `DynamoDBContext` クラスを使用できます。このクラスでは、DynamoDB に接続してテーブルにアクセスし、各種の CRUD オペレーションやクエリを実行することができます。

オブジェクト永続性モデルには、クライアント側クラスをテーブルにマッピングし、プロパティ/フィールドを属性にマッピングする、属性のセットが用意されています。

**注記**  
オブジェクト永続性モデルには、テーブルを作成、更新、または削除するための API はありません。データオペレーションだけが可能になっています。テーブルの作成、更新、削除が可能なのは AWS SDK for .NET の低レベル API だけです。

次の例は、オブジェクト永続性モデルの動作を示しています。`ProductCatalog` テーブルから開始します。ここでは `Id` がプライマリキーになっています。

```
ProductCatalog(Id, ...)
```

`Book`、`Title`、`ISBN` プロパティを持つ `Authors` クラスがあるとします。次の C\$1 サンプルコードに示すように、オブジェクト永続性モデルで定義された属性を追加することで、`Book` クラスを `ProductCatalog` テーブルにマッピングできます。

**Example**  

```
[DynamoDBTable("ProductCatalog")]
  public class Book
  {
    [DynamoDBHashKey]
    public int Id { get; set; }

    public string Title { get; set; }
    public int ISBN { get; set; }

    [DynamoDBProperty("Authors")]
    public List<string> BookAuthors { get; set; }

    [DynamoDBIgnore]
    public string CoverPage { get; set; }
  }
```

前述の例では、`DynamoDBTable` 属性によって、`Book` クラスが `ProductCatalog` テーブルにマッピングされています。

オブジェクト永続性モデルでは、クラスプロパティとテーブル属性との間で、明示的なマッピングとデフォルトのマッピングの両方がサポートされています。
+ **明示的なマッピング - ** プライマリキーにプロパティをマッピングするには、オブジェクト永続性モデル属性の `DynamoDBHashKey` および `DynamoDBRangeKey` を使用する必要があります。さらに、非プライマリキー属性については、クラス内のプロパティ名と、マッピング先の対応するテーブル属性が同じでない場合は、`DynamoDBProperty` 属性を明示的に追加してマッピングを定義する必要があります。

  前述の例では、`Id` プロパティが同じ名前のプライマリキーにマッピングされ、`BookAuthors` プロパティが `Authors` テーブル内の `ProductCatalog` 属性にマッピングされています。
+ **デフォルトのマッピング** – デフォルトでは、オブジェクト永続性モデルによって、クラスプロパティがテーブル内の同じ名前の属性にマッピングされます。

  前述の例では、`Title` および `ISBN` プロパティが、`ProductCatalog` テーブル内の同じ名前の属性にマッピングされています。

すべてのクラスプロパティをマッピングする必要はありません。これらのプロパティを特定するには、`DynamoDBIgnore` 属性を追加します。`Book` インスタンスをテーブルに保存する場合、`DynamoDBContext` には `CoverPage` プロパティは含まれません。このプロパティは、書籍インスタンスを取り出す場合にも返されません。

int や string など、.NET プリミティブ型のプロパティをマッピングできます。また、任意データをいずれかの DynamoDB 型にマッピングする適切なコンバーターがある限り、任意のデータ型をマッピングすることもできます。任意の型のマッピングについては、「[AWS SDK for .NET のオブジェクト永続性モデルを使用した、DynamoDB での任意データのマッピング](DynamoDBContext.ArbitraryDataMapping.md)」を参照してください。

オブジェクト永続性モデルでは、オプティミスティックロックがサポートされています。それによって、更新オペレーションで、更新する項目の最新のコピーを確実に使用することができます。詳細については、「[DynamoDB と AWS SDK for .NET のオブジェクト永続性モデルを使用した楽観的ロック](DynamoDBContext.VersionSupport.md)」を参照してください。

詳細については、以下のトピックを参照してください。

**Topics**
+ [サポートされているデータ型](#DotNetDynamoDBContext.SupportedTypes)
+ [.NET オブジェクト永続性モデルからの DynamoDB 属性](DeclarativeTagsList.md)
+ [.NET オブジェクト永続性モデルからの DynamoDBContext クラス](DotNetDynamoDBContext.md)
+ [DynamoDB と AWS SDK for .NET のオブジェクト永続性モデルを使用した楽観的ロック](DynamoDBContext.VersionSupport.md)
+ [AWS SDK for .NET のオブジェクト永続性モデルを使用した、DynamoDB での任意データのマッピング](DynamoDBContext.ArbitraryDataMapping.md)

## サポートされているデータ型
<a name="DotNetDynamoDBContext.SupportedTypes"></a>

オブジェクト永続性モデルでは、プリミティブな .NET データ型、コレクション、および任意のデータ型のセットがサポートされています。このモデルでは、次のプリミティブデータ型がサポートされています。
+ `bool`
+ `byte` 
+ `char`
+ `DateTime`
+ `decimal`
+ `double`
+ `float`
+ `Int16`
+ `Int32`
+ `Int64`
+ `SByte`
+ `string`
+ `UInt16`
+ `UInt32`
+ `UInt64`

オブジェクト永続性モデルでは .NET コレクション型もサポートされています。`DynamoDBContext` は具体的なコレクション型、およびシンプルな Plain Old CLR Objects (POCOs) を変換できます。

次の表に、前述の .NET 型が DynamoDB の型にどのようにマッピングされるかを示します。


****  

| .NET プリミティブ型 | DynamoDB 型 | 
| --- | --- | 
|  すべての数値型  |  `N`（数値型）  | 
|  すべての文字列型  |  `S` (文字列型)   | 
|  MemoryStream、byte[]  |  `B`（バイナリ型）   | 
| ブール | N (数値型)。0 は false、1 は true を表します。 | 
| コレクション型 | BS（バイナリセット）型、SS（文字列セット）型、NS（数値セット）型 | 
| DateTime | S (文字列型)。DateTime の値は、ISO-8601 形式の文字列として格納されます。 | 

オブジェクト永続性モデルでは、任意のデータ型もサポートされています。ただし、複合型を DynamoDB 型にマッピングする場合には、変換用のコードを用意する必要があります。

**注記**  
空のバイナリ値がサポートされています。
空の文字列値の読み取りがサポートされています。空の文字列属性値は、DynamoDB への書き込み中に、文字列セット型の属性値内でサポートされます。文字列型の空の文字列属性値と、リスト型またはマップ型に含まれる空の文字列値が書き込みリクエストから削除されます。

# .NET オブジェクト永続性モデルからの DynamoDB 属性
<a name="DeclarativeTagsList"></a>

このセクションでは、クラスとプロパティを DynamoDB のテーブルや属性にマッピングできるように、オブジェクト永続性モデルで提供されている属性を説明します。

**注記**  
次の属性では、`DynamoDBTable` と `DynamoDBHashKey` だけが必須です。

## DynamoDBGlobalSecondaryIndexHashKey
<a name="w2aac17b9c21c23c37b7"></a>

グローバルセカンダリインデックスのパーティションキーに、クラスプロパティをマッピングします。この属性は、グローバルセカンダリインデックスを `Query` する必要がある場合に使用します。

## DynamoDBGlobalSecondaryIndexRangeKey
<a name="w2aac17b9c21c23c37b9"></a>

グローバルセカンダリインデックスのソートキーにクラスプロパティをマッピングします。この属性は、グローバルセカンダリインデックスを `Query` し、インデックスソートキーを使用して結果を絞り込む必要がある場合に使用します。

## DynamoDBHashKey
<a name="w2aac17b9c21c23c37c11"></a>

テーブルのプライマリキーのパーティションキーにクラスプロパティをマッピングします。プライマリキーの属性をコレクション型にすることはできません。

次の C\$1 サンプルコードでは、`Book` クラスを `ProductCatalog` テーブルに、`Id` プロパティをテーブルのプライマリキーのパーティションキーにマッピングしています。

```
[DynamoDBTable("ProductCatalog")]
public class Book 
{
    [DynamoDBHashKey]
    public int Id { get; set; }

    // Additional properties go here.
}
```

## DynamoDBIgnore
<a name="w2aac17b9c21c23c37c13"></a>

関連するプロパティを無視するように指示します。クラスプロパティを保存しない場合は、この属性を追加することで、テーブルにオブジェクトを保存するときにこのプロパティを含めないように `DynamoDBContext` に指示できます。

## DynamoDBLocalSecondaryIndexRangeKey
<a name="w2aac17b9c21c23c37c15"></a>

ローカルセカンダリインデックスのソートキーにクラスプロパティをマッピングします。この属性は、ローカルセカンダリインデックスを `Query` し、インデックスソートキーを使用して結果を絞り込む必要がある場合に使用します。

## DynamoDBProperty
<a name="w2aac17b9c21c23c37c17"></a>

テーブルの属性にクラスプロパティをマッピングします。クラスプロパティを同じ名前のテーブル属性にマッピングする場合は、この属性を指定する必要はありません。ただし名前が異なる場合は、このタグを使用してマッピングを指定できます。次の C\$1 ステートメントでは、`DynamoDBProperty` によって、`BookAuthors` プロパティがテーブル内の `Authors` 属性にマッピングされています。

```
[DynamoDBProperty("Authors")]
public List<string> BookAuthors { get; set; }
```

`DynamoDBContext` はこのマッピング情報を使用して、対応するテーブルにオブジェクトデータを保存するときに `Authors` 属性を作成します。

## DynamoDBRenamable
<a name="w2aac17b9c21c23c37c19"></a>

クラスプロパティの代替名を指定します。これは、テーブル属性がクラスプロパティの名前と異なる DynamoDB テーブルに、任意データをマッピングするためのカスタムコンバーターを記述する場合に役立ちます。

## DynamoDBRangeKey
<a name="w2aac17b9c21c23c37c21"></a>

テーブルのプライマリキーのソートキーにクラスプロパティをマッピングします。テーブルに複合プライマリキー (パーティションキーおよびソートキー) がある場合は、クラスマッピングで、`DynamoDBHashKey` と `DynamoDBRangeKey` の両方の属性を指定する必要があります。

たとえば、サンプルテーブルの `Reply` には、`Id` パーティションキーと `Replenishment` ソートキーで構成されたプライマリキーがあります。次の C\$1 サンプルコードでは、`Reply` クラスを `Reply` テーブルにマッピングします。クラス定義では、プロパティのうち 2 つがプライマリキーにマッピングされることも示しています。

```
[DynamoDBTable("Reply")]
public class Reply 
{
   [DynamoDBHashKey]
   public int ThreadId { get; set; }
   [DynamoDBRangeKey]
   public string Replenishment { get; set; }
   
   // Additional properties go here.
}
```

## DynamoDBTable
<a name="w2aac17b9c21c23c37c23"></a>

クラスがマッピングされる、DynamoDB 内のターゲットテーブルを識別します。例えば次の C\$1 サンプルコードでは、`Developer` クラスを DynamoDB の `People` テーブルにマッピングしています。

```
[DynamoDBTable("People")]
public class Developer { ...}
```

この属性は、継承またはオーバーライドすることができます。
+ `DynamoDBTable` 属性は継承できます。前述の例では、`Lead` クラスから継承された新しいクラス `Developer` を追加すると、`People` テーブルにもマッピングされます。`Developer` テーブルに `Lead` と `People` の両方のオブジェクトが格納されます。
+ `DynamoDBTable` 属性もオーバーライドできます。次の C\$1 サンプルコードでは、`Manager` クラスは、`Developer` クラスから継承されます。ただし、`DynamoDBTable` 属性を明示的に追加すると、クラスは別のテーブル (`Managers`) にマップされます。

  ```
  [DynamoDBTable("Managers")]
  public class Manager : Developer { ...}
  ```

 次の C\$1 の例に示すように、オプションのパラメータ `LowerCamelCaseProperties` を追加すると、オブジェクトをテーブルに格納する際にプロパティ名の先頭文字を小文字にするよう、DynamoDB にリクエストを送ることができます。

```
[DynamoDBTable("People", LowerCamelCaseProperties=true)]
public class Developer 
{
    string DeveloperName;
    ...
}
```

`Developer` クラスのインスタンスを保存する場合、`DynamoDBContext` では `DeveloperName` プロパティが `developerName` として保存されます。

## DynamoDBVersion
<a name="w2aac17b9c21c23c37c25"></a>

項目のバージョン番号を格納するクラスプロパティを識別します。バージョニングの詳細については、「[DynamoDB と AWS SDK for .NET のオブジェクト永続性モデルを使用した楽観的ロック](DynamoDBContext.VersionSupport.md)」を参照してください。

# .NET オブジェクト永続性モデルからの DynamoDBContext クラス
<a name="DotNetDynamoDBContext"></a>

`DynamoDBContext` クラスは Amazon DynamoDB データベースのエントリポイントです。このクラスから DynamoDB に接続して、各種のテーブル内のデータにアクセスし、さまざまな CRUD オペレーションとクエリを実行することができます。`DynamoDBContext` クラスでは次のメソッドを使用できます。

**Topics**
+ [Create​MultiTable​BatchGet](#w2aac17b9c21c23c39b7)
+ [Create​MultiTable​BatchWrite](#w2aac17b9c21c23c39b9)
+ [CreateBatchGet](#w2aac17b9c21c23c39c11)
+ [CreateBatchWrite](#w2aac17b9c21c23c39c13)
+ [Delete](#w2aac17b9c21c23c39c15)
+ [Dispose](#w2aac17b9c21c23c39c17)
+ [Execute​Batch​Get](#w2aac17b9c21c23c39c19)
+ [Execute​Batch​Write](#w2aac17b9c21c23c39c21)
+ [FromDocument](#w2aac17b9c21c23c39c23)
+ [FromQuery](#w2aac17b9c21c23c39c25)
+ [FromScan](#w2aac17b9c21c23c39c27)
+ [Get​Target​Table](#w2aac17b9c21c23c39c29)
+ [Load](#w2aac17b9c21c23c39c31)
+ [Query](#w2aac17b9c21c23c39c33)
+ [保存](#w2aac17b9c21c23c39c35)
+ [Scan](#w2aac17b9c21c23c39c37)
+ [ToDocument](#w2aac17b9c21c23c39c39)
+ [DynamoDBContext でのオプションパラメータの指定](#OptionalConfigParams)

## Create​MultiTable​BatchGet
<a name="w2aac17b9c21c23c39b7"></a>

複数の個々の `MultiTableBatchGet` オブジェクトで構成される `BatchGet` オブジェクトを作成します。これらの各 `BatchGet` オブジェクトは、単一の DynamoDB テーブルから項目を取り出す場合に使用します。

1 つ以上のテーブルから項目を取得するには、`ExecuteBatchGet` メソッドを使用し、`MultiTableBatchGet` オブジェクトをパラメータとして渡します。

## Create​MultiTable​BatchWrite
<a name="w2aac17b9c21c23c39b9"></a>

複数の個々の `MultiTableBatchWrite` オブジェクトで構成される `BatchWrite` オブジェクトを作成します。これらの各 `BatchWrite` オブジェクトは、単一の DynamoDB テーブルに項目を書き込んだり、それを削除したりするために使用します。

テーブルに書き込むには、`ExecuteBatchWrite` メソッドを使用し、`MultiTableBatchWrite` オブジェクトをパラメータとして渡します。

## CreateBatchGet
<a name="w2aac17b9c21c23c39c11"></a>

テーブルから複数の項目を取り出すために使用できる `BatchGet` オブジェクトを作成します。

## CreateBatchWrite
<a name="w2aac17b9c21c23c39c13"></a>

テーブルに複数の項目を入力する、またはテーブルから複数の項目を削除するために使用できる `BatchWrite` オブジェクトを作成します。

## Delete
<a name="w2aac17b9c21c23c39c15"></a>

テーブルから項目を削除します。このメソッドでは、削除する項目のプライマリキーが必要になります。プライマリキーの値、またはこのメソッドのパラメータとしてプライマリキーの値を使用するクライアント側オブジェクトを入力できます。
+ クライアント側オブジェクトをパラメータとして指定し、オプティミスティックロックを有効にすると、クライアント側とサーバー側のオブジェクトのバージョンが一致する場合のみ、削除が成功します。
+ プライマリキーの値だけをパラメータとして指定すると、オプティミスティックロックを有効にしているかどうかにかかわらず、削除が成功します。

**注記**  
このオペレーションをバックグラウンドで実行するには、`DeleteAsync` メソッドを使用します。

## Dispose
<a name="w2aac17b9c21c23c39c17"></a>

すべてのマネージドリソースとアンマネージドリソースを破棄します。

## Execute​Batch​Get
<a name="w2aac17b9c21c23c39c19"></a>

1 つ以上のテーブルからデータを読み込みます。`BatchGet` 内のすべての `MultiTableBatchGet` オブジェクトを処理します。

**注記**  
このオペレーションをバックグラウンドで実行するには、`ExecuteBatchGetAsync` メソッドを使用します。

## Execute​Batch​Write
<a name="w2aac17b9c21c23c39c21"></a>

1 つ以上のテーブルにデータを書き込むまたは削除します。`BatchWrite` 内のすべての `MultiTableBatchWrite` オブジェクトを処理します。

**注記**  
このオペレーションをバックグラウンドで実行するには、`ExecuteBatchWriteAsync` メソッドを使用します。

## FromDocument
<a name="w2aac17b9c21c23c39c23"></a>

`Document` のインスタンスと仮定すると、`FromDocument` メソッドは、クライアント側のクラスのインスタンスを返します。

これは、オブジェクト永続性モデルと合わせてドキュメントモデルクラスを使用してデータオペレーションを行う場合に役立ちます。AWS SDK for .NET で使用されるドキュメントモデルクラスの詳細については、「[DynamoDB での .NET ドキュメントの操作](DotNetSDKMidLevel.md)」を参照してください。

`Document` という名前の `doc` オブジェクトがあり、`Forum` 項目の表現を含んでいるとします。(このオブジェクトの構成方法については、下の `ToDocument` メソッドの説明を参照してください)。次の C\$1 サンプルコードに示すように、`FromDocument` を使用して `Forum` から `Document` 項目を取得することができます。

**Example**  

```
forum101 = context.FromDocument<Forum>(101);
```

**注記**  
`Document` オブジェクトで `IEnumerable` インターフェイスを実装している場合、`FromDocuments` メソッドを使用できます。これにより、`Document` のすべてのクラスインスタンスを反復的に処理できます。

## FromQuery
<a name="w2aac17b9c21c23c39c25"></a>

`QueryOperationConfig` オブジェクトに定義されたクエリパラメータを使用して、`Query` オペレーションを実行します。

**注記**  
このオペレーションをバックグラウンドで実行するには、`FromQueryAsync` メソッドを使用します。

## FromScan
<a name="w2aac17b9c21c23c39c27"></a>

`ScanOperationConfig` オブジェクトに定義されたスキャンパラメータを使用して、`Scan` オペレーションを実行します。

**注記**  
このオペレーションをバックグラウンドで実行するには、`FromScanAsync` メソッドを使用します。

## Get​Target​Table
<a name="w2aac17b9c21c23c39c29"></a>

指定した型のターゲットテーブルを取り出します。これは、任意データを DynamoDB テーブルにマッピングするためのカスタムコンバーターを記述していて、カスタムデータ型に関連付けられているテーブルを特定する必要がある場合に役立ちます。

## Load
<a name="w2aac17b9c21c23c39c31"></a>

テーブルから項目を取り出します。このメソッドでは、取り出す項目のプライマリキーだけが必要になります。

DynamoDB のデフォルトでは、結果整合性のある値が含まれる項目が返されます。結果整合性モデルの詳細については、「[DynamoDB の読み取り整合性](HowItWorks.ReadConsistency.md)」を参照してください。

`Load` または `LoadAsync` メソッドは [GetItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_GetItem.html) オペレーションを呼び出します。このオペレーションでは、テーブルのプライマリキーを指定する必要があります。`GetItem` は `IndexName` パラメータを無視するため、インデックスのパーティションまたはソートキーを使用して項目を読み込むことはできません。そのため、テーブルのプライマリキーを使用して項目を読み込む必要があります。

**注記**  
このオペレーションをバックグラウンドで実行するには、`LoadAsync` メソッドを使用します。`LoadAsync` メソッドを使用して DynamoDB テーブルで高レベルの CRUD オペレーションを実行する例については、次の例を参照してください。

```
    /// <summary>
    /// Shows how to perform high-level CRUD operations on an Amazon DynamoDB
    /// table.
    /// </summary>
    public class HighLevelItemCrud
    {
        public static async Task Main()
        {
            var client = new AmazonDynamoDBClient();
            DynamoDBContext context = new DynamoDBContext(client);
            await PerformCRUDOperations(context);
        }

        public static async Task PerformCRUDOperations(IDynamoDBContext context)
        {
            int bookId = 1001; // Some unique value.
            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 to the ProductCatalog table.
            await context.SaveAsync(myBook);

            // Retrieve the book from the ProductCatalog table.
            Book bookRetrieved = await context.LoadAsync<Book>(bookId);

            // Update some properties.
            bookRetrieved.Isbn = "222-2222221001";

            // Update existing authors list with the following values.
            bookRetrieved.BookAuthors = new List<string> { " Author 1", "Author x" };
            await context.SaveAsync(bookRetrieved);

            // Retrieve the updated book. This time, add the optional
            // ConsistentRead parameter using DynamoDBContextConfig object.
            await context.LoadAsync<Book>(bookId, new DynamoDBContextConfig
            {
                ConsistentRead = true,
            });

            // Delete the book.
            await context.DeleteAsync<Book>(bookId);

            // Try to retrieve deleted book. It should return null.
            Book deletedBook = await context.LoadAsync<Book>(bookId, new DynamoDBContextConfig
            {
                ConsistentRead = true,
            });

            if (deletedBook == null)
            {
                Console.WriteLine("Book is deleted");
            }
        }
    }
```

## Query
<a name="w2aac17b9c21c23c39c33"></a>

指定したクエリパラメータに基づいてテーブルのクエリが実行されます。

複合プライマリキー (パーティションキーおよびソートキー) が存在する場合にのみ、テーブルにクエリを実行できます。クエリを実行する場合は、パーティションキーと、ソートキーに適用される条件を指定する必要があります。

ここで、クライアント側の `Reply` クラスが、DynamoDB の `Reply` テーブルにマッピングされている場合を考えてみます。次の C\$1 サンプルコードでは、`Reply` テーブルのクエリを実行し、過去 15 日間に投稿されたフォーラムスレッドの返信を検索しています。`Reply` テーブルには、`Id` パーティションキーと `ReplyDateTime` ソートキーを持つプライマリキーがあります。

**Example**  

```
DynamoDBContext context = new DynamoDBContext(client);

string replyId = "DynamoDB#DynamoDB Thread 1"; //Partition key
DateTime twoWeeksAgoDate = DateTime.UtcNow.Subtract(new TimeSpan(14, 0, 0, 0)); // Date to compare.
IEnumerable<Reply> latestReplies = context.Query<Reply>(replyId, QueryOperator.GreaterThan, twoWeeksAgoDate);
```

これにより、`Reply` オブジェクトのコレクションが返されます。

`Query` メソッドでは、「遅延ロード」された `IEnumerable` コレクションが返ります。最初に結果が 1 ページのみ返され、必要に応じて、さらに次ページを要求するサービス呼び出しが行われます。一致する項目をすべて取得するには、`IEnumerable` を反復的に処理します。

テーブルにシンプルなプライマリキー (パーティションキー) がある場合は、`Query` メソッドを使用できません。代わりに `Load` メソッドを使用して、パーティションキーを入力して項目を取り出すことができます。

**注記**  
このオペレーションをバックグラウンドで実行するには、`QueryAsync` メソッドを使用します。

## 保存
<a name="w2aac17b9c21c23c39c35"></a>

指定したオブジェクトがテーブルに保存されます。入力オブジェクトで指定されたプライマリキーがテーブル内に存在しない場合は、このメソッドによって新しい項目がテーブルに追加されます。プライマリキーが存在する場合は、このメソッドによって既存の項目が更新されます。

オプティミスティックロックを設定している場合には、クライアント側とサーバー側で項目のバージョンが一致する場合のみ、更新が正常に実行されます。詳細については、「[DynamoDB と AWS SDK for .NET のオブジェクト永続性モデルを使用した楽観的ロック](DynamoDBContext.VersionSupport.md)」を参照してください。

**注記**  
このオペレーションをバックグラウンドで実行するには、`SaveAsync` メソッドを使用します。

## Scan
<a name="w2aac17b9c21c23c39c37"></a>

テーブル全体のスキャンを実行します。

スキャン結果をフィルタリングするには、スキャン条件を指定します。この条件は、テーブル内の任意の属性に適用することができます。例えば、クライアント側の `Book` クラスが、DynamoDB の `ProductCatalog` テーブルにマッピングされているとします。次の C\$1 コード例では、テーブルがスキャンされ、価格が 0 未満の書籍項目だけが返されています。

**Example**  

```
IEnumerable<Book> itemsWithWrongPrice = context.Scan<Book>(
                    new ScanCondition("Price", ScanOperator.LessThan, price),
                    new ScanCondition("ProductCategory", ScanOperator.Equal, "Book")
      );
```

`Scan` メソッドでは、「遅延ロード」された `IEnumerable` コレクションが返ります。最初に結果が 1 ページのみ返され、必要に応じて、さらに次ページを要求するサービス呼び出しが行われます。一致するすべての項目は、`IEnumerable` を反復的に処理するだけで取得できます。

パフォーマンス上の理由から、テーブルについてはスキャンを避け、クエリを行うようにしてください。

**注記**  
このオペレーションをバックグラウンドで実行するには、`ScanAsync` メソッドを使用します。

## ToDocument
<a name="w2aac17b9c21c23c39c39"></a>

クラスインスタンスから、`Document` ドキュメントモデルクラスのインスタンスが返されます。

これは、オブジェクト永続性モデルと合わせてドキュメントモデルクラスを使用してデータオペレーションを行う場合に役立ちます。AWS SDK for .NET で使用されるドキュメントモデルクラスの詳細については、「[DynamoDB での .NET ドキュメントの操作](DotNetSDKMidLevel.md)」を参照してください。

クライアント側のクラスが `Forum` サンプルテーブルにマッピングされているとします。その場合は次の C\$1 サンプルコードに示すように、`DynamoDBContext` を使用して、`Document` テーブルから項目を `Forum` オブジェクトとして取得することができます。

**Example**  

```
DynamoDBContext context = new DynamoDBContext(client);

Forum forum101 = context.Load<Forum>(101); // Retrieve a forum by primary key.
Document doc = context.ToDocument<Forum>(forum101);
```

## DynamoDBContext でのオプションパラメータの指定
<a name="OptionalConfigParams"></a>

オブジェクト永続性モデルを使用する場合は、`DynamoDBContext` に次のオプションパラメータを指定できます。
+ **`ConsistentRead`-**`Load`、`Query`、または `Scan` オペレーションを使用してデータを取得する場合、このオプションパラメータを追加して、データの最新の値をリクエストすることができます。
+ **`IgnoreNullValues`-**このパラメータにより、`Save` オペレーション時に属性の null 値を無視するように `DynamoDBContext` に指示できます。このパラメータが false の場合 (または設定されていない場合)、null 値は、特定の属性を削除するディレクティブと見なされます。
+ **`SkipVersionCheck`–**このパラメータは、項目の保存または削除を実行する際、バージョンの比較を行わないように `DynamoDBContext` に指示します。バージョニングの詳細については、「[DynamoDB と AWS SDK for .NET のオブジェクト永続性モデルを使用した楽観的ロック](DynamoDBContext.VersionSupport.md)」を参照してください。
+ **`TableNamePrefix`-**すべてのテーブル名に特定の文字列をプレフィックスします。このパラメータが null の場合（または設定されていない場合）、プレフィックスは使用されません。
+ `DynamoDBEntryConversion` – クライアントで使用する変換スキーマを指定します。このパラメータはバージョン V1 または V2 に設定できます。デフォルトのバージョンは V1 です。

  設定したバージョンに応じて、このパラメータの動作が変わります。例えば、次のようになります。
  + V1 では、`bool` データ型が `N` 数値型に変換されます。0 は false、1 は true を表します。V2 では、`bool` が `BOOL` に変換されます。
  + V2 の場合、リストと配列は HashSets と一緒にグループ化されません。数値、文字列ベースの型、バイナリベースの型のリストと配列は `L` (List) 型に変換され、リストを更新するために空で送信できます。この動作は、空のリストがワイヤ経由で送信されない V1 とは異なります。

    V1 の場合、List、HashSet、配列などのコレクションタイプは同じように扱われます。List、HashSet、数値の配列は `NS` (数値セット) 型に変換されます。

  次の例では、変換スキーマのバージョンを V2 に設定し、.NET 型と DynamoDB データ型間の変換動作を変更します。

  ```
  var config = new DynamoDBContextConfig
  {
      Conversion = DynamoDBEntryConversion.V2
  };
  var contextV2 = new DynamoDBContext(client, config);
  ```

次の C\$1 サンプルコードでは、前述のオプションパラメータのうち 2 つ (`ConsistentRead` と `SkipVersionCheck`) を指定して、新しい `DynamoDBContext` を作成します。

**Example**  

```
AmazonDynamoDBClient client = new AmazonDynamoDBClient();
...
DynamoDBContext context =
       new DynamoDBContext(client, new DynamoDBContextConfig { ConsistentRead = true, SkipVersionCheck = true});
```

`DynamoDBContext` では、このコンテキストを使用して送信した各リクエストに、これらのオプションパラメータが含められます。

次の C\$1 サンプルコードに示すように、これらのパラメータを `DynamoDBContext` レベルで設定する代わりに、`DynamoDBContext` を使用して実行するオペレーションに対して個別に指定することもできます。この例では特定の書籍項目がロードされています。`DynamoDBContext` の `Load` メソッドでは、オプションパラメータとして `ConsistentRead` と `SkipVersionCheck` を指定します。

**Example**  

```
AmazonDynamoDBClient client = new AmazonDynamoDBClient();
...
DynamoDBContext context = new DynamoDBContext(client);
Book bookItem = context.Load<Book>(productId,new DynamoDBContextConfig{ ConsistentRead = true, SkipVersionCheck = true });
```

この場合 `DynamoDBContext` には、`Get` リクエストを送信する場合のみ、これらのパラメータが含まれます。

# DynamoDB と AWS SDK for .NET のオブジェクト永続性モデルを使用した楽観的ロック
<a name="DynamoDBContext.VersionSupport"></a>

オブジェクト永続性モデルではオプティミスティックロックがサポートされており、項目を更新または削除する前に、アプリケーションの項目バージョンとサーバー側の項目バージョンが同じになります。更新する項目を取得するとします。しかし、更新を返送する前に、他のアプリケーションが同じ項目を更新しました。この場合、アプリケーションに項目の古いコピーが残ることになります。オプティミスティックロックがない場合に更新を行うと、他のアプリケーションで行われた更新が上書きされます。

オブジェクト永続性モデルのオプティミスティックロック機能では、オプティミスティックロックを有効にするために `DynamoDBVersion` タグを使用できます。この機能を使用するには、バージョン番号を格納するためのプロパティをクラスに追加します。`DynamoDBVersion` 属性をプロパティに追加します。最初にオブジェクトを保存すると、`DynamoDBContext` によってバージョン番号が割り当てられ、項目を更新するたびにその値が増えていきます。

更新または削除リクエストは、クライアント側のオブジェクトのバージョンが、サーバー側の対応する項目のバージョン番号に一致する場合のみ成功します。アプリケーションに古いコピーがある場合に項目を更新または削除するには、その前にサーバーから最新バージョンを取得する必要があります。

次の C\$1 サンプルコードでは、オブジェクト永続性属性と合わせて `Book` クラスを定義し、`ProductCatalog` テーブルにマッピングします。`VersionNumber` 属性が指定されたクラスの `DynamoDBVersion` プロパティには、バージョン番号が格納されます。

**Example**  

```
[DynamoDBTable("ProductCatalog")]
  public class Book
  {
    [DynamoDBHashKey]   //Partition key
    public int Id { get; set; }
    [DynamoDBProperty]
    public string Title { get; set; }
    [DynamoDBProperty]
    public string ISBN { get; set; }
    [DynamoDBProperty("Authors")]
    public List<string> BookAuthors { get; set; }
    [DynamoDBVersion]
    public int? VersionNumber { get; set; }
  }
```

**注記**  
`DynamoDBVersion` 属性は、null が許容された数値プリミティブ型（`int?` など）に対してのみ適用できます。

オプティミスティックロックは、`DynamoDBContext` オペレーションに対して次のような影響があります。
+ `DynamoDBContext` は、新しい項目に対して初期バージョン番号 0 を割り当てます。既存の項目を取得し、1 つ以上のプロパティを更新して変更を保存しようとすると、保存オペレーションは、クライアント側とサーバー側のバージョン番号が一致する場合にのみ成功します。`DynamoDBContext` によってバージョン番号が増加します。バージョン番号を設定する必要はありません。
+ 次の C\$1 サンプルコードに示すように、`Delete` メソッドでは、プライマリキーの値またはオブジェクトのいずれかをパラメータとして指定できるオーバーロードを使用できます。  
**Example**  

  ```
  DynamoDBContext context = new DynamoDBContext(client);
  ...
  // Load a book.
  Book book = context.Load<ProductCatalog>(111);
  // Do other operations.
  // Delete 1 - Pass in the book object.
  context.Delete<ProductCatalog>(book);
  
  // Delete 2 - Pass in the Id (primary key)
  context.Delete<ProductCatalog>(222);
  ```

  パラメータとしてオブジェクトを指定した場合、オブジェクトのバージョンがサーバー側の対応する項目のバージョンと一致する場合のみ、削除が成功します。ただし、パラメータとしてプライマリキーの値を入力した場合には、`DynamoDBContext` はバージョン番号を認識せず、バージョンチェックを行わずに項目を削除します。

  オブジェクト永続性モデルのコードで、オプティミスティックロックを内部実装する場合は、DynamoDB の条件付き更新と条件付き削除用の API アクションが使用されることに注意してください。

## 楽観的ロックの無効化
<a name="DotNetDynamoDBContext.DisablingOptimisticLocking"></a>

オプティミスティックロックを無効にするには、`SkipVersionCheck` 設定プロパティを使用します。このプロパティは、`DynamoDBContext` の作成時に設定できます。この場合、このコンテキストを使用して作成したすべてのリクエストについて、オプティミスティックロックが無効になります。詳細については、「[DynamoDBContext でのオプションパラメータの指定](DotNetDynamoDBContext.md#OptionalConfigParams)」を参照してください。

コンテキストレベルでプロパティを設定する代わりに、次の C\$1 サンプルコードに示すように、特定のオペレーションに対するオプティミスティックロックを無効にすることができます。この例では、このコンテキストを使用して書籍項目を削除しています。`Delete` メソッドはオプションの `SkipVersionCheck` プロパティを true に設定し、バージョンチェックを無効にします。

**Example**  

```
DynamoDBContext context = new DynamoDBContext(client);
// Load a book.
Book book = context.Load<ProductCatalog>(111);
...
// Delete the book.
context.Delete<Book>(book, new DynamoDBContextConfig { SkipVersionCheck = true });
```

# AWS SDK for .NET のオブジェクト永続性モデルを使用した、DynamoDB での任意データのマッピング
<a name="DynamoDBContext.ArbitraryDataMapping"></a>

サポート済みの .NET 型 (「[サポートされているデータ型](DotNetSDKHighLevel.md#DotNetDynamoDBContext.SupportedTypes)」を参照) に加えて、アプリケーション内にあり Amazon DynamoDB 型に直接マッピングされていない型を使用できます。オブジェクト永続性モデルでは、任意型から DynamoDB 型に (またはその反対に) データを変換できるコンバーターを用意することで、任意型のデータを格納できます。コンバーターコードによって、オブジェクトの保存およびロード中にデータが変換されます。

クライアント側で任意の型を作成できます。ただし、テーブルには、いずれかの DynamoDB 型を使用してデータが格納されます。また、クエリおよびスキャンの際のデータ比較は、DynamoDB に格納されているデータに対して行われます。

次の C\$1 コード例では、`Book`、`Id`、`Title`、および `ISBN` プロパティを使用して `Dimension` クラスを定義しています。`Dimension` プロパティは、`DimensionType`、`Height`、および `Width` プロパティを記述する `Thickness` に含まれています。このコード例では、コンバーターメソッド `ToEntry` および `FromEntry` によって、`DimensionType` と DynamoDB の文字列型との間でデータが変換されます。たとえば、`Book` インスタンスを保存すると、コンバータによって、「8.5 x 11 x 05」などの書籍 `Dimension` 文字列が作成されます。書籍を取得すると、その文字列は `DimensionType` インスタンスに変換されます。

この例では、`Book` 型を `ProductCatalog` テーブルにマッピングしています。サンプルの `Book` インスタンスを保存し、取得し、寸法を更新し、更新された `Book` を再度保存しています。



以下の例をテストするための詳細な手順については、「[.NET コード例](CodeSamples.DotNet.md)」を参照してください。

**Example**  

```
using System;
using System.Collections.Generic;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DataModel;
using Amazon.DynamoDBv2.DocumentModel;
using Amazon.Runtime;
using Amazon.SecurityToken;

namespace com.amazonaws.codesamples
{
    class HighLevelMappingArbitraryData
    {
        private static AmazonDynamoDBClient client = new AmazonDynamoDBClient();

        static void Main(string[] args)
        {
            try
            {
                DynamoDBContext context = new DynamoDBContext(client);

                // 1. Create a book.
                DimensionType myBookDimensions = new DimensionType()
                {
                    Length = 8M,
                    Height = 11M,
                    Thickness = 0.5M
                };

                Book myBook = new Book
                {
                    Id = 501,
                    Title = "AWS SDK for .NET Object Persistence Model Handling Arbitrary Data",
                    ISBN = "999-9999999999",
                    BookAuthors = new List<string> { "Author 1", "Author 2" },
                    Dimensions = myBookDimensions
                };

                context.Save(myBook);

                // 2. Retrieve the book.
                Book bookRetrieved = context.Load<Book>(501);

                // 3. Update property (book dimensions).
                bookRetrieved.Dimensions.Height += 1;
                bookRetrieved.Dimensions.Length += 1;
                bookRetrieved.Dimensions.Thickness += 0.2M;
                // Update the book.
                context.Save(bookRetrieved);

                Console.WriteLine("To continue, press Enter");
                Console.ReadLine();
            }
            catch (AmazonDynamoDBException e) { Console.WriteLine(e.Message); }
            catch (AmazonServiceException e) { Console.WriteLine(e.Message); }
            catch (Exception e) { Console.WriteLine(e.Message); }
        }
    }
    [DynamoDBTable("ProductCatalog")]
    public class Book
    {
        [DynamoDBHashKey] //Partition key
        public int Id
        {
            get; set;
        }
        [DynamoDBProperty]
        public string Title
        {
            get; set;
        }
        [DynamoDBProperty]
        public string ISBN
        {
            get; set;
        }
        // Multi-valued (set type) attribute.
        [DynamoDBProperty("Authors")]
        public List<string> BookAuthors
        {
            get; set;
        }
        // Arbitrary type, with a converter to map it to DynamoDB type.
        [DynamoDBProperty(typeof(DimensionTypeConverter))]
        public DimensionType Dimensions
        {
            get; set;
        }
    }

    public class DimensionType
    {
        public decimal Length
        {
            get; set;
        }
        public decimal Height
        {
            get; set;
        }
        public decimal Thickness
        {
            get; set;
        }
    }

    // Converts the complex type DimensionType to string and vice-versa.
    public class DimensionTypeConverter : IPropertyConverter
    {
        public DynamoDBEntry ToEntry(object value)
        {
            DimensionType bookDimensions = value as DimensionType;
            if (bookDimensions == null) throw new ArgumentOutOfRangeException();

            string data = string.Format("{1}{0}{2}{0}{3}", " x ",
                            bookDimensions.Length, bookDimensions.Height, bookDimensions.Thickness);

            DynamoDBEntry entry = new Primitive
            {
                Value = data
            };
            return entry;
        }

        public object FromEntry(DynamoDBEntry entry)
        {
            Primitive primitive = entry as Primitive;
            if (primitive == null || !(primitive.Value is String) || string.IsNullOrEmpty((string)primitive.Value))
                throw new ArgumentOutOfRangeException();

            string[] data = ((string)(primitive.Value)).Split(new string[] { " x " }, StringSplitOptions.None);
            if (data.Length != 3) throw new ArgumentOutOfRangeException();

            DimensionType complexData = new DimensionType
            {
                Length = Convert.ToDecimal(data[0]),
                Height = Convert.ToDecimal(data[1]),
                Thickness = Convert.ToDecimal(data[2])
            };
            return complexData;
        }
    }
}
```