为 ADO.NET 中的数据列添加自定义验证






3.67/5 (5投票s)
2005 年 11 月 14 日
2分钟阅读

56703

518
本文档描述了如何在 ADO.NET 中为数据列添加自定义验证。
引言
目前,DataTable
在创建扩展数据列时,对数据列中的自定义验证的支持非常有限。本文档展示了如何通过扩展 ADO.NET DataColumn
来为数据列添加正则表达式验证功能。DataColumn
可以在其发生变化时,通过验证器进行验证。
动机
ADO.NET DataColumn
通过实现唯一约束来支持唯一值,但是我们如何添加自定义验证,这些验证可能由业务规则控制(例如正整数或某些正则表达式验证)? 一种选择是使用从抽象 Constraint
类派生的自定义约束,但这是一项繁琐的任务。
因此,我们需要对 DataColumn
进行一些扩展。扩展数据列 正是这样做的,它允许用户使用验证器类提供自己的验证逻辑,该验证器类返回验证是否成功。
该解决方案的核心是 DataColumnEx
类,它在构造函数中接收 DataTable
、名称和验证器作为参数。
IValidator 接口
所有参与 datacolumnEx
数据验证的验证器都需要实现 IValidator
接口,该接口具有一个名为 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);
}
}
验证器通过执行指定规则接收一个对象,并返回一个布尔值,指示验证是否成功。 显而易见的是,验证的范围可以从简单地限制值到正整数,到封装业务规则的更复杂的内容。
将任何业务逻辑封装到单独的类中,可以将控制验证的业务逻辑与扩展数据列分离。
DataColumnEx 类
DataColumnEx
在其 Validator
属性中接收一个类型为 IValidator
的类。 DataColumnEx
订阅其所属表(如在构造函数中指定)的 ColumnChanged
事件,并在那里调用验证器。 DataColumnEx
类还具有一个属性 RejectChangesOnError
,指示对行所做的更改是否应该被拒绝。
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"));
}
}
}
}
}
结论
我提供了一些非常基本的场景,可以在其中验证数据列以限制输入。 这个想法可以扩展到更复杂的场景,以适应手头的业务需求。