Issue
We have a custom serializer for an enum (MeasurementValueType), which stores the enum as a string in MongoDB and deserializes it from a string back into the enum when querying.
The enum MeasurementValueType is declared as ushort. If it is not then everything works as expected.
We are using Mongo C# driver version 2.30 and trying to upgrade to linq provider v# from V2.
Setup
A simple class with an enum property:
public class TestA
{
public MeasurementValueType ValueType { get; set; }
}
public enum MeasurementValueType : ushort
{
Distance = 1,
Angle = 2
}
Custom serializer for MeasurementValueType:
public class MeasurementValueTypeSerializer : StructSerializerBase<MeasurementValueType>
{
public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, MeasurementValueType value)
{
BsonSerializer.Serialize(context.Writer, value.ToString());
}
public override MeasurementValueType Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
{
var measurementValueType = (MeasurementValueType)Enum.Parse(
args.NominalType,
BsonSerializer.Deserialize<string>(context.Reader)
);
return measurementValueType;
}
}
Registered in startup:
BsonSerializer.RegisterSerializer(typeof(MeasurementValueType), new MeasurementValueTypeSerializer());
Expected behavior
When saving a document, ValueType should be stored as a string in MongoDB.
When querying, the deserializer should convert it back to the enum. When inserting an object the serializer is called and the enum is persisted as a string. When fetching it back as a whole document, the deserializer is called.
Problem
If I query using LINQ, the deserializer is not applied and no match is found:
database.TestACollection.Insert(new TestA { ValueType = MeasurementValueType.Angle });
var match = database.TestACollection
.AsQueryable()
.Single(x => x.ValueType == MeasurementValueType.Angle);
This worked fine in LINQ Provider v2, but in LINQ Provider v3, it no longer matches.
Question
Why isn't the right-hand expression (MeasurementValueType.Angle) passed to the serializer so it can be converted to a string before executing the query?
I understand that we do not want to deserialize the stored properties but my right-hand expression i.e. the enum could be serialized to the same format (string) for fast comparison on the database side.
Is there a workaround to ensure the serializer is respected in LINQ queries?
Can I register the serializer in a different way so that LINQ v3 applies it?