Skip to content

Commit c039186

Browse files
committed
Create e5fd3631-e192-4dcb-931b-69d45722ae02.json
add change file Allow to set DynamoDBEntryConversion per table
1 parent db805ae commit c039186

File tree

6 files changed

+126
-8
lines changed

6 files changed

+126
-8
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"services": [
3+
{
4+
"serviceName": "DynamoDBv2",
5+
"type": "patch",
6+
"changeLogMessages": [
7+
"Allow to set DynamoDBEntryConversion per table."
8+
]
9+
}
10+
]
11+
}

sdk/src/Services/DynamoDBv2/Custom/Conversion/DynamoDBEntryConversion.cs

+7-1
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,17 @@
3030

3131
namespace Amazon.DynamoDBv2
3232
{
33+
3334
/// <summary>
3435
/// Available conversion schemas.
3536
/// </summary>
36-
internal enum ConversionSchema
37+
public enum ConversionSchema
3738
{
39+
/// <summary>
40+
/// No schema set.
41+
/// </summary>
42+
Unset = -1,
43+
3844
/// <summary>
3945
/// Default schema before 2014 L, M, BOOL, NULL support
4046
///

sdk/src/Services/DynamoDBv2/Custom/DataModel/Attributes.cs

+20-1
Original file line numberDiff line numberDiff line change
@@ -52,22 +52,41 @@ public sealed class DynamoDBTableAttribute : DynamoDBAttribute
5252
/// </summary>
5353
public bool LowerCamelCaseProperties { get; set; }
5454

55+
/// <summary>
56+
/// Gets and sets the Conversion Schema property.
57+
/// </summary>
58+
public ConversionSchema Conversion { get; }
59+
5560
/// <summary>
5661
/// Construct an instance of DynamoDBTableAttribute
5762
/// </summary>
5863
/// <param name="tableName"></param>
5964
public DynamoDBTableAttribute(string tableName)
60-
: this(tableName, false) { }
65+
: this(tableName, false, ConversionSchema.Unset)
66+
{
67+
}
6168

6269
/// <summary>
6370
/// Construct an instance of DynamoDBTableAttribute
6471
/// </summary>
6572
/// <param name="tableName"></param>
6673
/// <param name="lowerCamelCaseProperties"></param>
6774
public DynamoDBTableAttribute(string tableName, bool lowerCamelCaseProperties)
75+
: this(tableName, lowerCamelCaseProperties, ConversionSchema.Unset)
76+
{
77+
}
78+
79+
/// <summary>
80+
/// Construct an instance of DynamoDBTableAttribute
81+
/// </summary>
82+
/// <param name="tableName"></param>
83+
/// <param name="lowerCamelCaseProperties"></param>
84+
/// <param name="conversion"></param>
85+
public DynamoDBTableAttribute(string tableName, bool lowerCamelCaseProperties, ConversionSchema conversion)
6886
{
6987
TableName = tableName;
7088
LowerCamelCaseProperties = lowerCamelCaseProperties;
89+
Conversion = conversion;
7190
}
7291
}
7392

sdk/src/Services/DynamoDBv2/Custom/DataModel/Configs.cs

+27-6
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,7 @@ public DynamoDBFlatConfig(DynamoDBOperationConfig operationConfig, DynamoDBConte
432432
bool ignoreNullValues = operationConfig.IgnoreNullValues ?? contextConfig.IgnoreNullValues ?? false;
433433
bool retrieveDateTimeInUtc = operationConfig.RetrieveDateTimeInUtc ?? contextConfig.RetrieveDateTimeInUtc ?? true;
434434
bool isEmptyStringValueEnabled = operationConfig.IsEmptyStringValueEnabled ?? contextConfig.IsEmptyStringValueEnabled ?? false;
435-
DynamoDBEntryConversion conversion = operationConfig.Conversion ?? contextConfig.Conversion ?? DynamoDBEntryConversion.CurrentConversion;
435+
DynamoDBEntryConversion conversion = contextConfig.Conversion ?? DynamoDBEntryConversion.CurrentConversion;
436436
string tableNamePrefix = operationConfig.TableNamePrefix ?? contextConfig.TableNamePrefix ?? string.Empty;
437437

438438
// These properties can only be set at the operation level
@@ -463,15 +463,16 @@ public DynamoDBFlatConfig(DynamoDBOperationConfig operationConfig, DynamoDBConte
463463
IndexName = indexName;
464464
QueryFilter = queryFilter;
465465
ConditionalOperator = conditionalOperator;
466-
Conversion = conversion;
466+
ContextConversion = conversion;
467+
OperationConversion = operationConfig.Conversion;
467468
MetadataCachingMode = metadataCachingMode;
468469
DisableFetchingTableMetadata = disableFetchingTableMetadata;
469470
RetrieveDateTimeInUtc = retrieveDateTimeInUtc;
470471
DerivedTypeAttributeName = derivedTypeAttributeName;
471472

472473
State = new OperationState();
473474
}
474-
475+
475476
/// <summary>
476477
/// Property that directs DynamoDBContext to use consistent reads.
477478
/// If property is not set, behavior defaults to non-consistent reads.
@@ -552,10 +553,29 @@ public DynamoDBFlatConfig(DynamoDBOperationConfig operationConfig, DynamoDBConte
552553
public List<ScanCondition> QueryFilter { get; set; }
553554

554555
/// <summary>
555-
/// Conversion specification which controls how conversion between
556+
/// Entity Conversion specification which controls how conversion between
556557
/// .NET and DynamoDB types happens.
557558
/// </summary>
558-
public DynamoDBEntryConversion Conversion { get; set; }
559+
public DynamoDBEntryConversion ItemConversion { get; set; }
560+
561+
562+
/// <summary>
563+
/// Operation Conversion specification which controls how conversion between
564+
/// .NET and DynamoDB types happens.
565+
/// </summary>
566+
private DynamoDBEntryConversion OperationConversion { get; }
567+
568+
/// <summary>
569+
/// Context Conversion specification which controls how conversion between
570+
/// .NET and DynamoDB types happens.
571+
/// </summary>
572+
public DynamoDBEntryConversion Conversion => OperationConversion ?? ItemConversion ?? ContextConversion;
573+
574+
/// <summary>
575+
/// Context Conversion specification which controls how conversion between
576+
/// .NET and DynamoDB types happens.
577+
/// </summary>
578+
private DynamoDBEntryConversion ContextConversion { get; }
559579

560580
/// <inheritdoc cref="DynamoDBContextConfig.DisableFetchingTableMetadata"/>
561581
public bool DisableFetchingTableMetadata { get; set; }
@@ -564,7 +584,7 @@ public DynamoDBFlatConfig(DynamoDBOperationConfig operationConfig, DynamoDBConte
564584
public bool RetrieveDateTimeInUtc { get; set; }
565585

566586
// Checks if the IndexName is set on the config
567-
internal bool IsIndexOperation { get { return !string.IsNullOrEmpty(IndexName); } }
587+
internal bool IsIndexOperation => !string.IsNullOrEmpty(IndexName);
568588

569589
// State of the operation using this config
570590
internal OperationState State { get; private set; }
@@ -584,6 +604,7 @@ public DynamoDBFlatConfig(DynamoDBOperationConfig operationConfig, DynamoDBConte
584604
/// </remarks>
585605
public string DerivedTypeAttributeName { get; set; }
586606

607+
587608
public class OperationState
588609
{
589610
private CircularReferenceTracking referenceTracking;

sdk/src/Services/DynamoDBv2/Custom/DataModel/InternalModel.cs

+17
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,9 @@ internal class ItemStorageConfig
428428
// indexName to GSIConfig mapping
429429
public Dictionary<string, GSIConfig> IndexNameToGSIMapping { get; set; }
430430

431+
// entity conversion
432+
public DynamoDBEntryConversion Conversion { get; set; }
433+
431434

432435
public bool StorePolymorphicTypes => this.PolymorphicTypesStorageConfig.Any();
433436

@@ -735,6 +738,10 @@ public ItemStorageConfig GetConfig([DynamicallyAccessedMembers(InternalConstants
735738

736739
if (tableCache.Cache.TryGetValue(actualTableName, out config))
737740
{
741+
if (flatConfig == null)
742+
throw new ArgumentNullException("flatConfig");
743+
744+
flatConfig.ItemConversion = config.Conversion;
738745
return config;
739746
}
740747
}
@@ -759,6 +766,8 @@ public ItemStorageConfig GetConfig([DynamicallyAccessedMembers(InternalConstants
759766
if (tableCache == null)
760767
{
761768
var baseStorageConfig = CreateStorageConfig(type, actualTableName: null, flatConfig);
769+
flatConfig.ItemConversion = baseStorageConfig.Conversion;
770+
762771
tableCache = new ConfigTableCache(baseStorageConfig);
763772
Cache[type] = tableCache;
764773
}
@@ -780,6 +789,7 @@ public ItemStorageConfig GetConfig([DynamicallyAccessedMembers(InternalConstants
780789
}
781790

782791
config = CreateStorageConfig(type, actualTableName, flatConfig);
792+
flatConfig.ItemConversion = config.Conversion;
783793
tableCache.Cache[actualTableName] = config;
784794

785795
return config;
@@ -858,6 +868,13 @@ private static void PopulateConfigFromType(ItemStorageConfig config, [Dynamicall
858868
if (string.IsNullOrEmpty(tableAttribute.TableName)) throw new InvalidOperationException("DynamoDBTableAttribute.Table is empty or null");
859869
config.TableName = tableAttribute.TableName;
860870
config.LowerCamelCaseProperties = tableAttribute.LowerCamelCaseProperties;
871+
872+
config.Conversion = tableAttribute.Conversion switch
873+
{
874+
ConversionSchema.V1 => DynamoDBEntryConversion.V1,
875+
ConversionSchema.V2 => DynamoDBEntryConversion.V2,
876+
_ => config.Conversion
877+
};
861878
}
862879

863880
string tableAlias;

sdk/test/Services/DynamoDBv2/IntegrationTests/DataModelTests.cs

+44
Original file line numberDiff line numberDiff line change
@@ -1114,6 +1114,45 @@ private void TestContextConversions()
11141114
#pragma warning restore CS0618 // Re-enable the warning
11151115
}
11161116

1117+
{
1118+
1119+
#pragma warning disable CS0618 // Disable the warning for the deprecated DynamoDBContext constructors
1120+
ProductV2 productV2 = new ProductV2
1121+
{
1122+
Id = 1,
1123+
Name = "CloudSpotter",
1124+
CompanyName = "CloudsAreGrate",
1125+
Price = 1200,
1126+
TagSet = new HashSet<string> { "Prod", "1.0" },
1127+
CurrentStatus = Status.Active,
1128+
FormerStatus = Status.Upcoming,
1129+
Supports = Support.Unix | Support.Windows,
1130+
PreviousSupport = null,
1131+
InternalId = "T1000",
1132+
IsPublic = true,
1133+
AlwaysN = true,
1134+
Rating = 4,
1135+
Components = new List<string> { "Code", "Coffee" },
1136+
KeySizes = new List<byte> { 16, 64, 128 },
1137+
CompanyInfo = new CompanyInfo
1138+
{
1139+
Name = "MyCloud",
1140+
Founded = new DateTime(1994, 7, 6),
1141+
Revenue = 9001
1142+
}
1143+
};
1144+
1145+
using (var contextV1 = new DynamoDBContext(Client, new DynamoDBContextConfig { Conversion = conversionV1 }))
1146+
{
1147+
var docV1 = contextV1.ToDocument(productV2, new ToDocumentConfig { Conversion = conversionV1 });
1148+
var docV2 = contextV1.ToDocument(productV2, new ToDocumentConfig { });
1149+
VerifyConversions(docV1, docV2);
1150+
}
1151+
1152+
#pragma warning restore CS0618 // Re-enable the warning
1153+
1154+
}
1155+
11171156
// Introduce a circular reference and try to serialize
11181157
{
11191158
product.CompanyInfo = new CompanyInfo
@@ -2632,6 +2671,11 @@ public object FromEntry(DynamoDBEntry entry)
26322671
}
26332672
}
26342673

2674+
[DynamoDBTable("HashTable", false, ConversionSchema.V2)]
2675+
public class ProductV2 : Product
2676+
{
2677+
}
2678+
26352679
/// <summary>
26362680
/// Class representing items in the table [TableNamePrefix]HashTable
26372681
/// </summary>

0 commit comments

Comments
 (0)