Let’s say that you’ve got a model with a marker interface and some types implementing that interface. Something like this:
public interface ILookup { } public class IntegerLookup : ILookup { public int Number { get; set; } } public class StringLookup : ILookup { public string Text { get; set; } }Then you have a type that holds a collection of the interface:
public class Container { public ILookup[] Lookups { get; set; } }All good so far, and now you want to store this in a database. Not quite so simple! If you’re using a relational database, whether through an ORM or another means, you will have to do quite a bit more work to get your objects into the database and back.
However, if you’re using RavenDB then your work is done! Well, nearly - all you need to do is to add an Id property to your container to tell RavenDB to store it as a root:
public class Container { public string Id { get; set; } public ILookup[] Lookups { get; set; } }That’s it – the rest is pure Raven magic! Here’s a test showing how Raven it handles it:
[Test] public void can_store_polymorphic_collection() { using (var store = new EmbeddableDocumentStore { DataDirectory = "Data", RunInMemory = true }) { store.Initialize(); var holder = new Container { Lookups = new ILookup[] { new StringLookup {Text = "Hello"}, new IntegerLookup {Number = 123} } };
using (var session = store.OpenSession()) { session.Store(holder); session.SaveChanges(); } using (var session = store.OpenSession()) { var h = session.Load<Container>(holder.Id); Assert.That(h.Lookups .OfType<StringLookup>().Single().Text == "Hello"); Assert.That(h.Lookups .OfType<IntegerLookup>().Single().Number == 123); } } }You just new up an instance of Container, add in a couple of ILookup instances, then save it. When I load it back up, it’s all there just as you need it to be. Now, that is seriously impressive!