12,292,006 members (70,085 online)
Technical Blog
alternative version

7.2K views
4 bookmarked
Posted

# Saving prices as decimal in mongodb

, 17 Jul 2014 CPOL
 Rate this:
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 th

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 :
http://stackoverflow.com/questions/2129804/rounding-double-values-in-c-sharp
http://stackoverflow.com/questions/15330988/double-vs-decimal-rounding-in-c-sharp
http://stackoverflow.com/questions/693372/what-is-the-best-data-type-to-use-for-money-in-c
http://pagehalffull.wordpress.com/2012/10/30/rounding-doubles-in-c/ )

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 :

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

public object Deserialize(BsonReader bsonReader, Type nominalType, Type actualType, IBsonSerializationOptions options)
{
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:

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.

## About the Author

 Web Developer 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!

## Comments and Discussions

 First Prev Next
 Great article. Another way to register custom serializer... klimonik18-Jul-14 5:26 klimonik 18-Jul-14 5:26
 Last Visit: 31-Dec-99 18:00     Last Update: 24-May-16 21:27 Refresh 1

General    News    Suggestion    Question    Bug    Answer    Joke    Praise    Rant    Admin

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