Click here to Skip to main content
Click here to Skip to main content

Add custom validation to data columns in ADO.NET

, 14 Nov 2005
Rate this:
Please Sign up or sign in to vote.
This article describes how to add custom validation to a data column in ADO.NET.

Introduction

Currently, the DataTable has minimal support for custom validation in data columns when creating extended data columns. This article shows how to add regular expression validation capabilities to the data columns by extending the ADO.NET DataColumn. The DataColumn can be validated whenever it undergoes a change, against a validator.

Motivation

The ADO.NET DataColumn supports unique values by the implementation of a unique constraint, but how do we add custom validation which may be governed by business rules (such as positive integers or some regular expression validation)? One option is to use a custom constraint derived from the abstract Constraint class, but this is an arduous task.

It hence follows that we need some extensions to the DataColumn. The extended data column does exactly this and allows the user to supply his own validation logic using a validator class, which returns whether the validation occurred successfully or not.

The backbone of the solution is the DataColumnEx class, which takes in a DataTable, name and a validator as parameters to the constructor.

IValidator Interface

All validators which participate in the validation of the data in the datacolumnEx need to implement the IValidator interface, which has a single method IsValid.

namespace DataColumnEx
{
    /// <summary>
    /// Base interface which will be implemented
    /// by classes to validate the values
    /// in the extended datacolumn
    /// </summary>

    public interface IValidator
    {
       bool IsValid(object value);
    }
}

The validator takes in an object by performing rules specified and returns a boolean indicating if the validation is successful. As is obvious, the validation can range from something as simple as restricting values to positive integers to something more complex that encapsulates a business rule.

The encapsulation of any business logic in a separate class decouples the business logic governing the validation from the extended data column.

DataColumnEx class

The DataColumnEx takes in a class of type IValidator in its Validator property. The DataColumnEx subscribes to the ColumnChanged event of the table to which it belongs (as specified in the constructor) and invokes the validator there. The DataColumnEx class also has a property RejectChangesOnError indicating if changes made to the row should not be effective.

using System;
using System.Data;

namespace DataColumnEx
{

    /// <summary>
    /// Extended data column which Inherits from data column and adds the
    /// capability to validate data as per rules specified in the validator
    /// </summary>

    public class DataColumnEx : DataColumn
    {

        private IValidator m_validator;
        private DataTable m_table;
        private bool m_rejectChangesOnError;
        private ResourceMgr m_resMgr = 
                new ResourceMgr("DataColumnEx.ErrorStrings");
    
        /// <summary>
        /// Overloaded Constructor
        /// </summary>
        /// <param name="table">Table to which this column belongs</param>
        /// <param name="name">Name of the column</param>
        /// <param name="validator">Validator 
        ////       to validate the proposed value in the column</param>
    
        public DataColumnEx(DataTable table, string name, IValidator validator)
        {
            ColumnName = name;
            m_validator = validator;
            m_table = table;
            DataType = typeof(string);

            if (m_table != null)
            {
                m_table.ColumnChanged += 
                   new DataColumnChangeEventHandler(OnColumnChanged);
            }
        }

        /// <summary>
        /// Overloaded Constructor
        /// </summary>
        /// <param name="table">Table to which this column belongs</param>
        /// <param name="name">Name of the column</param>
        /// <param name="validator">Validator to validate
        ///        the proposed value in the column</param>
        /// <param name="columnType">Data type of this column</param>
        
        public DataColumnEx(DataTable table, string name, 
                   IValidator validator, Type columnType)

        {
            ColumnName = name;
            m_validator = validator;
            m_table = table;
            DataType = columnType;

            if (m_table != null)
            {
                //Subscribe to the column changed event
                m_table.ColumnChanged += 
                  new DataColumnChangeEventHandler(OnColumnChanged);
            }
        }

        /// <summary>
        /// Sets or gets the validator which will validate the proposed value
        /// </summary>

        public IValidator Validator
        {
            get { return m_validator; }
            set { m_validator = value; }
        }
        
        /// <summary>
        /// Sets or gets whether the changes made to the row
        ///     should be rejected if the validation
        ///     fails for the column
        /// </summary>
        public bool RejectChangesOnError
        {
            get { return m_rejectChangesOnError; }
            set { m_rejectChangesOnError = value; }
        }

        private void OnColumnChanged(object sender, DataColumnChangeEventArgs e)
        {
            if (e.Column == this)
            {
                object obj = e.ProposedValue;
        
                //If not valid,then reject changes if the flag is set
                if (!m_validator.IsValid(obj))
                {
                    if (m_rejectChangesOnError)
                        e.Row.RejectChanges();
                    throw new Exception(m_resMgr.GetString("S_ERR_INVALID_DATA"));
                }
            }
        }
    }
}

Conclusion

I have presented some very elementary scenarios in which the data column can be validated to restrict input. This idea may be extended to more complex scenarios to suit the requirements of the business necessity at hand.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Karthik Krishnaswami
Web Developer
India India
Karthik works as a technical lead at Symphony Services,Bangalore.He has been actively involved in designing and developing complex applications on Microsoft Technologies for over 7 years.

Comments and Discussions

 
GeneralRejectChanges will reject all the changes to the row! PinmemberJason Law1-Apr-08 5:23 
QuestionVC++.net 2003 and excel 2002 Pinmemberminad_78624-Nov-06 1:57 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.140814.1 | Last Updated 14 Nov 2005
Article Copyright 2005 by Karthik Krishnaswami
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid