[CSHARP-3240] ImmutableTypeClassMapConvention is ignoring some constructors Created: 26/Oct/20  Updated: 28/Oct/23  Resolved: 11/Nov/20

Status: Closed
Project: C# Driver
Component/s: Serialization
Affects Version/s: 2.11.3
Fix Version/s: 2.12.0

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

Issue Links:
Duplicate
is duplicated by CSHARP-2984 Abstract getter confuses auto propert... Closed
is duplicated by CSHARP-3411 Ctors with Readonly Setters should ju... Closed

 Description   

ImmutableTypeClassMapConvention is ignoring any constructor that doesn't have exactly as many parameters as the class has properties.

This is not correct. All constructors should be considered.

The problem is this line of code:

https://github.com/mongodb/mongo-csharp-driver/blob/v2.11.3/src/MongoDB.Bson/Serialization/Conventions/ImmutableTypeClassMapConvention.cs#L55

The if statement and the continue statement should just be removed.



 Comments   
Comment by Gabriel Lucaci [ 22/Jun/22 ]

Just update a project from MongoDB.Driver 2.11.6 to latest version and realized that this Bugfix introduced a breaking change.

Considering class:

public class C
{
  public C(string property1)
  {
    Property1 = property1;
  }
 
  public string Property1 { get; private set; }
  public string Property2 { get; private set; }
}

and registering the map like this:

BsonClassMap.RegisterClassMap<C>();

will throw exception with latest version

No matching creator found. 

Comment by Githook User [ 11/Nov/20 ]

Author:

{'name': 'DmitryLukyanov', 'email': 'dmitry.lukyanov@mongodb.com', 'username': 'DmitryLukyanov'}

Message: CSHARP-3240: ImmutableTypeClassMapConvention is ignoring some constructors.
Branch: master
https://github.com/mongodb/mongo-csharp-driver/commit/8d175f2d2907348df0b6c63d95941c760332a08c

Comment by Robert Stam [ 26/Oct/20 ]

CSHARP-2984 is another manifestation of this issue.

Comment by Robert Stam [ 26/Oct/20 ]

This can be reproduced using this class:

// code placeholder
public class C
{
    private readonly int _id;
    private readonly int _x;
    private readonly int _y;
 
    public C(int id, int x)
    {
        _id = id;
        _x = x;
    }
 
    public C(int id, int x, int y)
    {
        _id = id;
        _x = x;
        _y = y;
    }
 
    public int Id => _id;
    public int X => _x;
    [BsonIgnoreIfDefault]
    public int Y => _y;
}

and this program:

public static void Main()
{
    var client = new MongoClient("mongodb://localhost");
    var database = client.GetDatabase("test");
    var collection = database.GetCollection<C>("test");
 
    database.DropCollection("test");
    var document = new C(1, 2);
    collection.InsertOne(document);
 
    var rehydrated = collection.FindSync("{}").Single();
    var json = rehydrated.ToJson();
}

which throws this exception:

