Complex validation

38 views
Skip to first unread message

Peter Morris

unread,
Mar 27, 2012, 3:39:08 AM3/27/12
to nhusers
I've been reading through a page describing NHibernate Validator. I
was wondering how I would add a very class specific validation, as
creating an attribute seems to be the wrong way to write something so
specific. For example

Description: Start date cannot be before previous end date
Psuedo code: this.Index == 0 or this.StartDate >=
this.Parent.Children[this.Index - 1].EndDate

What would be the best way to implement this kind of thing?

Ricardo Peres

unread,
Mar 27, 2012, 6:36:11 AM3/27/12
to nhu...@googlegroups.com
There is a not very known interface called NHibernate.Classic.IValidatable that describes a single method, Validate. If your entities implement this interface, this method will be called upon Save or Update, and you can perform your own validation there. If the entity is not valid, you can throw an exception and the saving will be aborted.

RP

Peter Morris

unread,
Mar 28, 2012, 3:23:46 AM3/28/12
to nhusers
Thanks, that's just what I needed :) However I don't like the idea of
throwing an exception because then you only get the first error rather
than a collection of all errors. Or will I have to implement
something myself?

Ricardo Peres

unread,
Mar 28, 2012, 7:26:44 AM3/28/12
to nhu...@googlegroups.com
Well, you can create your own Exception-derived class and expose all errors as properties. Or you can use the standard Exception.Data collection.

RP

On Tuesday, March 27, 2012 8:39:08 AM UTC+1, Peter Morris wrote:

allan....@gmail.com

unread,
Mar 28, 2012, 12:17:39 PM3/28/12
to nhu...@googlegroups.com
Pretty easy to do with NH Validator.  There is one catch if you lazy load during validation (because of the late event it is running in), it will lead to the DefaultFlushEventListener throwing an exception.  It isn't necessary for it to do so & it will not block persistence if you ignore it using the event listener code below.

public class YourObjectValidationDef : ValidationDef<YourObject> {
   
public YourObjectValidationDef() {
    this.ValidateInstance.By((obj, context) => {
        context.DisableDefaultError();
        bool valid = (obj.Index == 0 || obj.StartDate >= obj.Parent.Children[obj.Index - 1].EndDate);
        if (!valid)
            context.AddInvalid("Add your error message here", "StartDate");
        return flag;
    });
}


    public class FlushFixEventListener : DefaultFlushEventListener {

        public override void OnFlush(FlushEvent @event) {
            try {
                base.OnFlush(@event);
            }
            catch (AssertionFailure) {
                // throw away
            }
        }
    }
Reply all
Reply to author
Forward
0 new messages