/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using Amazon.DynamoDBv2.Model;
using Amazon.DynamoDBv2.DocumentModel;
#if AWS_ASYNC_API
using System.Threading.Tasks;
#endif
using System.Threading;
namespace Amazon.DynamoDBv2.DataModel
{
///
/// Represents a non-generic object for retrieving a batch of items
/// from a single DynamoDB table
///
public abstract partial class BatchGet
{
#region Internal/protected properties
///
/// Gets and sets the UntypedResults property.
///
protected List UntypedResults { get; set; }
internal DynamoDBContext Context { get; set; }
internal DynamoDBFlatConfig Config { get; set; }
internal List Keys { get; set; }
internal DocumentBatchGet DocumentBatch { get; set; }
internal ItemStorageConfig ItemStorageConfig { get; set; }
#endregion
#region Constructor
internal BatchGet(DynamoDBContext context, DynamoDBFlatConfig config)
{
Context = context;
Config = config;
Keys = new List();
}
#endregion
#region Public properties
///
/// List of results retrieved from DynamoDB.
/// Populated after Execute is called.
///
public List Results { get { return UntypedResults; } }
///
/// If set to true, a consistent read is issued. Otherwise eventually-consistent is used.
///
public bool ConsistentRead { get; set; }
#endregion
#region Protected methods
///
/// Executes a server call to batch-get the items requested.
/// Populates Results with the retrieved items.
///
internal protected abstract void ExecuteHelper();
#if AWS_ASYNC_API
///
/// Executes an asynchronous server call to batch-get the items requested.
/// Populates Results with the retrieved items.
///
internal protected abstract Task ExecuteHelperAsync(CancellationToken cancellationToken);
#endif
#endregion
#region Internal methods
internal abstract void CreateDocumentBatch();
internal abstract void PopulateResults(List items);
#endregion
}
///
/// Represents a strongly-typed object for retrieving a batch of items
/// from a single DynamoDB table
///
public class BatchGet : BatchGet
{
#region Public properties
///
/// List of results retrieved from DynamoDB.
/// Populated after Execute is called.
///
new public List Results { get { return TypedResults; } }
#endregion
#region Public methods
///
/// Add a single item to get, identified by its hash primary key.
///
/// Hash key of the item to get
public void AddKey(object hashKey)
{
AddKey(hashKey, null);
}
///
/// Add a single item to get, identified by its hash-and-range primary key.
///
/// Hash key of the item to get
/// Range key of the item to get
public void AddKey(object hashKey, object rangeKey)
{
Key key = Context.MakeKey(hashKey, rangeKey, ItemStorageConfig, Config);
Keys.Add(key);
}
///
/// Add a single item to get.
///
/// Object key of the item to get
public void AddKey(T keyObject)
{
Key key = Context.MakeKey(keyObject, ItemStorageConfig, Config);
Keys.Add(key);
}
///
/// Creates a MultiTableBatchGet object that is a combination
/// of the current BatchGet and the specified BatchGets
///
/// Other BatchGet objects
///
/// MultiTableBatchGet consisting of the multiple BatchGet objects:
/// the current batch and the passed-in batches.
///
public MultiTableBatchGet Combine(params BatchGet[] otherBatches)
{
return new MultiTableBatchGet(this, otherBatches);
}
#endregion
#region Constructor
internal BatchGet(DynamoDBContext context, DynamoDBFlatConfig config)
: base(context, config)
{
ItemStorageConfig = context.StorageConfigCache.GetConfig(config);
}
#endregion
#region Internal/protected/private members
///
/// Executes the batch get
///
internal protected override void ExecuteHelper()
{
CreateDocumentBatch();
DocumentBatch.ExecuteHelper();
PopulateResults(DocumentBatch.Results);
}
#if AWS_ASYNC_API
///
/// Executes the batch get asynchronously
///
internal protected override async Task ExecuteHelperAsync(CancellationToken cancellationToken)
{
CreateDocumentBatch();
await DocumentBatch.ExecuteHelperAsync(cancellationToken).ConfigureAwait(false);
PopulateResults(DocumentBatch.Results);
}
#endif
///
/// Gets and sets the TypedResults property.
///
protected List TypedResults { get; set; }
internal override void CreateDocumentBatch()
{
var storageConfig = Context.StorageConfigCache.GetConfig(Config);
var table = Context.GetTargetTable(storageConfig, Config);
DocumentBatchGet docBatch = new DocumentBatchGet(table)
{
AttributesToGet = storageConfig.AttributesToGet,
ConsistentRead = this.ConsistentRead
};
docBatch.Keys.AddRange(Keys);
DocumentBatch = docBatch;
}
internal override void PopulateResults(List items)
{
UntypedResults = new List();
TypedResults = new List();
foreach (var doc in items)
{
var item = Context.FromDocumentHelper(doc, Config);
TypedResults.Add(item);
UntypedResults.Add(item);
}
}
#endregion
}
///
/// Class for retrieving a batch of items from multiple DynamoDB tables,
/// using multiple strongly-typed BatchGet objects
///
public partial class MultiTableBatchGet
{
#region Private members
private List allBatches = new List();
#endregion
#region Constructor
///
/// Constructs a MultiTableBatchGet object from a number of
/// BatchGet objects
///
/// Collection of BatchGet objects
public MultiTableBatchGet(params BatchGet[] batches)
{
allBatches = new List(batches);
}
internal MultiTableBatchGet(BatchGet first, params BatchGet[] rest)
{
allBatches = new List();
allBatches.Add(first);
allBatches.AddRange(rest);
}
#endregion
#region Public properties
///
/// Gets the total number of primary keys to be loaded from DynamoDB,
/// across all batches
///
public int TotalKeys
{
get
{
int count = 0;
foreach (var batch in allBatches)
{
count += batch.Keys.Count;
}
return count;
}
}
#endregion
#region Public methods
///
/// Add a BatchGet object to the multi-table batch request
///
/// BatchGet to add
public void AddBatch(BatchGet batch)
{
allBatches.Add(batch);
}
internal void ExecuteHelper()
{
MultiTableDocumentBatchGet superBatch = new MultiTableDocumentBatchGet();
foreach (var batch in allBatches)
{
batch.CreateDocumentBatch();
superBatch.AddBatch(batch.DocumentBatch);
}
superBatch.ExecuteHelper();
foreach (var batch in allBatches)
{
batch.PopulateResults(batch.DocumentBatch.Results);
}
}
#if AWS_ASYNC_API
internal async Task ExecuteHelperAsync(CancellationToken cancellationToken)
{
MultiTableDocumentBatchGet superBatch = new MultiTableDocumentBatchGet();
foreach (var batch in allBatches)
{
batch.CreateDocumentBatch();
superBatch.AddBatch(batch.DocumentBatch);
}
await superBatch.ExecuteHelperAsync(cancellationToken).ConfigureAwait(false);
foreach (var batch in allBatches)
{
batch.PopulateResults(batch.DocumentBatch.Results);
}
}
#endif
#endregion
}
}