Third post in “Fun With NoRM” will be about how “the dynamism” of JavaScript and JSON is bridged into the rigid and statically typed world of C#. The thing is, in principle there’s no way to be certain that a JSON object returned from MongoDB will actually fit into our static object model.
Consider a situation where, for some reason, some of our orders have a field, PlacedBy, containing the name of the person who placed the order. Let’s see how things will go when adding the field and then querying all orders:
1 2 3 4 |
> use dbname > var order = db.Order.findOne(); > order.PlacedBy = "El Duderino"; > db.Order.save(order); |
1 2 3 4 5 6 |
var orders = mongo.GetCollection<Order>(); foreach(var order in orders.Find()) { Console.WriteLine("Order #{0}", order.Number); } |
– and BOOM ! – Cannot deserialize!: Norm.MongoException: Deserialization failed: type MongoTest.Order does not have a property named PlacedBy
This is actually pretty good, because this way we will never accidentally load a document with un-deserializable properties and save it back, thus truncating the document. But how can we handle this?
Well, NoRM makes it pretty easy: Make your model class inherit Expando, thus effectively becoming a dictionary. E.g. like so:
1 2 3 4 |
public class Order : Expando { // ... } |
Now we can do this:
1 2 3 4 5 6 7 8 9 10 11 12 |
var orders = mongo.GetCollection<Order>(); foreach(var order in orders.Find()) { Console.WriteLine("Order #{0}", order.Number); if (order.AllProperties().Any()) { var props = order.AllProperties().Select(p => string.Format("{0}: {1}", p.PropertyName, p.Value)); Console.WriteLine("\t{0}", string.Join(", ", props.ToArray())); } } |
– which yields:
1 2 3 4 |
Order #1 PlacedBy: El Duderino Order #2 Order #3 |
when run with a small DB containing three orders. Nifty, huh?
If you’re sad that you’ve given up your single opportunity to inherit something by deriving from Expando, just go ahead and implement IExpando instead. Then you need to suply a few members, but you can just redirect to an internal Expando in your class.
Next up, a post on how to model inheritance hierarchies… one of my favorites! 🙂