Creating validator classes

In the previous recipe, we saw how to decorate our entity classes with NHibernate Validator. A better practice is to extract your validation rules to separate classes and avoid this dependency. In this recipe, we'll show you how to create validator classes, as well as an alternative method for configuring NHibernate Validator.

Getting ready

Complete the Eg.Core model and mappings from Chapter 1, The Configuration and Schema.

How to do it…

  1. Create a new class library project named Eg.ClassValidation.
  2. Add a reference to the Eg.Core model.
  3. Install the NHibernate Validator package using NuGet Package Manager Console by executing the following command:
    Install-Package NHibernate.Validator
    
  4. Add the following ProductValidation class:
    public class ProductValidator : ValidationDef<Product>
    {
    
      public ProductValidator()
      {
        Define(p => p.Name)
          .NotNullableAndNotEmpty()
          .And.MaxLength(255);
    
        Define(p => p.Description)
          .NotNullableAndNotEmpty();
    
        Define(p => p.UnitPrice)
          .GreaterThanOrEqualTo(0M)
          .WithMessage("Unit price can't be negative."); 
    
      }
    
    }
  5. Create a new console application named Eg.ClassValidation.Runner.
  6. Install the NHibernate, NHibernate Validator, and log4net packages to Eg.ClassValidation.Runner project using NuGet Package Manager Console by running the following command:
    Install-Package NHibernate
    Install-Package NHibernate.Validator
    Install-Package log4net
    
  7. Set up an App.config with the standard log4net and hibernate-configuration sections, following the Configuring NHibernate with App.config and Configuring NHibernate logging recipes from Chapter 1, The Configuration and Schema.
  8. Add a new class named BasicSharedEngineProvider using the following code:
    public class BasicSharedEngineProvider : ISharedEngineProvider
    {
    
      private readonly ValidatorEngine ve;
    
      public BasicSharedEngineProvider(ValidatorEngine ve)
      {
        this.ve = ve;
      }
    
      public ValidatorEngine GetEngine()
      {
        return ve;
      }
    
      public void UseMe()
      {
        Environment.SharedEngineProvider = this;
      }
    
    }
  9. In Program.cs, use the following code:
    private static void Main(string[] args)
    {
      XmlConfigurator.Configure();
      var log = LogManager.GetLogger(typeof (Program));
    
      SetupNHibernateValidator();
    
     var nhibernateConfig = new Configuration().Configure();
     nhibernateConfig.Initialize(); 
     ISessionFactory sessionFactory = nhibernateConfig.
     BuildSessionFactory();
     var schemaExport = new SchemaExport(nhibernateConfig);
     schemaExport.Execute(false, true, false);
     var junk = new Product
     {
       Name = "Spiffy Junk",
       Description = string.Empty,
       UnitPrice = -1M
     };
    
      var ve = Environment.SharedEngineProvider.GetEngine();
      var invalidValues = ve.Validate(junk);
      foreach (var invalidValue in invalidValues)
      {
        log.InfoFormat("{0} {1}",
          invalidValue.PropertyName,
          invalidValue.Message);
      }
    
    }
    
    private static FluentConfiguration GetNhvConfiguration()
    {
      var nhvConfiguration = new FluentConfiguration();
      nhvConfiguration
        .SetDefaultValidatorMode(ValidatorMode.UseExternal)
        .Register(Assembly.Load("Eg.ClassValidation")
                    .ValidationDefinitions())
        .IntegrateWithNHibernate
        .ApplyingDDLConstraints()
        .And.RegisteringListeners();
      return nhvConfiguration;
    }
    
    private static ValidatorEngine GetValidatorEngine()
    {
      var cfg = GetNhvConfiguration();
      var validatorEngine = new ValidatorEngine();
      validatorEngine.Configure(cfg);
      return validatorEngine;
    }
    
    private static void SetupNHibernateValidator()
    {
      var validatorEngine = GetValidatorEngine();
      new BasicSharedEngineProvider(validatorEngine).UseMe();
    }
  10. Build and run your application.

How it works…

In this recipe, we have separated our validation rules into a separate class named ProductValidation. Just as we did in our previous recipe, we have decided that each valid Product must have a non-null, non-empty Name, a Description (not more than 255 characters long), and a non-negative UnitPrice.

As we learned in the previous recipe, we use an ISharedEngineProvider to locate our validation engine.

Unlike the previous recipe, we use the loquacious, or fluent, syntax to configure NHibernate Validator.

We validate our junk Product. It fails two validation rules. First, the Description can't be empty. Second, the UnitPrice can't be negative. As we see in the log4net output, we get the following validation error messages:

Description may not be null or empty

UnitPrice can't be negative

There's more…

We can also use NHibernate Validator to validate an entire object graph. Let's take our Movie entity as an example. Suppose we want to ensure that the movie entity is valid, as well as all of its ActorRole children. Our validation class would appear as shown:

Define(m => m.Director)
  .NotNullableAndNotEmpty()
  .And.MaxLength(255);

Define(m => m.Actors)
  .HasValidElements();

The HasValidElements runs the ActorRole validation rules on each object in the Actors collection.

See also

  • Property validation with attributes
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
52.14.39.59