MongoDB.Bson.BsonSerializationException
  HResult=0x80131500
  Message=No matching creator found.
  Source=MongoDB.Bson
  StackTrace:
   at MongoDB.Bson.Serialization.BsonClassMapSerializer`1.ChooseBestCreator(Dictionary`2 values) in C:\work\rstam\mongo-csharp-driver\src\MongoDB.Bson\Serialization\Serializers\BsonClassMapSerializer.cs:line 465
   at MongoDB.Bson.Serialization.BsonClassMapSerializer`1.CreateInstanceUsingCreator(Dictionary`2 values) in C:\work\rstam\mongo-csharp-driver\src\MongoDB.Bson\Serialization\Serializers\BsonClassMapSerializer.cs:line 473
   at MongoDB.Bson.Serialization.BsonClassMapSerializer`1.DeserializeClass(BsonDeserializationContext context) in C:\work\rstam\mongo-csharp-driver\src\MongoDB.Bson\Serialization\Serializers\BsonClassMapSerializer.cs:line 340
   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 129
   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 49
   at MongoDB.Driver.Core.Operations.CursorBatchDeserializationHelper.DeserializeBatch[TDocument](RawBsonArray batch, IBsonSerializer`1 documentSerializer, MessageEncoderSettings messageEncoderSettings) in C:\work\rstam\mongo-csharp-driver\src\MongoDB.Driver.Core\Core\Operations\CursorBatchDeserializationHelper.cs:line 64
   at MongoDB.Driver.Core.Operations.FindCommandOperation`1.CreateFirstCursorBatch(BsonDocument cursorDocument) in C:\work\rstam\mongo-csharp-driver\src\MongoDB.Driver.Core\Core\Operations\FindCommandOperation.cs:line 509
   at MongoDB.Driver.Core.Operations.FindCommandOperation`1.CreateCursor(IChannelSourceHandle channelSource, BsonDocument commandResult) in C:\work\rstam\mongo-csharp-driver\src\MongoDB.Driver.Core\Core\Operations\FindCommandOperation.cs:line 487
   at MongoDB.Driver.Core.Operations.FindCommandOperation`1.Execute(RetryableReadContext context, CancellationToken cancellationToken) in C:\work\rstam\mongo-csharp-driver\src\MongoDB.Driver.Core\Core\Operations\FindCommandOperation.cs:line 535
   at MongoDB.Driver.Core.Operations.FindOperation`1.Execute(RetryableReadContext context, CancellationToken cancellationToken) in C:\work\rstam\mongo-csharp-driver\src\MongoDB.Driver.Core\Core\Operations\FindOperation.cs:line 463
   at MongoDB.Driver.Core.Operations.FindOperation`1.Execute(IReadBinding binding, CancellationToken cancellationToken) in C:\work\rstam\mongo-csharp-driver\src\MongoDB.Driver.Core\Core\Operations\FindOperation.cs:line 453
   at MongoDB.Driver.OperationExecutor.ExecuteReadOperation[TResult](IReadBinding binding, IReadOperation`1 operation, CancellationToken cancellationToken) in C:\work\rstam\mongo-csharp-driver\src\MongoDB.Driver\OperationExecutor.cs:line 34
   at MongoDB.Driver.MongoCollectionImpl`1.ExecuteReadOperation[TResult](IClientSessionHandle session, IReadOperation`1 operation, ReadPreference readPreference, CancellationToken cancellationToken) in C:\work\rstam\mongo-csharp-driver\src\MongoDB.Driver\MongoCollectionImpl.cs:line 1226
   at MongoDB.Driver.MongoCollectionImpl`1.ExecuteReadOperation[TResult](IClientSessionHandle session, IReadOperation`1 operation, CancellationToken cancellationToken) in C:\work\rstam\mongo-csharp-driver\src\MongoDB.Driver\MongoCollectionImpl.cs:line 1219
   at MongoDB.Driver.MongoCollectionImpl`1.FindSync[TProjection](IClientSessionHandle session, FilterDefinition`1 filter, FindOptions`2 options, CancellationToken cancellationToken) in C:\work\rstam\mongo-csharp-driver\src\MongoDB.Driver\MongoCollectionImpl.cs:line 392
   at MongoDB.Driver.MongoCollectionImpl`1.<>c__DisplayClass45_0`1.<FindSync>b__0(IClientSessionHandle session) in C:\work\rstam\mongo-csharp-driver\src\MongoDB.Driver\MongoCollectionImpl.cs:line 382
   at MongoDB.Driver.MongoCollectionImpl`1.UsingImplicitSession[TResult](Func`2 func, CancellationToken cancellationToken) in C:\work\rstam\mongo-csharp-driver\src\MongoDB.Driver\MongoCollectionImpl.cs:line 1304
   at MongoDB.Driver.MongoCollectionImpl`1.FindSync[TProjection](FilterDefinition`1 filter, FindOptions`2 options, CancellationToken cancellationToken) in C:\work\rstam\mongo-csharp-driver\src\MongoDB.Driver\MongoCollectionImpl.cs:line 382
   at MongoDB.Driver.IMongoCollectionExtensions.FindSync[TDocument](IMongoCollection`1 collection, FilterDefinition`1 filter, FindOptions`2 options, CancellationToken cancellationToken) in C:\work\rstam\mongo-csharp-driver\src\MongoDB.Driver\IMongoCollectionExtensions.cs:line 933
   at ConsoleApplication.Program.Main() in C:\projects\ConsoleApplicationv2x\ConsoleApplicationv2x\Program.cs:line 68

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