21.8.1 通过数据适配器进行更新
除了SqlDataAdapter最有可能包含的 SelectCommand之外,还可以定义InsertCommand、 UpdateCommand 和 DeleteCommand。顾名思义,这些对象都是适用于相应提供程序的命令对象(例如SqlCommand 或 OleDbCommand)实例。
有了这种灵活性后,就可以自由调整应用程序,对频繁使用的命令(例如select和insert)采用合适的存储过程来执行,对不常使用的命令(例如delete)采用SQL命令的方式执行。一般应为所有的数据库交互操作提供存储过程,因为这会更快,更容易调整。
本节的示例重新使用“调用存储过程”一节中的存储过程,插入、更新和删除Region记录,再把这些与上面编写的RegionSelect过程结合起来,生成一个新示例,这个示例使用这些命令来检索和更新DataSet中的代码。代码的主体如下所示。
1. 插入一个新行
把新行添加到DataTable中有两种方式。第一种方式是调用NewRow()函数,返回一个空行,然后向其填充数据,最后把它添加到Rows集合中:
DataRow r = ds.Tables["Region"].NewRow();
r["RegionID"]=999;
r["RegionDescription"]="North West";
ds.Tables["Region"].Rows.Add(r);
第二种方式是把一组数据传送给Rows.Add()方法:
DataRow r = ds.Tables["Region"].Rows.Add
(new object [] { 999 , "North West" });
DataTable中的每个新行都把自己的RowState设置为Added,在对数据库进行修改前,这个示例先把记录清空,然后把下面的行添加到DataTable中(以任何一种方式)。注意右边一列显示行的状态:
New row pending inserting into database
1 Eastern Unchanged
2 Western Unchanged
3 Northern Unchanged
4 Southern Unchanged
999 North West Added
要在DataAdapter中更新数据库,调用Update方法:
da.Update(ds , "Region");
对于DataTable中的每一新行,这将执行存储过程(在本例中是RegionInsert),然后再次把DataTable中的记录清空,查看对数据库进行的修改。
New row updated and new RegionID assigned by database
1 Eastern Unchanged
2 Western Unchanged
3 Northern Unchanged
4 Southern Unchanged
5 North West Unchanged
看看DataTable中的最后一行。把代码中的RegionID设置为999,但在执行RegionInsert存储过程后,该值改为5,这是本例的目的—— 数据库会生成主键码,并且更新DataTable中的数据。DataTable中的数据更新是因为源代码中的SqlCommand定义会把UpdatedRowSource属性设置为UpdateRowSource.OutputParameters:
SqlCommand aCommand = new SqlCommand("RegionInsert" , conn);
aCommand.CommandType = CommandType.StoredProcedure;
aCommand.Parameters.Add(new SqlParameter("@RegionDescription" ,
SqlDbType.NChar ,
50 ,
"RegionDescription"));
aCommand.Parameters.Add(new SqlParameter("@RegionID" ,
SqlDbType.Int,
0 ,
ParameterDirection.Output ,
false ,
0 ,
0 ,
"RegionID" , // Defines the SOURCE column
DataRowVersion.Default ,
null));
aCommand.UpdatedRowSource = UpdateRowSource.OutputParameters;
无论何时DataAdapter执行这个命令,输出参数都应映射回数据行的源,在本例中是DataTable中的一行,该标志说明了应更新什么数据—— 存储过程有一个输出参数映射回DataRow,它应用的列是RegionID,这是在命令定义中定义的。
UpdateRowSource的值如表21-9所示。
|
UpdateRowSource值 |
说 明 |
|
Both |
存储过程可以返回输出参数和一个完整的数据库记录。这些数据源都用于更新源数据行 |
|
FirstReturnedRecord |
该命令返回一个记录,该记录的内容应合并到最初的源DataRow中,当给定的表有许多默认(或计算)列时,使用这个值很有用,因为在执行插入语句之后,这些行需要与客户机上的DataRow同步。例如INSERT (列) INTO (表) WITH (主键码),SELECT (列) FROM (表) WHERE (主键码)。返回的记录应合并到源数据行上 |
|
None |
删除从该命令返回的所有数据 |
|
OutputParameters |
命令的任何输出参数都映射到DataRow的对应列上 |
2. 更新现有的行
更新DataTable中一个已经存在的行只需使用带有一个列名或列号的DataRow索引器即可,如下面的代码所示:
r["RegionDescription"]="North West England";
r[1] = "North East England";
这两个语句是等价的(在本例中):
Changed RegionID 5 description
1 Eastern Unchanged
2 Western Unchanged
3 Northern Unchanged
4 Southern Unchanged
5 North West England Modified
在更新数据库前,被更新的行应把其状态设置为Modified,其值如上所示。
3. 删除一行
r.Delete();
被删除的行把其行状态设置为Deleted,但不能从被删除的DataRow中读取列,因为它们已经不再有效,当调用适配器的Update()方法时,所有被删除的行都会使用DeleteCommand,在本例中是执行RegionDelete存储过程。





