Deleting RavenDB View Models Before Replaying Your Events

I’ve recently been looking for a nice way to be able to programatically blow away the view models I have stored in RavenDB as part of a new CQRS project I’m working on so I can rebuild them by replaying my events. Whilst the rebuilding part is fairly simple, the deleting part isn’t. At first glance there is no immediately obvious answer as to how to get rid of them all though I did find this post but I wanted something a bit cleaner. The problem is that each document type you define gets stored in its own collection. When you want to replay your events so that you can rebuild those view models you somehow need to first delete them all. You might be tempted to query for the documents and then pass each one to the delete method on the session:

using (var session = store.OpenSession())
{
    var viewModels = session.Query<SampleViewModel>();
    foreach (var vm in viewModels)
    {
        session.Delete(vm);
        session.SaveChanges();
    }
}

but this isn’t a good approach at all as you don’t want to have to load the documents into memory before being able to delete them. Even if it was a good idea, you’d have to repeat that code for each different view model document type, and each time you added a new view model you’d have to update the code to do it again. Not good at all.

Luckily, RavenDB supports a set-based Delete operation which takes an index which we could use to return to us all the view model types:

using (var session = store.OpenSession())
{
    session.Advanced.DatabaseCommands.DeleteByIndex("ViewModelIndex", 
        new IndexQuery());
    session.SaveChanges();
}

The question is what should the index definition look like?

Ordinarily you would define an index in code along the following lines:

public class ViewModelIndex : AbstractIndexCreationTask<SampleViewModel>
{
    public ViewModelIndex()
    {
        Map = docs => from doc in docs
                      select new { Id = doc.Id };
    }
}

but again this index is for a specific view model type, in this case SampleViewModel. What I really wanted was an index that would return me documents from multiple collections. One that I could use to find all my view models no matter what their type, and after quite a bit of experimentation and a few dead-ends, I finally hit upon a way of achieving my goal. The trick is to take advantage of a piece of metadata each document in RavenDB has and to follow the “convention over configuration” approach. Take a look at this index definition:

public class ViewModelIndex : AbstractIndexCreationTask<object>
{
    public ViewModelIndex()
    {
        Map = docs => from doc in docs
                      where MetadataFor(doc)["Raven-Clr-Type"]
                            .ToString().Contains("ViewModels")
                      select new {};
    }
}

This index looks at the “Raven-Clr-Type” metadata on each document which contains the fully qualified type name. If that name is deemed to contain the word “ViewModels” the document is added to the results. The convention part therefore is simply that you have to ensure that all your view model documents are located in a namespace containing the word “ViewModels”. The result is a set of documents from multiple collections which can be used in the DeleteByIndex method. Once your views have been destroyed it’s a simple matter to reload your events and push them through your event handlers again.

I am quite new to RavenDB so there may be an alternative/better approach but if so I’ve yet to find it but I’d be interested to hear from anyone if there is. In the meantime, this solved my dilemma neatly.

Deleting RavenDB View Models Before Replaying Your Events