Skip to content

Commit dd50568

Browse files
author
Oleksandr Poliakov
committed
CSHARP-5588: Unable to select KeyValuePair Key when using camelCase convention
1 parent e33629a commit dd50568

File tree

2 files changed

+44
-11
lines changed

2 files changed

+44
-11
lines changed

src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/NewKeyValuePairExpressionToAggregationExpressionTranslator.cs

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,24 +43,32 @@ public static TranslatedExpression Translate(
4343
var keyTranslation = ExpressionToAggregationExpressionTranslator.Translate(context, keyExpression);
4444
var valueTranslation = ExpressionToAggregationExpressionTranslator.Translate(context, valueExpression);
4545

46+
var serializer = CreateResultSerializer(expression.Type, keyTranslation.Serializer, valueTranslation.Serializer, out var keyElementName, out var valueElementName);
4647
var ast = AstExpression.ComputedDocument([
47-
AstExpression.ComputedField("Key", keyTranslation.Ast),
48-
AstExpression.ComputedField("Value", valueTranslation.Ast)
48+
AstExpression.ComputedField(keyElementName, keyTranslation.Ast),
49+
AstExpression.ComputedField(valueElementName, valueTranslation.Ast)
4950
]);
5051

51-
var serializer = CreateResultSerializer(expression.Type, keyTranslation.Serializer, valueTranslation.Serializer);
52-
5352
return new TranslatedExpression(expression, ast, serializer);
5453
}
5554

56-
private static IBsonSerializer CreateResultSerializer(Type resultType, IBsonSerializer keySerializer, IBsonSerializer valueSerializer)
55+
private static IBsonSerializer CreateResultSerializer(
56+
Type resultType,
57+
IBsonSerializer keySerializer,
58+
IBsonSerializer valueSerializer,
59+
out string keyElementName,
60+
out string valueElementName)
5761
{
5862
var constructorInfo = resultType.GetConstructor([keySerializer.ValueType, valueSerializer.ValueType]);
5963
var classMap = new BsonClassMap(resultType);
6064
classMap.MapConstructor(constructorInfo);
6165
classMap.AutoMap();
62-
classMap.GetMemberMap("Key").SetSerializer(keySerializer);
63-
classMap.GetMemberMap("Value").SetSerializer(valueSerializer);
66+
var keyMemberMap = classMap.GetMemberMap("Key");
67+
keyElementName = keyMemberMap.ElementName;
68+
keyMemberMap.SetSerializer(keySerializer);
69+
var valueMemberMap = classMap.GetMemberMap("Value");
70+
valueElementName = valueMemberMap.ElementName;
71+
valueMemberMap.SetSerializer(valueSerializer);
6472
classMap.Freeze();
6573

6674
// have to use BsonClassMapSerializer here to mimic the MemberInitExpressionToAggregationExpressionTranslator to avoid risking a behavioral breaking change

tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/NewKeyValuePairExpressionToAggregationExpressionTranslatorTests.cs

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,27 @@
1616
using System.Collections.Generic;
1717
using System.Linq;
1818
using FluentAssertions;
19+
using MongoDB.Bson.Serialization.Conventions;
1920
using MongoDB.Driver.TestHelpers;
2021
using Xunit;
2122

2223
namespace MongoDB.Driver.Tests.Linq.Linq3Implementation.Translators.ExpressionToAggregationExpressionTranslators;
2324

24-
#if NET6_0_OR_GREATER || NETCOREAPP3_1_OR_GREATER
2525
public class NewKeyValuePairExpressionToAggregationExpressionTranslatorTests : LinqIntegrationTest<NewKeyValuePairExpressionToAggregationExpressionTranslatorTests.ClassFixture>
2626
{
27+
private readonly bool _useCamelCase = false;
28+
2729
public NewKeyValuePairExpressionToAggregationExpressionTranslatorTests(ClassFixture fixture)
2830
: base(fixture)
2931
{
32+
// TODO: uncomment the code to demonstrate the fix, revert changes in the test class before merging into the main
33+
// _useCamelCase = true;
34+
35+
if (_useCamelCase)
36+
{
37+
var defaultPack = new ConventionPack { new CamelCaseElementNameConvention() };
38+
ConventionRegistry.Register("camelCase", defaultPack, c => true);
39+
}
3040
}
3141

3242
[Fact]
@@ -38,13 +48,21 @@ public void NewKeyValuePair_should_translate()
3848
.Select(d => new KeyValuePair<string,int>("X", d.X));
3949

4050
var stages = Translate(collection, queryable);
41-
AssertStages(stages, "{ $project : { Key : 'X', Value : '$X', _id : 0 } }");
51+
if (_useCamelCase)
52+
{
53+
AssertStages(stages, "{ $project : { key : 'X', value : '$X', _id : 0 } }");
54+
}
55+
else
56+
{
57+
AssertStages(stages, "{ $project : { Key : 'X', Value : '$X', _id : 0 } }");
58+
}
4259

4360
var result = queryable.Single();
4461
result.Key.Should().Be("X");
4562
result.Value.Should().Be(42);
4663
}
4764

65+
#if NET6_0_OR_GREATER || NETCOREAPP3_1_OR_GREATER
4866
[Fact]
4967
public void KeyValuePair_Create_should_translate()
5068
{
@@ -54,12 +72,20 @@ public void KeyValuePair_Create_should_translate()
5472
.Select(d => KeyValuePair.Create("X", d.X));
5573

5674
var stages = Translate(collection, queryable);
57-
AssertStages(stages, "{ $project : { Key : 'X', Value : '$X', _id : 0 } }");
75+
if (_useCamelCase)
76+
{
77+
AssertStages(stages, "{ $project : { key : 'X', value : '$X', _id : 0 } }");
78+
}
79+
else
80+
{
81+
AssertStages(stages, "{ $project : { Key : 'X', Value : '$X', _id : 0 } }");
82+
}
5883

5984
var result = queryable.Single();
6085
result.Key.Should().Be("X");
6186
result.Value.Should().Be(42);
6287
}
88+
#endif
6389

6490
public class C
6591
{
@@ -75,4 +101,3 @@ public sealed class ClassFixture : MongoCollectionFixture<C>
75101
}
76102
}
77103

78-
#endif

0 commit comments

Comments
 (0)