Skip to content

Instantly share code, notes, and snippets.

@therightstuff
Created March 24, 2022 22:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save therightstuff/7e9103d3aaa78d2ca176e72eb12e5b1a to your computer and use it in GitHub Desktop.
Save therightstuff/7e9103d3aaa78d2ca176e72eb12e5b1a to your computer and use it in GitHub Desktop.
Storing and Retrieving Unstructured DynamoDB objects in C# with the AWS SDK
/// <summary>
/// The object mapping used to store structured test data
/// </summary>
private class StructuredDynamoDbTestObject
{
/// <summary>
/// The data key.
/// </summary>
[DynamoDBHashKey("structured_key")]
public string StructuredKey { get; set; }
}
/// <summary>
/// Test that uploaded structured data can be downloaded
/// Designed for testing against localstack, see https://github.com/localstack/localstack
/// </summary>
[TestMethod]
public void StructuredDataUploadAndDownload()
{
// assumes table has been created
const string tableName = "structured-data-upload-download-test";
// the partition key name
const string keyName = "structured_key";
// assumes AwsDynamoDbClient has been configured and is pointing to localstack
var dynamoDbContext = new DynamoDBContext(
AwsDynamoDbClient,
new DynamoDBContextConfig
{
ConsistentRead = true
});
var dynamoDbOperationConfig = new DynamoDBOperationConfig
{
OverrideTableName = tableName, BackwardQuery = false
};
var expectedTicks = $"{DateTime.UtcNow.Ticks}";
var testObject = new StructuredDynamoDbTestObject
{
StructuredKey = expectedTicks
};
dynamoDbContext
.SaveAsync(testObject, dynamoDbOperationConfig)
.Wait();
var ticks = dynamoDbContext
.LoadAsync(testObject, dynamoDbOperationConfig)
.Result;
Assert.AreEqual(expectedTicks, ticks.StructuredKey);
}
/// <summary>
/// Test that unstructured data can be uploaded and downloaded
/// Designed for testing against localstack, see https://github.com/localstack/localstack
/// </summary>
[TestMethod]
public void UnstructuredDataUploadAndDownload()
{
// assumes table has been created
const string tableName = "unstructured-data-upload-download-test";
// the partition key name
const string keyName = "unstructured_key";
const string testKeyValue = "test_key_value";
const string stringValueKey = "stringValue";
const string stringListKey = "stringList";
const string stringSetKey = "stringSet";
const string numberMapKey = "numberMap";
const string multilevelMapKey = "multilevelMap";
const string innerKey = "innerKey";
const string initialStringValue = "initial value";
const string updatedStringValue = "updated value";
const string oneString = "one";
const string twoString = "two";
const string threeString = "three";
const string oneNumeric = "1";
const string twoNumeric = "2";
var putItemRequest = new PutItemRequest
{
TableName = tableName,
Item = new Dictionary<string, AttributeValue>
{
{
keyName, new AttributeValue(testKeyValue)
},
{
stringValueKey, new AttributeValue
{
S = initialStringValue
}
},
{
stringListKey, new AttributeValue
{
L = new List<AttributeValue>
{
new AttributeValue
{
S = oneString
},
new AttributeValue
{
S = twoString
}
}
}
},
{
stringSetKey, new AttributeValue
{
SS = new List<string>
{
oneString, twoString
}
}
},
{
numberMapKey, new AttributeValue
{
M = new Dictionary<string, AttributeValue>
{
{
oneString, new AttributeValue
{
N = oneNumeric
}
},
{
twoString, new AttributeValue
{
N = twoNumeric
}
}
}
}
},
{
multilevelMapKey, new AttributeValue
{
M = new Dictionary<string, AttributeValue>
{
{
oneString, new AttributeValue
{
N = oneNumeric
}
},
{
twoString, new AttributeValue
{
M = new Dictionary<string, AttributeValue>
{
{
innerKey, new AttributeValue
{
BOOL = true
}
}
}
}
}
}
}
}
}
};
// assumes AwsDynamoDbClient has been configured and is pointing to localstack
AwsDynamoDbClient
.PutItemAsync(putItemRequest)
.Wait();
var initialUploadedItem = AwsDynamoDbClient
.GetItemAsync(
new GetItemRequest
{
TableName = tableName,
Key = new Dictionary<string, AttributeValue>
{
{
keyName, new AttributeValue
{
S = testKeyValue
}
}
}
})
.Result
.Item;
Assert.AreEqual(testKeyValue, initialUploadedItem[keyName].S);
Assert.AreEqual(initialStringValue, initialUploadedItem[stringValueKey].S);
Assert.AreEqual(2, initialUploadedItem[stringListKey].L.Count);
Assert.AreEqual(oneString, initialUploadedItem[stringListKey].L[0].S);
Assert.AreEqual(twoString, initialUploadedItem[stringListKey].L[1].S);
Assert.AreEqual(2, initialUploadedItem[stringSetKey].SS.Count);
Assert.IsTrue(initialUploadedItem[stringSetKey].SS.IndexOf(twoString) > -1);
Assert.IsTrue(initialUploadedItem[stringSetKey].SS.IndexOf(threeString) == -1);
Assert.AreEqual(oneNumeric, initialUploadedItem[numberMapKey].M[oneString].N);
Assert.AreEqual(true, initialUploadedItem[multilevelMapKey].M[twoString].M[innerKey].BOOL);
// modify simple and complex values and re-upload
initialUploadedItem[stringValueKey] = new AttributeValue
{
S = updatedStringValue
};
initialUploadedItem[stringListKey] = new AttributeValue
{
L = new List<AttributeValue>
{
new AttributeValue
{
S = oneString
},
new AttributeValue
{
S = twoString
},
new AttributeValue
{
S = threeString
}
}
};
initialUploadedItem[stringSetKey] = new AttributeValue
{
SS = new List<string>
{
oneString, twoString, threeString
}
};
AwsDynamoDbClient
.PutItemAsync(
new PutItemRequest
{
TableName = tableName, Item = initialUploadedItem
})
.Wait();
// verify that the updated object was stored as expected
var updatedUploadedItem = AwsDynamoDbClient
.GetItemAsync(
new GetItemRequest
{
TableName = tableName,
Key = new Dictionary<string, AttributeValue>
{
{
keyName, new AttributeValue
{
S = testKeyValue
}
}
}
})
.Result
.Item;
Assert.AreEqual(testKeyValue, updatedUploadedItem[keyName].S);
Assert.AreEqual(updatedStringValue, updatedUploadedItem[stringValueKey].S);
Assert.AreEqual(3, updatedUploadedItem[stringListKey].L.Count);
Assert.AreEqual(twoString, updatedUploadedItem[stringListKey].L[1].S);
Assert.AreEqual(threeString, updatedUploadedItem[stringListKey].L[2].S);
Assert.AreEqual(3, updatedUploadedItem[stringSetKey].SS.Count);
Assert.IsTrue(updatedUploadedItem[stringSetKey].SS.IndexOf(twoString) > -1);
Assert.IsTrue(updatedUploadedItem[stringSetKey].SS.IndexOf(threeString) > -1);
Assert.AreEqual(oneNumeric, updatedUploadedItem[numberMapKey].M[oneString].N);
Assert.AreEqual(true, updatedUploadedItem[multilevelMapKey].M[twoString].M[innerKey].BOOL);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment