Ayende @ Rahien

My name is Oren Eini
Founder of Hibernating Rhinos LTD and RavenDB.
You can reach me by phone or email:


+972 52-548-6969

, @ Q c

Posts: 6,128 | Comments: 45,550

filter by tags archive

Handling entities validations in RavenDB

time to read 15 min | 2926 words

This post came out of a stack overflow question. The user had the following code:

   1: public void StoreUser(User user)
   2: {
   3:     //Some validation logic
   4:     if(string.IsNullOrWhiteSpace(user.Name))
   5:         throw new Exception("User name can not be empty");
   7:     Session.Store(user);
   8: }

But he noted that this will not work for other approaches, such as this:

   1: var u1 = Sesion.Load<User>(1);
   2: u1.Name = null; //change is tracked and will persist on the next save changes
   3: Session.SaveChanges();

This is because RavenDB tracks the entity and will persist it if there has been any changes when SaveChanges is called.

The question was:

Is there someway to get RavenDB to store only a snapshot of the item that was stored and not track further changes?

The answer is, as is often the case if you run into hardship with RavenDB, you are doing something wrong. In this particular case, that wrongness is the fact that you are trying to do validation manually. This means that you always have to remember to call it, and that you can’t use a lot of the good stuff that RavenDB gives you, like change tracking. Instead, RavenDB contains the hooks to do it once, and do it well.

   1: public class ValidationListener : IDocumentStoreListener
   2: {
   3:     readonly Dictionary<Type, List<Action<object>>> validations = new Dictionary<Type, List<Action<object>>>();
   5:     public void Register<T>(Action<T> validate)
   6:     {
   7:         List<Action<object>> list;
   8:         if(validations.TryGetValue(typeof(T),out list) == false)
   9:             validations[typeof (T)] = list = new List<Action<object>>();
  11:         list.Add(o => validate((T) o));
  12:     }
  14:     public bool BeforeStore(string key, object entityInstance, RavenJObject metadata, RavenJObject original)
  15:     {
  16:         List<Action<object>> list;
  17:         if (validations.TryGetValue(entityInstance.GetType(), out list))
  18:         {
  19:             foreach (var validation in list)
  20:             {
  21:                 validation(entityInstance);
  22:             }
  23:         }
  24:         return false;
  25:     }
  27:     public void AfterStore(string key, object entityInstance, RavenJObject metadata)
  28:     {
  29:     }
  30: }

This will be called by RavenDB whenever we save to the database. We can now write the validation / registration code like this:

   1: var validationListener = new ValidationListener();
   2: validationListener.Register<User>(user=>
   3:     {
   4:         if (string.IsNullOrWhiteSpace(user.Name))
   5:             throw new Exception("User name can not be empty");
   6:     });
   7: store.RegisterListener(validationListener);

And that is all that she wrote.



exists same easy way to use nhibernate validator?


And there is also the question of whether "validation by exception" is a proper way of doing validation...

Alexander Nyquist

@ugo Yes, check out IPreInsertEventListener and IPreUpdateEventListener.


Oh there goes another chunk of code. I've been manually validating things with Data Annotations, this lets me get rid of that step altogether.

However, is it possible to register a generic validator? I have a single Validator already that takes any object and checks the data annotations.

David Boike

This is great! I've finished a RavenDB project and had no idea this feature existed!

It does raise one question for me though.

I could see implementing a custom user validation exception that would store all the different issues with a model, so you could easily catch that exception and translate it to a ValidationSummary type of control in a web application.

However, if you're using a one session per request model, and you trap the exception, the SaveChanges() is still going to occur. How do you deal with that? Does the Listener just make it so that the update to that model never took place, but all the other activity on the pages proceeds normally?


This works fine. The interface is just to ensure that objects that do not need validation are skipped.

public interface IPersistValidated

public class ValidationListener : IDocumentStoreListener
    public bool BeforeStore(string key, object entityInstance, RavenJObject metadata, RavenJObject original)
        if (entityInstance is IPersistValidated)
            var context = new ValidationContext(entityInstance, null, null);

            Validator.ValidateObject(entityInstance, context);
        return true;

    public void AfterStore(string key, object entityInstance, RavenJObject metadata)

Beware, this is a 1 minute experiment.


David: The exception is thrown at SaveChanges(), so nothing is stored.


The example code is for Data Annotations, and the validated class is:

public class User : IPersistValidated
    public string Username { get; set; }
    public PasswordString Password { get; set; } // just class so manage hashing
Ayende Rahien

Rangoric, Certainly, if you noted, I added code to handle typing explicitly.

Ayende Rahien

David, If an exception is raised from the BeforeStore method, SaveChanges will NOT happen.


store.RegisterListener(validationListener); ???

I have no such RegisterListener. Maybe this is for a newer version? My version is 960

Ayende Rahien

Uwe, It is there, it isn't on the IDocumentStore interface, but it is on the DocumentStore impl.


But there are other types of validations that involves other object instances at some the execution context. Let's suppose that in a Nerd Dinner like app, you cannot schedule ther same dinner twice.

In this case, we cannot "register" the validation, because it's in a business service.


Ayende Rahien

Daniel, There is generally a distinction between business style validation (you can't order more than 5 items unless you have a Gold membership, or you can't schedule an event twice) vs. data validation (field is not null, age is valid, etc). This post talks about data validation, not business validation.


Sure. Post a comment here because didn't find an approach to the business validation context.

In the case that a existing Dinner is edited and then validated before SaveChanges, I think that we could have a "RestoreState" feature (something like memento pattern).

Don't you think that could be useful?

Ayende Rahien

Daniel, What do you need a RestoreState feature? Just don't save the diner


The dinner was loaded from database and edited, but some business validation over it throws exception. This exception is handled at the Application Level, and because of this, the end of the request calls de SaveChanges. I used the memento pattern to restore the state of the entity at the context of the exception handling to prevent an update at the SaveChanges. Maybe there is a better way to handle this scenario. For example, using a TransactionScope around this operation. In this case, RavenDB could have a VoteCommit and VoteRollback to control SaveChanges (similar to ActiveRecord.TransactionScope)

Comment preview

Comments have been closed on this topic.


  1. The worker pattern - about one day from now

There are posts all the way to May 30, 2016


  1. The design of RavenDB 4.0 (14):
    26 May 2016 - The client side
  2. RavenDB 3.5 whirl wind tour (14):
    25 May 2016 - Got anything to declare, ya smuggler?
  3. Tasks for the new comer (2):
    15 Apr 2016 - Quartz.NET with RavenDB
  4. Code through the looking glass (5):
    18 Mar 2016 - And a linear search to rule them
  5. Find the bug (8):
    29 Feb 2016 - When you can't rely on your own identity
View all series


Main feed Feed Stats
Comments feed   Comments Feed Stats