CHAPTER 9
A proper data framework allows you to validate entities against business rules and invalid values. NHibernate Validator can be used precisely for that. It is a general purpose validation framework that integrates tightly with NHibernate.
The best way to get it is through NuGet as NHibernate.Validator:

Another way to get it is by downloading it from SourceForge: http://sourceforge.net/projects/nhcontrib/files/NHibernate.Validator.
You can also get the source code from GitHub: https://github.com/darioquintana/NHibernate-Validator.
Once you have set it up, you must decide how you want to apply validation. NHibernate Validator supports configuring validation:
You see, some things in the NHibernate world never change!
To use NHibernate Validator, we need to set up the framework to work together with NHibernate. This is achieved through a listener that performs validation on entities when they are about to be saved or updated. If any validation error occurs, an InvalidStateException is thrown. You can call its GetInvalidValues() to find out exactly what is wrong and fix it.
We integrate NHibernate Validator with the NHibernate Configuration instance before building any session factory. The following shows how to do it with loquacious configuration:
Tip: Add using statements for the NHibernate.Validator.Cfg.Loquacious, NHibernate.Validator, and NHibernate.Validator.Engine namespaces.
But it is also possible to do it with XML configuration; just make sure you add the following content to your App/Web.config file:
<configuration> <configSections> <!-- … --> <section name="nhv-configuration" type="NHibernate.Validator.Cfg.ConfigurationSectionHandler, NHibernate.Validator" /> </configSections> <nhv-configuration xmlns="urn:nhv-configuration-1.0"> <property name="apply_to_ddl">true</property> <property name="autoregister_listeners">true</property> <property name="default_validator_mode">UseExternal</property> <mapping assembly="Succinctly.Model"/> </nhv-configuration> <!-- … --> </configuration> |
And include the following code:
XmlConfiguration xmlConfiguration = new XmlConfiguration(); ValidatorEngine validatorEngine = NHibernate.Validator.Cfg.Environment.SharedEngineProvider.GetEngine(); validatorEngine.Configure(validatorConfiguration);
cfg.Initialize(validatorEngine); |
If you want, you can also have IntelliSense for the NHibernate Validator XML. If you added NHibernate Validator from NuGet, just copy the nhv-configuration.xsd and nhv-mapping.xsd files from the packages\NHibernate.Validator.1.3.2.4000\lib\Net35 folder to the C:\Program Files (x86)\Microsoft Visual Studio 10.0\Xml\Schemas or C:\Program Files (x86)\Microsoft Visual Studio 11.0\Xml\Schemas, depending on your Visual Studio version. See XML Configuration for more information on this. If you haven’t used NuGet, you will have to extract these files from the distribution .zip file or the source GitHub repository.
Next, we need to configure validations for our entities. First, using code:
The CustomerValidation class inherits from NHibernate.Validator.ValidationDef<T> and is defined as follows:
And the same rules, except the ValidateInstanceBy custom validation can be defined in attributes like this:
|
{ [NotNullNotEmpty(Message = "The customer name is mandatory")] [Length(Max = 50, Message = "The customer name can only have 50 characters")] public virtual String Name { get; set; }
[NotNullNotEmpty(Message = "The customer email is mandatory")] [Email(Message = "The customer email must be a valid email adddress")] [Length(Max = 50, Message = "The customer email can only have 50 characters")] public virtual String Email { get; set; }
[NotNull(Message = "The customer address is mandatory")] public virtual Address Address { get; set; } } |
Tip: You need to reference the namespace NHibernate.Validator.Constraints.
You have to change the Validator configuration to use attributes:
Finally, to use XML, you need to add a file named Customer.nhv.xml, place it in the same location as the Customer class, and mark it as an embedded resource, just as we saw on XML Mappings:
<?xml version="1.0" encoding="utf-8" ?> <nhv-mapping namespace="Succinctly.Model" assembly="Succinctly.Model" xmlns="urn:nhibernate-validator-1.0"> <class name="Customer"> <property name="Name"> <length max="50" message="The customer name can only have 50 characters"/> <notnull-notempty message="The customer name is mandatory"/> </property> <property name="Email"> <length max="50" message="The customer email can only have 50 characters"/> <notnull-notempty message="The customer email is mandatory"/> <email message="The customer email must be a valid email adddress"/> </property> <property name="Address"> <not-null message="The customer address is mandatory"/> </property> </class> </nhv-mapping> |
You also have to tell NHibernate Validator to look for embedded resources explicitly:
For some properties, we are using the built-in validation mechanisms such as NotNullableAndNotEmpty and IsEmail whereas, in other cases, we are performing a custom check (the Address reference). Out-of-the-box validators include:
Included Validators
Validator | Type | Description |
Digits/digits/decimalmax/ Decimalmin | Numbers, Strings | Validates the maximum number of digits/digits and fractional digits |
FilePathExists/fileexists | Strings | Checks if a file path exists |
GreaterThanOrEqualTo/min | Numbers | Checks if a number is greater or equal to a given value |
HasValidElements/isvalid | Collections | Checks if all of the collections’ elements are valid recursively |
IncludedBetween/range | Numbers | Checks if a number is included within a range (inclusive) |
IsCreditCardNumber/ Creditcardnumber | Strings | Checks if a string matches a credit card number |
IsEAN/ean | Numbers, Strings | Checks if a string or number matches an EAN |
IsEmail/email | Strings | Checks if a string is a valid e-mail address |
IsFalse/assertfalse | Booleans | Checks that a boolean is false |
IsIBAN/iban | Strings | Checks that a string is a valid IBAN |
IsInTheFuture/future | Dates and Times | Checks that a date is in the future |
IsInThePast/past | Dates and Times | Checks that a date is in the past |
IsIP/ipaddress | Strings | Checks that a string is a valid IP address |
IsNumeric/digits | Strings | Checks that a string is a valid number |
IsTrue/asserttrue | Booleans | Checks that a boolean is true |
IsValid/valid | Entities | Checks that an entity is valid recursively |
LengthBetween/length | Strings | Checks that the length of a string is contained within given limits |
LessThanOrEqualTo/max | Numbers | Checks that a number is less or equal to a given value |
MatchWith/pattern | Strings | Check that a string matches a regular expression |
MaxLength/length | Strings | Checks the maximum length of a string |
MaxSize/size | Collections | Checks the maximum size of a collection |
MinLength/length | Strings | Checks the minimum length of a string |
MinSize/size | Collections | Checks the minimum size of a collection |
NotEmpty/not-empty | String, Collections, GUIDs | Checks if a string/collection/GUID is not empty |
NotNullable/not-null | Any | Checks that a value is not null |
NotNullableAndNotEmpty/ notnull-notempty | String, Collections | Checks that a string/collection is not null and contains values |
Satisfy | Any | A custom rule, as a lambda expression |
SizeBetween/size | Collections | Checks that a collection’s size is contained within given limits |
Whitih/range | Numbers | Checks if a number is included within a range (exclusive) |
Some of these validations can be implemented on the database in the form of the maximum length for a string and as check constraints. In this case, if NHibernate Validator is integrated with NHibernate using the ApplyingDDLConstraints/apply_to_ddl option, when the model is generated, it will include these checks.
Finally, you can implement your own attributes by inheriting from EmbeddedRuleArgsAttribute and implementing a couple of interfaces:
This validator checks that a number is even, and can even change the property to which it is applied in order to add this check at the database level. That is what the IPropertyConstraint is for and you don’t have to implement it because, sometimes, a validation cannot be expressed easily in database terms.
To add the attribute by XML, add a <rule> tag to Customer.nhv.xml that references your custom attribute:
<property name="SomeIntegerProperty"> <rule attribute="IsEvenAttribute"> <param name="Message" value="Number is odd"/> </rule> </property> |
Finally, let me just say this: Validation occurs when NHibernate tries to save an entity with validations attached but you can also validate explicitly:
InvalidValue[] invalidValuesObtainedExplicitly = validatorEngine.Validate(entity); |
And that’s just about it. Happy validating!