数据集中的数据验证代码应该写在什么位置?

数据集中的数据验证可以通过多种方式来完成:

(1)通过主键与唯一条件约束来进行唯一性验证;

(2)通过外键约束来确保数据引用完整性;

(3)使用字段的相关属性,如AllowDBNull、MaxLength与Unique来辅助完成数据验证操作;

(4)自行替应用程序书写数据验证代码,以便在字段和记录变更事件期间检查数据。

前提:在DataGridView控件中修改字段(不包括新行)。

在默认状态下,每次变更一个字段时将会顺序引发4个事件:首先会引发被更改字段的ColumnChanging与ColumnChanged事件,接着是RowChanging与RowChanged事件。值得注意的是,当修改完一个字段后,焦点离开该字段,但仍在该字段所在行时,仅引发ColumnChanging与ColumnChanged事件,此时可继续修改该行的其它字段,并引发相应事件。一旦焦点离开该行,若焦点离开之前刚修改完一个字段值,不管焦点是否仍落在该列,都将顺序引发4个事件;否则引发被修改行的RowChanging与RowChanged事件。

Row.BeginEdit()会将记录置于编辑模式。在此模式中,事件将暂时停止以便在不触发字段约束的情况下,对一个记录的多个字段进行修改。而等到调用Row.EndEdit()时,又会触发约束。

当用户修改数据绑定控件的数据时(如DataGridView控件),会隐式调用被修改行的BeginEdit(),当焦点离开该行时又会隐式调用该行的EndEdit(),从而触发字段约束。(如AllowDBNull、Unique约束等)

字段值改变会调用4个改变事件,即ColumnChanging、ColumnChanged、RowChanging与RowChanged事件,这时有一个问题,如果自行书写数据验证代码,又该写在的哪个事件中呢?

我写了一段试验代码,对不同的执行结果进行了分析。

View Code
        private void DataTableTest4_Load(object sender, EventArgs e)
{
string sql = "select * from dbo.客户";
tbl = Rabbit.DBUtility.DBHelperSql.Query(sql).Tables[0];
tbl.Columns[0].AllowDBNull = false;
dataGridView1.DataSource = tbl;
tbl.Columns["公司名称"].AllowDBNull = false;
tbl.Columns["公司名称"].DefaultValue = "新世纪公司";

tbl.ColumnChanging += new DataColumnChangeEventHandler(tbl_ColumnChanging);
tbl.ColumnChanged += new DataColumnChangeEventHandler(tbl_ColumnChanged);
tbl.RowChanging += new DataRowChangeEventHandler(tbl_RowChanging);
tbl.RowChanged += new DataRowChangeEventHandler(tbl_RowChanged);
}

private void tbl_ColumnChanging(object sender, DataColumnChangeEventArgs e)
{
//e.Row.EndEdit();
//e.Row.CancelEdit();
Console.WriteLine(e.Row.RowState.ToString());
}

private void tbl_ColumnChanged(object sender, DataColumnChangeEventArgs e)
{
//e.Row.CancelEdit();
//e.Row.EndEdit();
Console.WriteLine(e.Row.RowState.ToString());
}

private void tbl_RowChanging(object sender, DataRowChangeEventArgs e)
{
//e.Row.CancelEdit();
//e.Row.EndEdit();
Console.WriteLine(e.Row.RowState.ToString());
}

private void tbl_RowChanged(object sender, DataRowChangeEventArgs e)
{
//e.Row.EndEdit();
//e.Row.CancelEdit();
Console.WriteLine(e.Row.RowState.ToString());
}

操作:修改DataGridView控件某行(该行不是新行)某列的值,然后焦点离开该行。

结果:见下面8个表

表格说明:第1行表示事件,第2行表示在对应事件中调用行的哪个方法,第3行表示事件的执行顺序,第4行表示每次执行对应事件时行的状态,第5行表示执行结果。

ColumnChanging

ColumnChanged

RowChanging

RowChanged

EndEdit()

 

 

 

1/4

5

2/6

3/7

Unchanged/ Modified

Modified

Unchanged/ Modified

Modified/Modified

修改成功

 

ColumnChanging

ColumnChanged

RowChanging

RowChanged

 

EndEdit()

 

 

1

2/5

3

4

Unchanged

Unchanged/ Modified

Unchanged

Modified

修改成功

 

ColumnChanging

ColumnChanged

RowChanging

RowChanged

 

 

EndEdit()

 

1

2

出现异常

 

Unchanged

Unchanged

 

 

不能在RowChanging中调用EndEdit(),同时也不能调用CancelEdit()

 

ColumnChanging

ColumnChanged

RowChanging

RowChanged

 

 

 

EndEdit()

1

2

3

4

Unchanged

Unchanged

Unchanged

Modified

修改成功

 

ColumnChanging

ColumnChanged

RowChanging

RowChanged

 

 

 

 

1

2

3

4

Unchanged

Unchanged

Unchanged

Modified

修改成功

 

ColumnChanging

ColumnChanged

RowChanging

RowChanged

CancelEdit()

 

 

 

1

2

3

4

Unchanged

Unchanged

Unchanged

Modified

修改成功

 

ColumnChanging

ColumnChanged

RowChanging

RowChanged

 

CancelEdit()

 

 

1

2

 

 

Unchanged

Unchanged

 

 

未修改

 

ColumnChanging

ColumnChanged

RowChanging

RowChanged

 

 

 

CancelEdit()

1

2

3

4

Unchanged

Unchanged

Unchanged

Modified

修改成功

结论1:分析上面8个表格的执行结果,可以成功编辑的有6种方案,可以取消编辑的只有1种方案。显而易见,Row.EndEdit()和Row.CancelEdit()在调用条件上是对立的,而这两个方法最好是在一个条件语句的两个对立逻辑下被分别调用。因此,为了满足这一条件,数据验证代码应该写在ColumnChanged事件中;

结论2:在记录修改成功的6个方案中,该行状态变为Modified都是在调用RowChanged事件时(该事件之后保持Modified是必然的),在此之前,在其它3个事件中行状态都不会由Unchanged变为成功修改后的Modified。

原文地址:https://www.cnblogs.com/2008freestyle/p/2427841.html