Reputation: 13973
I'm trying to set an attribute in a DynamoDB document to an empty list via an update request, using the DynamoDBv2 library from the AWS SDK for .NET.
I've tried the obvious update expression, with no success:
// Fails, expression attribute values cannot contain an empty list
...
ExpressionAttributeValues = new Dictionary<string, AttributeValue> {
{ ":empty", new AttributeValue { L = new List<AttributeValue> { } } },
},
UpdateExpression = "SET #P.MyList = :empty",
...
How can I achieve this?
Upvotes: 5
Views: 9541
Reputation: 11
For those encountering this issue in the Java SDK, I found the solution. Java doesn't seem to have an IsLSet
analogy in its library. To specify an empty AttributeValue list for DynamoDB using Java, the following works:
AttributeValue.builder().l(new ArrayList<AttributeValue>()).build();
For Example,
String updateExpression = "SET my_list = :empty_list";
Map<String, AttributeValue> expressionAttributeValues = Map.of(
":empty_list", AttributeValue.builder().l(new ArrayList<AttributeValue>()).build()
);
Upvotes: 1
Reputation: 2259
Just ran across this problem myself. Looks like a bug that's been around since at least November 2018 ( https://github.com/aws/aws-sdk-net/issues/1116 ). My workaround was to manually set IsLSet = true
immediately after you set the value of L
.
For example, here is how you would create an empty list attribute:
ExpressionAttributeValues = new Dictionary<string, AttributeValue>
{
{ ":empty", new AttributeValue { L = new List<AttributeValue>(), IsLSet = true }},
},
UpdateExpression = "SET #P.MyList = :empty",
You should be able to use the above syntax regardless of whether or not your list is empty. For example:
ExpressionAttributeValues = new Dictionary<string, AttributeValue>
{
{ ":MyListOfValues", new AttributeValue { L = listValues, IsLSet = true }},
},
UpdateExpression = "SET #P.MyList = :MyListOfValues",
Upvotes: 4
Reputation: 176
I found the answer after digging through the AWS SDK source code. The key is that the IsLSet
property is settable. This calls the following code:
public static void SetIsSet<T>(bool isSet, ref List<T> field)
{
if (isSet)
field = new AlwaysSendList<T>(field);
else
field = new List<T>();
}
When determining if your AttributeValue is initialised, is uses the following code:
public static bool GetIsSet<T>(List<T> field)
{
if (field == null)
return false;
if (field.Count > 0)
return true;
var sl = field as AlwaysSendList<T>;
if (sl != null)
return true;
return false;
}
This also shows why using new AttributeValue { L = new List<AttributeValue> { } }
doesn't have the intended effect - this method will return false as the Count
is 0. However, the check for the special AlwaysSendList
type will return true if you've set the IsLSet
property.
Back to your code, the answer is to use the following:
...
ExpressionAttributeValues = new Dictionary<string, AttributeValue> {
{ ":empty", new AttributeValue { IsLSet = true } },
},
UpdateExpression = "SET #P.MyList = :empty",
...
Upvotes: 16