[CSHARP-4538] Error on Project if null values are not filtered Created: 21/Feb/23  Updated: 28/Oct/23  Resolved: 23/Feb/23

Status: Closed
Project: C# Driver
Component/s: LINQ3
Affects Version/s: 2.19.0
Fix Version/s: 2.19.1

Type: Bug Priority: Unknown
Reporter: Salvo Furnari Assignee: Robert Stam
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Attachments: Zip Archive minimalRepro.zip    
Documentation Changes: Not Needed
Documentation Changes Summary:

1. What would you like to communicate to the user about this feature?
2. Would you like the user to see examples of the syntax and/or executable code and its output?
3. Which versions of the driver/connector does this apply to?


 Description   

Summary

Using LINQ3 If Project will produce a null result element an exception will be thrown:

 

_System.InvalidOperationException: ReadName can only be called when State is Name, not when State is EndOfDocument.
   at MongoDB.Bson.IO.BsonReader.ThrowInvalidState(String methodName, BsonReaderState[] validStates)
   at MongoDB.Bson.IO.BsonBinaryReader.ReadName(INameDecoder nameDecoder)
   at MongoDB.Bson.IO.IBsonReaderExtensions.ReadName(IBsonReader reader)
   at MongoDB.Bson.IO.IBsonReaderExtensions.VerifyName(IBsonReader reader, String expectedName)
   at MongoDB.Bson.IO.IBsonReaderExtensions.ReadName(IBsonReader reader, String name)
   at MongoDB.Driver.Linq.Linq3Implementation.Serializers.WrappedValueSerializer`1.Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
   at MongoDB.Bson.Serialization.IBsonSerializerExtensions.Deserialize[TValue](IBsonSerializer`1 serializer, BsonDeserializationContext context)
   at MongoDB.Driver.Core.Operations.CursorBatchDeserializationHelper.DeserializeBatch[TDocument](RawBsonArray batch, IBsonSerializer`1 documentSerializer, MessageEncoderSettings messageEncoderSettings)
   at MongoDB.Driver.Core.Operations.FindOperation`1.CreateFirstCursorBatch(BsonDocument cursorDocument)
   at MongoDB.Driver.Core.Operations.FindOperation`1.CreateCursor(IChannelSourceHandle channelSource, IChannelHandle channel, BsonDocument commandResult)
   at MongoDB.Driver.Core.Operations.FindOperation`1.ExecuteAsync(RetryableReadContext context, CancellationToken cancellationToken)
   at MongoDB.Driver.Core.Operations.FindOperation`1.ExecuteAsync(IReadBinding binding, CancellationToken cancellationToken)
   at MongoDB.Driver.OperationExecutor.ExecuteReadOperationAsync[TResult](IReadBinding binding, IReadOperation`1 operation, CancellationToken cancellationToken)
   at MongoDB.Driver.MongoCollectionImpl`1.ExecuteReadOperationAsync[TResult](IClientSessionHandle session, IReadOperation`1 operation, ReadPreference readPreference, CancellationToken cancellationToken)
   at MongoDB.Driver.MongoCollectionImpl`1.UsingImplicitSessionAsync[TResult](Func`2 funcAsync, CancellationToken cancellationToken)
   at MongoDB.Driver.IAsyncCursorSourceExtensions.ToListAsync[TDocument](IAsyncCursorSource`1 source, CancellationToken cancellationToken)_

 

LINQ2 adds null elements in the result.

How to Reproduce

define a class with a nullable type property

class TestData
{
    [BsonId]
    [BsonRepresentation(BsonType.ObjectId)]
    public string _id { get; set; }
    public double? DoubleNullableValue { get; set; }
} 

Insert elements with null value for DoubleNullableValue


_var mongoUrl = MongoUrl.Create("mongodb://localhost:27017");
var clientSettings = MongoClientSettings.FromUrl(mongoUrl);
clientSettings.LinqProvider = LinqProvider.V3;
var mongoC = new MongoClient(clientSettings);
var collection = mongoC.GetDatabase("Tests").GetCollection<TestData>("NullableDataTest");
//Insert test samples
await collection.InsertManyAsync(new []
{
new TestData

{ DoubleNullableValue = 1.4d }

,
new TestData()
});_

Make a find thath will not exlude the null values and projects them
__

await collection.Find(_ => true).Project(t => t.DoubleNullableValue).ToListAsync(); 

The above exception will be thrown.

Additional Background

.NET6 Console project reproducing bug attached. (Ensure {}mongoUrl).



 Comments   
Comment by Githook User [ 24/Mar/23 ]

Author:

{'name': 'rstam', 'email': 'robert@robertstam.org', 'username': 'rstam'}

Message: CSHARP-4538: Skip some tests on older servers.
Branch: v2.19.x
https://github.com/mongodb/mongo-csharp-driver/commit/d7b814478fed8bcc16ba89a90555b20ad006cec0

Comment by Githook User [ 24/Mar/23 ]

Author:

{'name': 'rstam', 'email': 'robert@robertstam.org', 'username': 'rstam'}

Message: CSHARP-4538: WrappedValueSerializer should handle empty documents.
Branch: v2.19.x
https://github.com/mongodb/mongo-csharp-driver/commit/41604c9a11d68d80d7bcdc6d54041c97cfe5f3fe

Comment by Githook User [ 01/Mar/23 ]

Author:

{'name': 'rstam', 'email': 'robert@robertstam.org', 'username': 'rstam'}

Message: CSHARP-4538: Skip some tests on older servers.
Branch: master
https://github.com/mongodb/mongo-csharp-driver/commit/9af3ab9289fc1aa475766bbe130c8354bad4a7a0

Comment by Githook User [ 23/Feb/23 ]

Author:

{'name': 'rstam', 'email': 'robert@robertstam.org', 'username': 'rstam'}

Message: CSHARP-4538: WrappedValueSerializer should handle empty documents.
Branch: master
https://github.com/mongodb/mongo-csharp-driver/commit/19ae03fc772ae0ed10ba1cea19ccaa12ed4190ec

Comment by Salvo Furnari [ 21/Feb/23 ]

Thanks for the feedback, 
After reading the answer i investigated further.
Mongo Version: 4.2.23 my code will reproduce the bug.
Mongo Version: 6.0.4 the nullable field needs to be missing entirely as you said.
Hope it can be useful.

Comment by Robert Stam [ 21/Feb/23 ]

Thanks for letting us know about this issue.

I have been able to reproduce the issue but not with the exact code you provided. I had to manually create a document where the nullable field is missing entirely (as opposed to being present but having a value of `null`).

I am working on a fix.

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