Summary
Apologies if I miss something expected, just joined the project so I could report this. I'm encountering a bug where the LINQ3 provider is not matching a document for update, but LINQ2 provider works.
I think it has something to do with the string -> ObectId conversion not woking with Linq3, maybe bsonserializer attribute is being ignored?
Please provide the version of the driver. If applicable, please provide the MongoDB server version and topology (standalone, replica set, or sharded cluster).
MongoDB.Driver 2.22.0 (worked with MongoDB.Driver 2.16.1)
MongoDB 6.04 replicaset
How to Reproduce
Steps to reproduce. If possible, please include a Short, Self Contained, Correct (Compilable), Example.
create a .net 6 console application
add nuget for:
MongoDB.Driver 2.22
Microsoft.Extensions.Configuration 7.0
_ _Microsoft.Extensions.Configuration.Json 7.0
add an appsettings.json file with
_
{ "ConnectionStrings": \{ "MongoConnectionString": "<<<mongo connection string here>>>" }}_
in Program.cs add this code
_using MongoDB.Bson.Serialization.Serializers;
using MongoDB.Bson;
using MongoDB.Driver;
using MongoDB.Bson.Serialization;
using Microsoft.Extensions.Configuration;
using MongoDB.Bson.Serialization.Attributes;/**
*
*
* toggle the value for useLinq3 to true to reproduce bug
* toggle the vaue for useLinq3 to false to show working in legacy
*
*/_
_var useLinq3 = false;
#region mainvar configuration = new ConfigurationBuilder()
.AddJsonFile($"appsettings.json");var config = configuration.Build();
var connectionString = config.GetConnectionString("MongoConnectionString");MongoClientSettings settings = MongoClientSettings.FromConnectionString(connectionString);
if (!useLinq3)
{
settings.LinqProvider = MongoDB.Driver.Linq.LinqProvider.V2;
}
MongoClient dbClient = new MongoClient(settings);var database = dbClient.GetDatabase("sample_update_bug");
var collection = database.GetCollection<RootDocument>("RootDocuments");
var newDoc = new RootDocument() { Id = ObjectId.GenerateNewId().ToString() };
await collection.InsertOneAsync(newDoc);
var newSubDoc = new SubDocument()
{
SdId = ObjectId.GenerateNewId().ToString(),
DateAdded = DateTime.UtcNow
};FilterDefinition<RootDocument> filter = Builders<RootDocument>.Filter.Where(x => x.Id == newDoc.Id);
UpdateDefinition<RootDocument> update = Builders<RootDocument>.Update.Set(x => x.SubDoc, newSubDoc);var updateResult = await collection.UpdateOneAsync(filter, update).ConfigureAwait(false);
#endregion main
public static class Extensions
{
public static ObjectId ToObjectId(this string source)
{
if (ObjectId.TryParse(source, out ObjectId returnId))
else
{
return ObjectId.Empty; }
}
}#region string to ObjectId serializer
public class ObjectIdSerializer : SerializerBase<string>
{
public override string Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
{
BsonType type = context.Reader.GetCurrentBsonType();
switch (type)
{
case BsonType.ObjectId: return context.Reader.ReadObjectId().ToString();
default:
var message = $"Cannot convert a
to a String.";
throw new NotSupportedException(message);
}
} public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, string value)
{
context.Writer.WriteObjectId(value.ToObjectId());
}
}
#endregion#region entities
[BsonIgnoreExtraElements]
public class RootDocument
{
public RootDocument()
[BsonSerializer(typeof(ObjectIdSerializer))]
public string Id { get; set; } [BsonElement("sd")]
public SubDocument SubDoc { get; set; }
}public class SubDocument
{
/// <summary>The _id of the document in GridFS</summary>
[BsonElement("s")]
[BsonSerializer(typeof(ObjectIdSerializer))]
public string SdId
[BsonElement("d")]
public DateTime DateAdded { get; set; }}
#endregion_
Run with useLinq3 = false
Run with useLinq3 = true
open a mongodb client and query the docs in the RootDocuments collection
expected:
the docs should be equivalent (diff id's, and times, but same fields should be populated)
actual:
the doc when linq3 is used still has "sd" : null instead of the subdocument being saved
Additional Background
Please provide any additional background information that may be helpful in diagnosing the bug.