Skip to content

Commit 08689b6

Browse files
committed
CSHARP-3845: Deserialize Select of anonymous types using default values for missing fields.
1 parent b96a0ea commit 08689b6

File tree

3 files changed

+94
-1
lines changed

3 files changed

+94
-1
lines changed

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

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@ public static AggregationExpression Translate(TranslationContext context, NewExp
5050
var fieldExpression = expression.Arguments[i];
5151
var fieldTranslation = ExpressionToAggregationExpressionTranslator.Translate(context, fieldExpression);
5252
var memberSerializer = fieldTranslation.Serializer ?? BsonSerializer.LookupSerializer(fieldExpression.Type);
53-
classMap.MapProperty(member.Name).SetSerializer(memberSerializer);
53+
var defaultValue = GetDefaultValue(memberSerializer.ValueType);
54+
classMap.MapProperty(member.Name).SetSerializer(memberSerializer).SetDefaultValue(defaultValue);
5455
computedFields.Add(AstExpression.ComputedField(member.Name, fieldTranslation.Ast));
5556
}
5657

@@ -69,5 +70,17 @@ public static AggregationExpression Translate(TranslationContext context, NewExp
6970

7071
return new AggregationExpression(expression, ast, serializer);
7172
}
73+
74+
private static object GetDefaultValue(Type type)
75+
{
76+
if (type.IsValueType)
77+
{
78+
return Activator.CreateInstance(type);
79+
}
80+
else
81+
{
82+
return null;
83+
}
84+
}
7285
}
7386
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/* Copyright 2010-present MongoDB Inc.
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
using System.Linq;
17+
using FluentAssertions;
18+
using MongoDB.Bson.Serialization.Attributes;
19+
using Xunit;
20+
21+
namespace MongoDB.Driver.Tests.Linq.Linq3ImplementationTests.Jira
22+
{
23+
public class CSharp3845Tests : Linq3IntegrationTest
24+
{
25+
[Fact]
26+
public void Select_of_anonymous_class_with_missing_fields_should_work()
27+
{
28+
var collection = GetCollection<C>();
29+
CreateCollection(
30+
collection,
31+
new[]
32+
{
33+
new C { Id = 1, S = null, X = 0 },
34+
new C { Id = 2, S = "abc", X = 123 }
35+
});
36+
37+
var queryable = collection.AsQueryable()
38+
.Select(c => new { F = c.S, G = c.X });
39+
40+
var stages = Translate(collection, queryable);
41+
var expectedStages = new[]
42+
{
43+
"{ $project : { F : '$S', G : '$X', _id : 0 } }"
44+
};
45+
AssertStages(stages, expectedStages);
46+
47+
var results = queryable.ToList();
48+
results.Count.Should().Be(2);
49+
results[0].F.Should().Be(null);
50+
results[0].G.Should().Be(0);
51+
results[1].F.Should().Be("abc");
52+
results[1].G.Should().Be(123);
53+
}
54+
55+
private class C
56+
{
57+
public int Id { get; set; }
58+
[BsonIgnoreIfNull]
59+
public string S { get; set; }
60+
[BsonIgnoreIfDefault]
61+
public int X { get; set; }
62+
}
63+
}
64+
}

tests/MongoDB.Driver.Tests/Linq/Linq3ImplementationTests/Linq3IntegrationTest.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,22 @@ protected void AssertStages(IEnumerable<BsonDocument> stages, IEnumerable<string
2929
stages.Should().Equal(expectedStages.Select(json => BsonDocument.Parse(json)));
3030
}
3131

32+
protected void CreateCollection<TDocument>(IMongoCollection<TDocument> collection, IEnumerable<TDocument> documents = null)
33+
{
34+
var database = collection.Database;
35+
var collectionName = collection.CollectionNamespace.CollectionName;
36+
database.DropCollection(collectionName);
37+
38+
if (documents != null && documents.Any())
39+
{
40+
collection.InsertMany(documents);
41+
}
42+
else
43+
{
44+
database.CreateCollection(collectionName);
45+
}
46+
}
47+
3248
protected IMongoCollection<TDocument> GetCollection<TDocument>(string collectionName = null)
3349
{
3450
var databaseName = DriverTestConfiguration.DatabaseNamespace.DatabaseName;

0 commit comments

Comments
 (0)