[CSHARP-3195] GuidRepresentation made obsolete while function appears impared and documentation remains out of date. Created: 21/Aug/20  Updated: 22/Jun/22

Status: Backlog
Project: C# Driver
Component/s: API, BSON, Documentation
Affects Version/s: 2.11.0
Fix Version/s: None

Type: Bug Priority: Major - P3
Reporter: Chris McKee Assignee: Unassigned
Resolution: Unresolved Votes: 5
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

All


Attachments: File MongoGuidStandardIssue.csproj     Text File Program.cs     PNG File image-2020-08-28-09-48-09-587.png    
Issue Links:
Related
is related to CSHARP-3179 FilterDefinition don't respect GuidRe... Backlog
Backwards Compatibility: Fully Compatible

 Description   

Linked to https://jira.mongodb.org/browse/CSHARP-3179

The entirety of the commonly used BsonDefaults method of setting GuidRepresentation has been marked obsolete while the documentation still refers to it and neither the "obsolete" warning or xmldoc inform you of what the replacement is beyond the vague statement `[Obsolete("Configure serializers instead.")]`

The following example will fail with `MongoDB.Driver.MongoCommandException: 'Command findAndModify failed: After applying the update, the (immutable) field '_id' was found to have been altered to _id: UUID("45206b70-146b-4947-9de2-aaab99c2223b").'`

Appending `?uuidRepresentation=Standard` to the connection string and the upsert will work as expected (previous behaviour); as would setting `BsonDefaults.GuidRepresentation = GuidRepresentation.Standard;` both of these configurations correctly store the ID as UUID() in mongo.

Swapping BSONID for [BsonRepresentation(BsonType.Binary)] will allow the code to run otherwise unaltered but then stores the ID as BinData(3, "a1A8tGgqy0myU3jvfIW3wQ==")

Changing the ID field to [BsonId, BsonGuidRepresentation(GuidRepresentation.Standard)]
results in the immutable id error again.

using MongoDB.Driver;
using System;
using System.Threading.Tasks;
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
 
namespace MongoGuidStandardIssue
{
 
    [Serializable]
    public class ReadModel
    {
        public ReadModel(Guid id)
        {
            Id = id;
            CreatedDate = DateTimeOffset.UtcNow;
        }
 
        [BsonId]
        public Guid Id { get; set; }
 
        [BsonRepresentation(BsonType.String)]
        public DateTimeOffset CreatedDate { get; set; }
 
    }
 
    public sealed class UserReadModel : ReadModel
    {
        public string Username { get; set; }
        public UserReadModel(Guid id) : base(id) { }
    }
 
 
    public static class Program
    {
        public static async Task Main(string[] args)
        {
            BsonSerializer.RegisterSerializer(new GuidSerializer(GuidRepresentation.Standard));
            var mongoClient = new MongoClient("mongodb://localhost:32768");
 
            var readStoreDb = mongoClient.GetDatabase("test");
 
            var userReadStore = readStoreDb.GetCollection<UserReadModel>(nameof(UserReadModel));
 
            var userId = Guid.NewGuid();
            var newUser = new UserReadModel(userId)
            {
                CreatedDate = DateTimeOffset.UtcNow,
                Username = "Test " + DateTime.Now.Ticks.ToString()
            };
 
            var findOneAndReplaceTask = await userReadStore.FindOneAndReplaceAsync<UserReadModel>(_ => _.Id == newUser.Id, newUser, new FindOneAndReplaceOptions<UserReadModel> { IsUpsert = true, ReturnDocument = ReturnDocument.After });
 
            Console.WriteLine("Done");
            Console.ReadLine();
        }
    }
}

 
We appear to have gone from one line of code to configure ID storage to config roulette.

Its hard to tell if this is an underlying driver issue, a lack of validation or just a communication/documentation issue; the commit messages around the change don't shine much light on it either. ( ` CSHARP-2724: Implement specification for handling native UUID types. `
 https://github.com/mongodb/mongo-csharp-driver/commit/b0b11348e1fb2418ca6a5999a2494db54ec186e5 ) the addition of new code that is immediately marked as obsolete also muddies the water a tad.

