Question

RavenDb - working with json / Polymorphic objects

I'd like to store configuration for a plugin system in RavenDb. The data is JSON (specifically, a string containing JSON), and every configuration item has some common data and a lot of implementation specific data. The common data looks like this and every implementation specific configuration derives from this class:

class BaseConfiguration
{
    public string Id {get; set;}
    public string Name {get; set;}
}

In other NoSqlDbs, when adding, I would construct a BsonDocument based on the JSON string representation of the object derived from BaseConfiguration and store that in a collection whose name I specify. Similarly, I'd extract the BsonDocument from the same collection, then return the JSON string to my application.

the number of items being saved is small - there's one of each class type and the type is not a known type for the database layer.

so, how'd I go about it? I could also imagine using a BaseConfiguration collection but then I'd need the ability to capture all properties that cannot be deserialized, and turn it back into a Json document.

 4  21  4
1 Jan 1970

Solution

 2

Here's how I ended up doing it (props to the RavenDb employees who helped me)

I stored and loaded the data as JObject.

using (var session = store.OpenSession())
{
    var data= session.Load<JObject>(id);
}

And saved my data (which I get as a json string) as follows

var newConfig = JObject.Parse(jsonString);
await session.StoreAsync(newConfig, id).ConfigureAwait(false);
await session.SaveChangesAsync().ConfigureAwait(false);

That will save the objects in a collection named JObjects. I didn't like that so I used the FindCollectionName convention name to specify my own collection name:

store = new DocumentStore()
{
    Urls = [ ..urls],
    Conventions =
    {
        FindCollectionName = GetCollectionName
    },
};

internal static string GetCollectionName(Type type)
{
    if (type == typeof(JObject))
        return "PluginConfigurations";
    var className = type.Name;
    className = $"{className[..1].ToLower()}{className[1..]}";
    if (!className.EndsWith('s'))
        className = $"{className}s";
    return className;
}

So the objects end up in a collection named PluginConfigurations.

2024-07-16
Stephan Steiner