Replace AttributesToGet usage with ProjectionExpression for batch get requests#4392
Replace AttributesToGet usage with ProjectionExpression for batch get requests#4392irina-herciu wants to merge 4 commits intoaws:developmentfrom
Conversation
|
Is this the same as #4343? (And if yes, should that PR be closed?) |
|
this PR targets BatchGet operations, and #4343 is for load item operation. there is indeed code duplication as I needed to build and pass ProjectionExpression from ItemStorageConfig |
| { | ||
| var projectionExpressionBuilder = new StringBuilder(); | ||
| var expressionAttributeName = "#P" + ProjectionExpression.ExpressionAttributeNames.Count.ToString(CultureInfo.InvariantCulture); | ||
| if (projectionExpressionBuilder.Length == 0 && !string.IsNullOrEmpty(ProjectionExpression.ExpressionStatement)) |
There was a problem hiding this comment.
Redundant projectionExpressionBuilder.Length == 0 check (InternalModel.cs:688) — the StringBuilder is freshly created on line 685, so this is always true.
There was a problem hiding this comment.
derivedTypeAttributeName (the $type attribute used to identify which polymorphic subclass an item belongs to) is added to AttributesToGet here but not to ProjectionExpression. Since BatchGet.CreateDocumentBatch() now uses ProjectionExpression instead of AttributesToGet, and DynamoDB only returns attributes listed in the projection, the $type attribute won't come back in the response. Without it, the SDK can't tell which subclass to deserialize into and silently falls back to the base class — losing any subclass-specific properties.Fix: add AddAttributeNameToProjectionExpression(derivedTypeAttributeName); after this line. Verified with a unit test that fails on current code and passes after the fix:
[TestMethod]
public void Denormalize_DerivedTypeAttribute_MustBeInProjectionExpression()
{
var mockClient = new Mock();
var context = new DummyContext(mockClient.Object);
var config = CreatePopulatedConfig(mockClient);
var polyStorage = new StorageConfig(typeof(DerivedType));
var extraProp = new PropertyStorage(typeof(DerivedType).GetProperty(nameof(DerivedType.Extra)))
{ AttributeName = "Extra" };
extraProp.IndexNames ??= new List<string>();
extraProp.FlattenProperties ??= new List<PropertyStorage>();
polyStorage.Properties.Add(extraProp);
config.AddPolymorphicPropertyStorageConfiguration("DT1", typeof(DerivedType), polyStorage);
var polyPropOnBase = new PropertyStorage(typeof(TestClass).GetProperty(nameof(TestClass.Poly)))
{ AttributeName = "Poly", PolymorphicProperty = true };
polyPropOnBase.IndexNames ??= new List<string>();
polyPropOnBase.FlattenProperties ??= new List<PropertyStorage>();
config.BaseTypeStorageConfig.Properties.Add(polyPropOnBase);
config.Denormalize(context, derivedTypeAttributeName: "dtype");
Assert.IsTrue(config.AttributesToGet.Contains("dtype"));
Assert.IsTrue(
config.ProjectionExpression.ExpressionAttributeNames.ContainsValue("dtype"),
"ProjectionExpression must include the derived type attribute so polymorphic batch gets return the $type column");
}
There was a problem hiding this comment.
fixed the Denormalize, by adding missing projection attribute name. Also added integration test for BatchGet WithDerivedTypeItems as it was missing from DataModelNestedTableTests.
Replace
AttributesToGetusage withProjectionExpressionfor batch get requests created from the DynamoDB data model layer, and add tests aroundDocumentBatchGetbehavior.Description
ProjectionExpressionfromItemStorageConfigintoDocumentBatchGetProjectionExpressionorAttributesToGet, and throws if both are set,DocumentBatchGet.Motivation and Context
Replace legacy params usage in HLL
Testing
Unit tests added, all existing integration tests passing
Dry-runs
Breaking Changes Assessment
Screenshots (if appropriate)
Types of changes
Checklist
License