[CSHARP-1359] Runtime exception using Project with Aggregate Created: 07/Aug/15  Updated: 09/Aug/15  Resolved: 08/Aug/15

Status: Closed
Project: C# Driver
Component/s: API
Affects Version/s: 2.0.1
Fix Version/s: None

Type: Bug Priority: Major - P3
Reporter: Robert Stam Assignee: Unassigned
Resolution: Done Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

Given the following classes:

public class C
{
    public int Id;
    public X X;
}
 
public class X
{
    public int A;
}

And the following sample data in a collection:

> db.test.find()
{ "_id" : 1, "X" : { "A" : 2 } }
>

The following code compiles correctly but throws an exception at runtime:

var collection = __database.GetCollection<C>("test");
var result = await collection.Aggregate()
    .Project(c => c.X)
    .ToListAsync();

The stack trace is:

Unhandled exception:
System.FormatException: Element 'X' does not match any field or property of class ConsoleApplication.X.
   at MongoDB.Bson.Serialization.BsonClassMapSerializer`1.DeserializeClass(BsonDeserializationContext context) in c:\work\rstam\mongo-csharp-driver\src\MongoDB.Bson\Serialization\Serializers\BsonClassMapSerializer.cs:line 209
   at MongoDB.Bson.Serialization.BsonClassMapSerializer`1.Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) in c:\work\rstam\mongo-csharp-driver\src\MongoDB.Bson\Serialization\Serializers\BsonClassMapSerializer.cs:line 96
   at MongoDB.Bson.Serialization.IBsonSerializerExtensions.Deserialize[TValue](IBsonSerializer`1 serializer, BsonDeserializationContext context) in c:\work\rstam\mongo-csharp-driver\src\MongoDB.Bson\Serialization\IBsonSerializerExtensions.cs:line 48
   at MongoDB.Bson.Serialization.Serializers.EnumerableSerializerBase`2.Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) in c:\work\rstam\mongo-csharp-driver\src\MongoDB.Bson\Serialization\Serializers\EnumerableSerializerBase.cs:line 286
   at MongoDB.Bson.Serialization.IBsonSerializerExtensions.Deserialize[TValue](IBsonSerializer`1 serializer, BsonDeserializationContext context) in c:\work\rstam\mongo-csharp-driver\src\MongoDB.Bson\Serialization\IBsonSerializerExtensions.cs:line 48
   at MongoDB.Driver.Core.Operations.AggregateOperation`1.CursorDeserializer.Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) in c:\work\rstam\mongo-csharp-driver\src\MongoDB.Driver.Core\Core\Operations\AggregateOperation.cs:line 327
   at MongoDB.Bson.Serialization.IBsonSerializerExtensions.Deserialize[TValue](IBsonSerializer`1 serializer, BsonDeserializationContext context) in c:\work\rstam\mongo-csharp-driver\src\MongoDB.Bson\Serialization\IBsonSerializerExtensions.cs:line 48
   at MongoDB.Driver.Core.Operations.AggregateOperation`1.AggregateResultDeserializer.Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) in c:\work\rstam\mongo-csharp-driver\src\MongoDB.Driver.Core\Core\Operations\AggregateOperation.cs:line 285
   at MongoDB.Bson.Serialization.IBsonSerializerExtensions.Deserialize[TValue](IBsonSerializer`1 serializer, BsonDeserializationContext context) in c:\work\rstam\mongo-csharp-driver\src\MongoDB.Bson\Serialization\IBsonSerializerExtensions.cs:line 48
   at MongoDB.Driver.Core.WireProtocol.CommandWireProtocol`1.ProcessReply(ConnectionId connectionId, ReplyMessage`1 reply) in c:\work\rstam\mongo-csharp-driver\src\MongoDB.Driver.Core\Core\WireProtocol\CommandWireProtocol.cs:line 164
... and a bunch more less useful stuff



 Comments   
Comment by Robert Stam [ 09/Aug/15 ]

Regarding the documentation, it was unclear that "new type" actually meant "instantiating a new instance of a type using the new keyword".

We should reopen this ticket (or create new ones) to:

1. Clarify the documentation of Project to document exactly what is and isn't supported
2. Throw a more informative exception when a form of Project is used that isn't supported
3. Add a feature request for this type of projection

Comment by Craig Wilson [ 08/Aug/15 ]

"a new type, either anonymous or named, must be used."

That seems clear to me. The problem is we don't have access to the entire tree, which means we cannot project a fake field into the next stage. This is different in LINQ, where we do have access to the entire tree and can project a fake a field. Regardless, as it is now, doing what you want is not possible. There is a chance we can change this in 2.1, but, because this is documented, it is not a bug.

Comment by Robert Stam [ 08/Aug/15 ]

There may be more going on here than you think.

It gave me the impression of working, because it rendered the pipeline as:

{ $project : { X : 1, _id : 0 } }

But the resulting documents were:

{ X : { A : 2 } }

instead of:

{ A : 2 }

which is what the deserializer expected.

The documentation you linked to only describes using anonymous types to describe the projection. It is unclear what should happen if the projection is to a regular class. Certainly the compile time result of this aggregate method is claiming that the result is a List<X>.

Comment by Craig Wilson [ 08/Aug/15 ]

This is documented here: http://mongodb.github.io/mongo-csharp-driver/2.0/reference/driver/crud/reading/#project.

We could probably throw a better exception.

Generated at Wed Feb 07 21:39:22 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.