How to use decimal type in MongoDB

How can I store decimals in MongoDB using the standard C# driver? It seems that all decimals are stored inside the database as strings.


MongoDB doesn't properly support decimals until MongoDB v3.4. Before this version it stored decimals as strings to avoid precision errors.

Pre v3.4 Store decimals as strings, but this prevents arithmetic operations. Operators as $min, $avg, ... won't be available. If precision is not a big deal, then you might be able to switch to double.

v3.4+ You need to make sure the following preconditions are true:

  • MongoDB server should be at least v3.4.
  • MongoCSharpDriver should be at least v2.4.3.
  • Database should have featureCompatibilityVersion set to '3.4'. If your database has been created by an older MongoDB version and you have upgraded your server to v3.4 your database might still be on an older version.

If you have all the properties set, then register the following serializers to use the decimal128 type:

BsonSerializer.RegisterSerializer(typeof(decimal), new DecimalSerializer(BsonType.Decimal128));
BsonSerializer.RegisterSerializer(typeof(decimal?), new NullableSerializer<decimal>(new DecimalSerializer(BsonType.Decimal128)));

I recently ran in to this problem. I solved it by simply annotating my object like this:

[BsonRepresentation(BsonType.Decimal128)]
public decimal Price {get; set;}

I had issues using the RegisterSerializer approach as it complained that it already had a serializer registered, but an alternative is to write your own serialization provider and use that.

Here's the provider:

public class CustomSerializationProvider : IBsonSerializationProvider
{
    private static readonly DecimalSerializer DecimalSerializer = new DecimalSerializer(BsonType.Decimal128);
    private static readonly NullableSerializer<decimal> NullableSerializer = new NullableSerializer<decimal>(new DecimalSerializer(BsonType.Decimal128));

    public IBsonSerializer GetSerializer(Type type)
    {
        if (type == typeof(decimal)) return DecimalSerializer;
        if (type == typeof(decimal?)) return NullableSerializer;

        return null; // falls back to Mongo defaults
    }
}

which you need to register by calling

BsonSerializer.RegisterSerializationProvider(new CustomSerializationProvider());

I solved it like Erik Kindling, by annotating the object like this:

[BsonRepresentation(BsonType.Decimal128)]
public decimal Price {get; set;}

However, it is important that you re-populate your mongodb collection otherwise the string value will be preserved. The field value will be in this format once inserted properly:

"Price" : NumberDecimal("99")