Skip to content

Create separate operation-specific configs for the Delete, Load, and Save Operations #3387

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
137 changes: 59 additions & 78 deletions sdk/src/Services/DynamoDBv2/Custom/DataModel/Context.cs
Original file line number Diff line number Diff line change
Expand Up @@ -475,11 +475,10 @@ public MultiTableTransactWrite CreateMultiTableTransactWrite(params TransactWrit

#region Save/serialize

private void SaveHelper<T>(T value, DynamoDBOperationConfig operationConfig)
private void SaveHelper<T>(T value, DynamoDBFlatConfig flatConfig)
{
if (value == null) return;

DynamoDBFlatConfig flatConfig = new DynamoDBFlatConfig(operationConfig, this.Config);
ItemStorage storage = ObjectToItemStorage(value, false, flatConfig);
if (storage == null) return;

Expand All @@ -503,16 +502,15 @@ private void SaveHelper<T>(T value, DynamoDBOperationConfig operationConfig)
}

#if AWS_ASYNC_API
private async Task SaveHelperAsync<T>(T value, DynamoDBOperationConfig operationConfig, CancellationToken cancellationToken)
private async Task SaveHelperAsync<T>(T value, DynamoDBFlatConfig flatConfig, CancellationToken cancellationToken)
{
await SaveHelperAsync(typeof(T), value, operationConfig, cancellationToken).ConfigureAwait(false);
await SaveHelperAsync(typeof(T), value, flatConfig, cancellationToken).ConfigureAwait(false);
}

private async Task SaveHelperAsync(Type valueType, object value, DynamoDBOperationConfig operationConfig, CancellationToken cancellationToken)
private async Task SaveHelperAsync(Type valueType, object value, DynamoDBFlatConfig flatConfig, CancellationToken cancellationToken)
{
if (value == null) return;

DynamoDBFlatConfig flatConfig = new DynamoDBFlatConfig(operationConfig, this.Config);
ItemStorage storage = ObjectToItemStorage(value, valueType, false, flatConfig);
if (storage == null) return;

Expand All @@ -537,24 +535,14 @@ await table.UpdateHelperAsync(
}
#endif

/// <summary>
/// Serializes an object to a Document.
/// </summary>
/// <typeparam name="T">Type to serialize as.</typeparam>
/// <param name="value">Object to serialize.</param>
/// <returns>Document with attributes populated from object.</returns>
/// <inheritdoc/>
public Document ToDocument<T>(T value)
{
return ToDocument<T>(value, null);
return ToDocument<T>(value, (ToDocumentConfig)null);
}

/// <summary>
/// Serializes an object to a Document.
/// </summary>
/// <typeparam name="T">Type to serialize as.</typeparam>
/// <param name="value">Object to serialize.</param>
/// <param name="operationConfig">Config object which can be used to override the table used.</param>
/// <returns>Document with attributes populated from object.</returns>
/// <inheritdoc/>
[Obsolete("Use the ToDocument overload that takes ToDocumentConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to ToDocument.")]
public Document ToDocument<T>(T value, DynamoDBOperationConfig operationConfig)
{
if (value == null) return null;
Expand All @@ -566,40 +554,48 @@ public Document ToDocument<T>(T value, DynamoDBOperationConfig operationConfig)
return storage.Document;
}

/// <inheritdoc/>
public Document ToDocument<T>(T value, ToDocumentConfig toDocumentConfig)
{
if (value == null) return null;

DynamoDBFlatConfig flatConfig = new DynamoDBFlatConfig(toDocumentConfig?.ToDynamoDBOperationConfig(), Config);
ItemStorage storage = ObjectToItemStorage<T>(value, false, flatConfig);
if (storage == null) return null;

return storage.Document;
}

#endregion

#region Load/deserialize

private T LoadHelper<T>(object hashKey, object rangeKey, DynamoDBOperationConfig operationConfig)
private T LoadHelper<T>(object hashKey, object rangeKey, DynamoDBFlatConfig flatConfig)
{
DynamoDBFlatConfig flatConfig = new DynamoDBFlatConfig(operationConfig, this.Config);
ItemStorageConfig storageConfig = StorageConfigCache.GetConfig<T>(flatConfig);
Key key = MakeKey(hashKey, rangeKey, storageConfig, flatConfig);
return LoadHelper<T>(key, flatConfig, storageConfig);
}

#if AWS_ASYNC_API
private Task<T> LoadHelperAsync<T>(object hashKey, object rangeKey, DynamoDBOperationConfig operationConfig, CancellationToken cancellationToken)
private Task<T> LoadHelperAsync<T>(object hashKey, object rangeKey, DynamoDBFlatConfig flatConfig, CancellationToken cancellationToken)
{
DynamoDBFlatConfig flatConfig = new DynamoDBFlatConfig(operationConfig, this.Config);
ItemStorageConfig storageConfig = StorageConfigCache.GetConfig<T>(flatConfig);
Key key = MakeKey(hashKey, rangeKey, storageConfig, flatConfig);
return LoadHelperAsync<T>(key, flatConfig, storageConfig, cancellationToken);
}
#endif

private T LoadHelper<T>(T keyObject, DynamoDBOperationConfig operationConfig)
private T LoadHelper<T>(T keyObject, DynamoDBFlatConfig flatConfig)
{
DynamoDBFlatConfig flatConfig = new DynamoDBFlatConfig(operationConfig, this.Config);
ItemStorageConfig storageConfig = StorageConfigCache.GetConfig<T>(flatConfig);
Key key = MakeKey<T>(keyObject, storageConfig, flatConfig);
return LoadHelper<T>(key, flatConfig, storageConfig);
}

#if AWS_ASYNC_API
private Task<T> LoadHelperAsync<T>(T keyObject, DynamoDBOperationConfig operationConfig, CancellationToken cancellationToken)
private Task<T> LoadHelperAsync<T>(T keyObject, DynamoDBFlatConfig flatConfig, CancellationToken cancellationToken)
{
DynamoDBFlatConfig flatConfig = new DynamoDBFlatConfig(operationConfig, this.Config);
ItemStorageConfig storageConfig = StorageConfigCache.GetConfig<T>(flatConfig);
Key key = MakeKey<T>(keyObject, storageConfig, flatConfig);
return LoadHelperAsync<T>(key, flatConfig, storageConfig, cancellationToken);
Expand Down Expand Up @@ -640,34 +636,27 @@ private async Task<T> LoadHelperAsync<T>(Key key, DynamoDBFlatConfig flatConfig,
}
#endif

/// <summary>
/// Deserializes a document to an instance of type T.
/// </summary>
/// <typeparam name="T">Type to populate.</typeparam>
/// <param name="document">Document with properties to use.</param>
/// <returns>
/// Object of type T, populated with properties from the document.
/// </returns>
/// <inheritdoc/>
public T FromDocument<T>(Document document)
{
return FromDocument<T>(document, null);
return FromDocument<T>(document, (FromDocumentConfig)null);
}

/// <summary>
/// Deserializes a document to an instance of type T.
/// </summary>
/// <typeparam name="T">Type to populate.</typeparam>
/// <param name="document">Document with properties to use.</param>
/// <param name="operationConfig">Config object which can be used to override the table used.</param>
/// <returns>
/// Object of type T, populated with properties from the document.
/// </returns>
/// <inheritdoc/>
[Obsolete("Use the FromDocument overload that takes FromDocumentConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to FromDocument.")]
public T FromDocument<T>(Document document, DynamoDBOperationConfig operationConfig)
{
DynamoDBFlatConfig flatConfig = new DynamoDBFlatConfig(operationConfig, Config);
return FromDocumentHelper<T>(document, flatConfig);
}

/// <inheritdoc/>
public T FromDocument<T>(Document document, FromDocumentConfig fromDocumentConfig)
{
DynamoDBFlatConfig flatConfig = new DynamoDBFlatConfig(fromDocumentConfig?.ToDynamoDBOperationConfig(), Config);
return FromDocumentHelper<T>(document, flatConfig);
}

internal T FromDocumentHelper<T>(Document document, DynamoDBFlatConfig flatConfig)
{
ItemStorageConfig storageConfig = StorageConfigCache.GetConfig<T>(flatConfig);
Expand All @@ -677,28 +666,14 @@ internal T FromDocumentHelper<T>(Document document, DynamoDBFlatConfig flatConfi
return instance;
}

/// <summary>
/// Deserializes a collections of documents to a collection of instances of type T.
/// </summary>
/// <typeparam name="T">Type to populate.</typeparam>
/// <param name="documents">Documents to deserialize.</param>
/// <returns>
/// Collection of items of type T, each populated with properties from a corresponding document.
/// </returns>
/// <inheritdoc/>
public IEnumerable<T> FromDocuments<T>(IEnumerable<Document> documents)
{
return FromDocuments<T>(documents, null);
return FromDocuments<T>(documents, (FromDocumentConfig)null);
}

/// <summary>
/// Deserializes a collections of documents to a collection of instances of type T.
/// </summary>
/// <typeparam name="T">Type to populate.</typeparam>
/// <param name="documents">Documents to deserialize.</param>
/// <param name="operationConfig">Config object which can be used to override the table used.</param>
/// <returns>
/// Collection of items of type T, each populated with properties from a corresponding document.
/// </returns>
/// <inheritdoc/>
[Obsolete("Use the FromDocuments overload that takes FromDocumentConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to FromDocuments.")]
public IEnumerable<T> FromDocuments<T>(IEnumerable<Document> documents, DynamoDBOperationConfig operationConfig)
{
foreach (var document in documents)
Expand All @@ -708,6 +683,16 @@ public IEnumerable<T> FromDocuments<T>(IEnumerable<Document> documents, DynamoDB
}
}

/// <inheritdoc/>
public IEnumerable<T> FromDocuments<T>(IEnumerable<Document> documents, FromDocumentConfig fromDocumentConfig)
{
foreach (var document in documents)
{
T item = FromDocument<T>(document, fromDocumentConfig);
yield return item;
}
}

internal IEnumerable<T> FromDocumentsHelper<T>(IEnumerable<Document> documents, DynamoDBFlatConfig flatConfig)
{
foreach (var document in documents)
Expand All @@ -721,33 +706,30 @@ internal IEnumerable<T> FromDocumentsHelper<T>(IEnumerable<Document> documents,

#region Delete

private void DeleteHelper<T>(object hashKey, object rangeKey, DynamoDBOperationConfig operationConfig)
private void DeleteHelper<T>(object hashKey, object rangeKey, DynamoDBFlatConfig flatConfig)
{
DynamoDBFlatConfig config = new DynamoDBFlatConfig(operationConfig, this.Config);
ItemStorageConfig storageConfig = StorageConfigCache.GetConfig<T>(config);
Key key = MakeKey(hashKey, rangeKey, storageConfig, config);
ItemStorageConfig storageConfig = StorageConfigCache.GetConfig<T>(flatConfig);
Key key = MakeKey(hashKey, rangeKey, storageConfig, flatConfig);

Table table = GetTargetTable(storageConfig, config);
Table table = GetTargetTable(storageConfig, flatConfig);
table.DeleteHelper(key, null);
}

#if AWS_ASYNC_API
private Task DeleteHelperAsync<T>(object hashKey, object rangeKey, DynamoDBOperationConfig operationConfig, CancellationToken cancellationToken)
private Task DeleteHelperAsync<T>(object hashKey, object rangeKey, DynamoDBFlatConfig flatConfig, CancellationToken cancellationToken)
{
DynamoDBFlatConfig config = new DynamoDBFlatConfig(operationConfig, this.Config);
ItemStorageConfig storageConfig = StorageConfigCache.GetConfig<T>(config);
Key key = MakeKey(hashKey, rangeKey, storageConfig, config);
ItemStorageConfig storageConfig = StorageConfigCache.GetConfig<T>(flatConfig);
Key key = MakeKey(hashKey, rangeKey, storageConfig, flatConfig);

Table table = GetTargetTable(storageConfig, config);
Table table = GetTargetTable(storageConfig, flatConfig);
return table.DeleteHelperAsync(key, null, cancellationToken);
}
#endif

private void DeleteHelper<T>(T value, DynamoDBOperationConfig operationConfig)
private void DeleteHelper<T>(T value, DynamoDBFlatConfig flatConfig)
{
if (value == null) throw new ArgumentNullException("value");

DynamoDBFlatConfig flatConfig = new DynamoDBFlatConfig(operationConfig, this.Config);
flatConfig.IgnoreNullValues = true;
ItemStorage storage = ObjectToItemStorage<T>(value, true, flatConfig);
if (storage == null) return;
Expand All @@ -770,11 +752,10 @@ private void DeleteHelper<T>(T value, DynamoDBOperationConfig operationConfig)

private static readonly Task CompletedTask = Task.FromResult<object>(null);

private Task DeleteHelperAsync<T>(T value, DynamoDBOperationConfig operationConfig, CancellationToken cancellationToken)
private Task DeleteHelperAsync<T>(T value, DynamoDBFlatConfig flatConfig, CancellationToken cancellationToken)
{
if (value == null) throw new ArgumentNullException("value");

DynamoDBFlatConfig flatConfig = new DynamoDBFlatConfig(operationConfig, this.Config);
flatConfig.IgnoreNullValues = true;
ItemStorage storage = ObjectToItemStorage(value, true, flatConfig);
if (storage == null) return CompletedTask;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,9 @@ internal static Expression CreateConditionExpressionForVersion(ItemStorage stora
#region Table methods

// Retrieves the target table for the specified type
private Table GetTargetTableInternal<T>(DynamoDBOperationConfig operationConfig)
private Table GetTargetTableInternal<T>(DynamoDBFlatConfig flatConfig)
{
Type type = typeof(T);
DynamoDBFlatConfig flatConfig = new DynamoDBFlatConfig(operationConfig, this.Config);
ItemStorageConfig storageConfig = StorageConfigCache.GetConfig(type, flatConfig);
Table table = GetTargetTable(storageConfig, flatConfig, Table.DynamoDBConsumer.DocumentModel);
return table;
Expand Down
43 changes: 43 additions & 0 deletions sdk/src/Services/DynamoDBv2/Custom/DataModel/DeleteConfig.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* 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.
*/

namespace Amazon.DynamoDBv2.DataModel
{
/// <summary>
/// Input for the Delete operation in the object-persistence programming model
/// </summary>
#if NET8_0_OR_GREATER
// The DataModel namespace doesn't support trimming yet, so annotate public classes/methods as incompatible
[System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode(Custom.Internal.InternalConstants.RequiresUnreferencedCodeMessage)]
#endif
public class DeleteConfig : BaseOperationConfig
{
/// <summary>
/// Property that directs <see cref="DynamoDBContext"/> to skip version checks
/// when saving or deleting an object with a version attribute.
/// If property is not set, version checks are performed.
/// </summary>
public bool? SkipVersionCheck { get; set; }

/// <inheritdoc/>
internal override DynamoDBOperationConfig ToDynamoDBOperationConfig()
{
var config = base.ToDynamoDBOperationConfig();
config.SkipVersionCheck = SkipVersionCheck;

return config;
}
}
}
47 changes: 47 additions & 0 deletions sdk/src/Services/DynamoDBv2/Custom/DataModel/FromDocumentConfig.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* 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;

namespace Amazon.DynamoDBv2.DataModel
{
/// <summary>
/// Input for the FromDocument operation in the object-persistence programming model
/// </summary>
#if NET8_0_OR_GREATER
// The DataModel namespace doesn't support trimming yet, so annotate public classes/methods as incompatible
[System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode(Custom.Internal.InternalConstants.RequiresUnreferencedCodeMessage)]
#endif
public class FromDocumentConfig : BaseOperationConfig
{
/// <summary>
/// If true, all <see cref="DateTime"/> properties are retrieved in UTC timezone while reading data from DynamoDB. Else, the local timezone is used.
/// </summary>
/// <remarks>
/// This setting is only applicable to the high-level library. Service calls made via
/// <see cref="AmazonDynamoDBClient"/> will always return <see cref="DateTime"/> attributes in UTC.
/// </remarks>
public bool? RetrieveDateTimeInUtc { get; set; }

/// <inheritdoc/>
internal override DynamoDBOperationConfig ToDynamoDBOperationConfig()
{
var config = base.ToDynamoDBOperationConfig();
config.RetrieveDateTimeInUtc = RetrieveDateTimeInUtc;

return config;
}
}
}
Loading