Thanks



 Comments   
Comment by James Kovacs [ 23/Mar/21 ]

Hi, Joe and Chris,

Apologies for the late response on this issue. It percolated back up to the top of our queue due to Hugo's comment.

Chris is correct that the intention behind marking the property as obsolete is that we plan to remove it in a future version when we switch to only supporting V3 mode and subtype 4 GUIDs. Our desire is to warn users not to depend on being able to switch between GUID representation modes.

Thank you for your suggestion about linking the xmldocs to the reference page to make this issue more discoverable. We will consider this for a future version of our documentation.

Sincerely,
James

Comment by James Kovacs [ 23/Mar/21 ]

Hi, Hugo,

Thank you for reaching out to us about this issue. Although it is related, your issue appears to be separate and distinct from the poor documentation/expectations around BsonDefaults.GuidRepresentationMode that this ticket focuses on. Please open a separate ticket with a reproduction of your issue and we will be happy to investigate with you.

Sincerely,
James

Comment by Hugo Tavares [ 23/Mar/21 ]

Hi, so regarding the V3 representation mode. I'm having an issue using it in conjunction with a custom `BsonDocumentFilterDefinition` using aggregation pipeline operators when the value I'm trying to match is a Guid. The reason for this is that when the BsonArray constructor tries to add the values to the document it tries to instantiate a BsonBinaryData object with the Guid value. This constructor throws an exception  stating that it is only supported when using the V2 GuidRepresentationMode. I can't find any documentation on how this can be used with the V3 GuidRepresentationMode.

Comment by Chris McKee [ 28/Aug/20 ]

Thanks for the update; its just a confusing mix of changes as the whole feature for setting guid representations is marked obsolete ("use the serializer"); which does of course match the docs `In future v3.x versions of the driver V3 will be the default mode (and support for V2 mode will be removed).` if you read between the lines that the entire setting will be removed as only V3 will exist.

It would be a good idea to add a link to the xmldoc pointing to the `http://mongodb.github.io/mongo-csharp-driver/2.11/reference/bson/guidserialization/` page though. (summaries can hold <a href=xxx>etc )

Comment by Joe Cummings [ 28/Aug/20 ]

BsonDefaults.GuidRepresentation is marked as obsolete in 2.11.0 and does not align with documentation, V3 is being pushed however warned as obsolete when used.

//
// Summary:
//     Gets or sets the default representation to be used in serialization of Guids
//     to the database. MongoDB.Bson.GuidRepresentation
[Obsolete("This property will be removed in a later release.")]
public static GuidRepresentationMode GuidRepresentationMode { get; set; }

 

Comment by Robert Stam [ 27/Aug/20 ]

An alternative workaround while staying in V2 mode is the following:

BsonDefaults.GuidRepresentation = GuidRepresentation.Unspecified;

Setting the default GuidRepresentation to Unspecified turns off the automatic conversions of Guids to the default representation (which is the cause of this bug).

Switching to V3 mode also turns off automatic conversions (Guids are never automatically converted to other representations in V3 mode).

 

 

Comment by Robert Stam [ 27/Aug/20 ]

I am able to reproduce this with the code you provided. Thanks very much for providing a reproduction.

There does seem to be an issue here that needs to be fixed.

In the long run we encourage everyone to use the new V3 GuidRepresentationMode, and in fact when using V3 mode this bug does not appear to happen. I added the following line of code as the first line of main:

BsonDefaults.GuidRepresentationMode = GuidRepresentationMode.V3;

We still need to figure out how to get your code to work in V2 mode, but if you are willing to use V3 mode you could have an immediate workaround.

 

Comment by Robert Stam [ 27/Aug/20 ]

The changes to how Guids are serialized are documented here:

http://mongodb.github.io/mongo-csharp-driver/2.11/reference/bson/guidserialization/

 

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