NHibernate Validator
Validation is one of those things that goes hand in hand with data access. I guess it is not much of surprise that one of the contrib projects for NHibernate is extensive validation support.
True, there are about as many validation frameworks as there are ToDo applications, but NHibernate Validator bring something special to the table, it brings tight integration with NHibernate itself and:
“…multi-layered data validation, where constraints are expressed in a single place and checked in various different layers of the application.”
I am sorry, I just love this quote. :-)
Anyway, let me jump right it and show you what I mean by that.
We can initialize the validation framework using several ways, but probably the easier would be:
var configuration = new Configuration() .Configure("hibernate.cfg.xml"); var engine = new ValidatorEngine(); engine.Configure(new NHVConfigurationBase()); ValidatorInitializer.Initialize(configuration, engine);
And now, all we need to do is set the validation attributes on our the entities, and we are done:
[NotNullNotEmpty] [Length(25)] public virtual string Title
At this point, several very interesting things are going to happen. First, if we ask NHibernate to generate the schema for us we are going to get the following:
Before using NHV | After using NHV |
create table Blogs ( Id INT IDENTITY NOT NULL, Title NVARCHAR(255) null, Subtitle NVARCHAR(255) null, AllowsComments BIT null, CreatedAt DATETIME null, primary key (Id) ) |
create table Blogs ( Id INT IDENTITY NOT NULL, Title NVARCHAR(25) not null, Subtitle NVARCHAR(255) null, AllowsComments BIT null, CreatedAt DATETIME null, primary key (Id) ) |
Note the title column, where before we used the default values (null and 255) we are now using the values defined in the validation scheme. That is what we mean when we say that we can get pretty multi layered data validation.
That is not the end of it, however, NHibernate Validator is hooking up into the NHibernate engine, and if we tried to save the following, we will get a validation exception:
s.Save(new Blog { Title = new string('*',255), });
And, obviously, we support a way to extract all the validation errors from the entity:
var invalidValues = engine.Validate(blog); foreach (var invalidValue in invalidValues) { Console.WriteLine( "{0}: {1}", invalidValue.PropertyName, invalidValue.Message); }
NHibernate Validator also support all the other things that you would expect from validation frameworks, the ability to create your own constraints (including the ability to embed them in the database schema!), i18n, XML only configuration, if you want to keep your entities clear of attributes, etc.
This has been truly just a tidbit, to whet your appetite.
You can learn more about NH Validator here.
Comments
A nice start :-)
How would you add validation which cannot be expressed as a .NET attribute. For example an invariant which is based on an object's state.
"Signature required if the order.Status == OrderStatus.Approved"
for the last project i evaluated it, but compared to castle validator its harder to extend, cause di doesn't work nice. what are your thoughts when comparing it with castle validator?
One validation message needs the ability to invalidate multiple property names.
Example: A must be greater than B
It's one rule. It invalidates both A and B, but it's still only one rule and should ultimately display only a single error message.
I see this again and again in every validation framework and it drives me mad.
Secondly, is this another direct port from Java? I see references like "beanName" all over the source code. I thought we'd finally moved beyond this in the .NET world and were able to stand on our own?
About 6 months ago, I invested several days looking into this framework and was very impressed.
Since I am a bit rusty on the details, I was hoping you could remind how one would use this framework to do validation based on property comparisons. For instance, say property A is only valid in a certain range and that range depends on the value of property B. Typically I have done such validation with declarative/attribute based validation frameworks within the body of a function, and somehow hooking that function into the validation process.
This question is in the same vain as Peter Morris'
Peter,
Then you create a custom validator.
Sarong,
I am not going to get into that. The main benefit of NHV is that it ties strongly into NH.
Bryan,
I am not going to touch on that. Validation framework design is not something that I did.
I can comment on that it seems workable to invalidate one of them or to create two error messages, and that adding that would significantly complicate the design of most other scenarios.
And yes, this is a port of a Java project, there is no need to reinvent the wheel if it is already there and moving.
Merritt,
And in the same vain, you write a custom validator. There are docs about doing just that, and you can also look here:
msmvps.com/.../...he-code-with-external-rules.aspx
I wouldn't want to write a custom class for something like A < B. I presume there is some kind of interface the class can implement to return broken constraints or something?
I'll ask the guy who wrote the blog entry you posted a link to :-)
How this relate to the <column element when generating schemas.
oops, the column element
If you want to know from technical perspective, NHV will intercept the schema generation and add the validation to the schema itself
Peter,
Of the top of my head, I don't think that you can implement an interface, mostly because it hurt the poconess of the class
Adding an interface to a class to return a list of errors is still POCO in my opinion. NH has call back interface options for classes doesn't it? That isn't considered breaking the POCOness, or is it?
I like the look of the validator, but without the ability to have the class itself define more complicated invariants you'll end up writing a class per rule which can only be used on a specific entity type. In addition to that you sometimes need to access private state in order to validate.
I posted a comment on that blog you linked to but it hasn't been approved yet, we'll see if it does or not :-)
Peter,
It creates a dependency between the class and the framework, that breaks POCO
And while NH has such interfaces, they are considered deprecated, and their use is frowned upon.
Hi Ayende
Oh I understand the misunderstanding between us now :-) Maybe it would be better if I had written
"I presume there is some kind of interface SOME VALIDATION class can implement to return broken constraints or something?"
By this I mean that instead of writing a .NET attribute class which performs a single validation, for the complex rules I would write something like
public class Validator <person
{
}
or
public class PersonValidator : IValidator <person
{
}
Where all validation rules may be added? The big problem with validation though is when a rule depends upon private state.
private string password;
public string Password
{
set { password = value; }
}
I presume the validator attribute may also be applied to a private member?
Cheers :-)
Pete
"Of the top of my head, I don't think that you can implement an interface, mostly because it hurt the poconess of the class"
I see what you are saying, but I consider a lot of validation to be a domain concern, so I want the option of having an object controlling many aspects of its own validation (its won invariants in particular).
Comment preview