Click here to Skip to main content
15,885,537 members
Articles / Programming Languages / C#

Saving Prices as Decimal in mongodb

Rate me:
Please Sign up or sign in to vote.
5.00/5 (3 votes)
17 Jul 2014CPOL2 min read 20.6K   4   1
Saving prices as decimal in mongodb

When working with prices in C#, you should always work with the 'decimal' type. Working with the 'Double' type can lead to a variety of rounding errors when doing calculations with them, and is more intended for mathematical equations.

(I don't want to go into details about what problems this can cause exactly, but you can read more about it here:

I am currently working on a project that involves commerce and prices, so naturally I used 'decimal' for all price types. Then I headed to my db, which in my case is mongodb, and the problem arose. MongoDB doesn't support 'decimal'!! It only supports the double type.

Since I rather avoid saving it as a double for reasons stated above, I had to think of a better solution. I decided to save all the prices in the db as Int32 saving the prices in 'cents'.

This means I just need to multiply the values by 100 when inserting to the db, and dividing by 100 when retrieving. This should never cause any rounding problems, and is pretty much straight-forward. I even don't need to worry about sorting, or any other query for that matter.

But... I don't want ugly code doing all these conversions from cents to dollars in every place...

I'm using the standard C# mongo db driver (https://github.com/mongodb/mongo-csharp-driver), which gives me the ability to write a custom serializer for a specific field. This is a great solution, since it's the lowest level part of the code that deals with the db, and that means all my entities will be using 'decimal' everywhere.

This is the code for the serializer:

C#
[BsonSerializer(typeof(MongoDbMoneyFieldSerializer))]
public class MongoDbMoneyFieldSerializer : IBsonSerializer
{
    public object Deserialize
    (BsonReader bsonReader, Type nominalType, IBsonSerializationOptions options)
    {
        var dbData = bsonReader.ReadInt32();
        return (decimal)dbData / (decimal)100;
    }

    public object Deserialize
    (BsonReader bsonReader, Type nominalType, Type actualType, IBsonSerializationOptions options)
    {
        var dbData = bsonReader.ReadInt32();
        return (decimal)dbData / (decimal)100;
    }

    public IBsonSerializationOptions GetDefaultSerializationOptions()
    {
        return new DocumentSerializationOptions();
    }

    public void Serialize
    (BsonWriter bsonWriter, Type nominalType, object value, IBsonSerializationOptions options)
    {
        var realValue = (decimal) value;
        bsonWriter.WriteInt32(Convert.ToInt32(realValue * 100));
    }
}

And then, all you need to do is add the custom serializer to the fields which are prices, like this:

C#
public class Product
{
    public string Title{ get; set; }
    public string Description { get; set; }

    [BsonSerializer(typeof(MongoDbMoneyFieldSerializer))]
    public decimal Price { get; set; }

    [BsonSerializer(typeof(MongoDbMoneyFieldSerializer))]
    public decimal MemberPrice { get; set; }

    public int Quantity { get; set; }
}

That's all there is to it.

This article was originally posted at http://www.debuggerstepthrough.com/feeds/posts/default

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
Israel Israel
Started programming e-commerce sites with PHP & MySQL at the age of 14. Worked for me well for about 5 years.

Transfered to C# & asp.net, while serving in the IDF.
Worked on the 'Core Performance' Team at ShopYourWay.com (Sears Israel)
Currently working at Logz.io

Check out my blog!
or my twitter

Comments and Discussions

 
QuestionGreat article. Another way to register custom serializer... Pin
klimonik18-Jul-14 5:26
klimonik18-Jul-14 5:26 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.