Bryandh
Bryandh

Reputation: 529

How to store C# objects with dynamic properties in RavenDB?

I'm having problems when trying to save an object that has a dynamic property in RavenDB

The object I'm trying to save represents an order. The order contains a list of orderlines so imagine the following Order class:

public class Order {
    public int Id { get; set; }
    public List<Orderline> Orderlines { get; set; }
}

And the Orderline class being:

public class Orderline {
    public Product Product { get; set; }
    public int Quantity { get; set; }
    public dynamic Attributes { get; set; }
}

The object I'm trying to save (I'll display it with JSON);

{
    "Id": 0,
    "Orderlines": [
        {
            "Product": {
                "Id": 0,
                "Name": "Some product"
            },
            "Quantity": 1,
            "Attributes": {
                "color": "Red"
            }
        }
    ]
}

Saving it does not throw any errors
RavenDB stores the Order object as

{
    "Id": 0,
    "Orderlines": [
        {
            "Product": {
                "Id": 0,
                "Name": "Some product"
            },
            "Quantity": 1,
            "Attributes": {
                "$type": "Newtonsoft.Json.Linq.JObject, Newtonsoft.Json",
                "color": {
                    "$type": "Newtonsoft.Json.Linq.JValue, Newtonsoft.Json",
                    "$values": []
                }
            }
        }
    ]
}

Note that the values property of Order.Orderlines[0].Attributes.color is not set...

When I try to serialize the object back to my C# Order object I get the following exception;

Unable to cast object of type 'Raven.Imports.Newtonsoft.Json.Utilities.CollectionWrapper`1[Newtonsoft.Json.Linq.JToken]' to type 'Newtonsoft.Json.Linq.JValue'.

What am I doing wrong, how can I store this object in the RavenDB database and retrieve it?

Upvotes: 4

Views: 837

Answers (2)

Bryandh
Bryandh

Reputation: 529

Storing the dynamic property with type 'dynamic' apparently wasn't enough. When I gave the Attributes property the ExpandoObject type, RavenDB stored the Attributes property as normal JSON (without $type and $values, so clean as desired)

When retrieving it back from the RavenDB database it deserializes back to an ExpandoObject object.

Make sure to cast the ExpandoObject property to a dynamic (e.g. 'as dynamic') when trying to display the property in a Razor view.

Upvotes: 2

Ayende Rahien
Ayende Rahien

Reputation: 22956

What is the type that you are actually saving into attributes? Typically you'll use something that is actually dynamic, like ExpandoObject

Upvotes: 2

Related Questions