【理论基础】
在2.0以前版本的 ADO.NET 中,使用 DataSet 中的更改来更新数据库时,DataAdapter 的 Update 方法每次更新数据库的一行。因为该方法循环访问指定 DataTable 中的行,所以,会检查每个 DataRow,确定是否已修改。如果该行已修改,将根据该行的 RowState 属性值调用相应的 UpdateCommand、InsertCommand 或 DeleteCommand。每一次行更新都涉及网络与数据库之间的双向数据传输。
——注意这段话的意思是根据DataSet中每一行的RowState值,采取相应的数据操作:由DataAdapter 调用相应的命令执行。在ADO.NET 2.0版本中也是这样执行的。
在 ADO.NET 2.0 中,DataAdapter 公开了 UpdateBatchSize 属性。将 UpdateBatchSize 设置为正整数值将使对数据库的更新以指定大小的批次进行发送。例如,如果将 UpdateBatchSize 设置为 10,会将 10 个独立的语句组合在一起并作为一批提交。将 UpdateBatchSize 设置为 0 将导致 DataAdapter 使用服务器可以处理的最大批次的大小。如果将其设置为 1,则禁用批量更新,因为此时每次发送一行。
——UpdateBatchSize 属性是实现批量修改数据的关键。
【具体实现】
这是一个进行批量修改的函数,参数为一个dataTable和批次大小的值batchSize。为简单起见这里仅对修改的数据进行更新。
public static void BatchUpdate(DataTable dataTable, Int32 batchSize)
{
// Assumes GetConnectionString() returns a valid connection string.
string connectionString = GetConnectionString();
// Connect to the AdventureWorks database.
using (SqlConnection connection = new
SqlConnection(connectionString))
{
// Create a SqlDataAdapter.
SqlDataAdapter adapter = new SqlDataAdapter();
// Set the UPDATE command and parameters.
adapter.UpdateCommand = new SqlCommand(
"UPDATE Table_Student SET "
+ "StudentName=@StudentName WHERE StudentID=@StudentID;",
connection);
adapter.UpdateCommand.Parameters.Add("@StudentName",
SqlDbType.NVarChar, 50, "StudentName");
adapter.UpdateCommand.Parameters.Add("@StudentID",
SqlDbType.Int, 4, "StuID");
adapter.UpdateCommand.UpdatedRowSource = UpdateRowSource.None;
adapter.UpdateBatchSize = batchSize;
// Execute the update.
adapter.Update(dataTable);
}
}
以下是对该方法的调用,写在Main函数中。
static void Main(string[] args)
{
DataTable dt = new DataTable();
dt.Columns.Add("StuID", typeof(string));
dt.Columns.Add("StudentName", typeof(string));
DataRow dr = dt.NewRow();
dt.Rows.Add(dr);
dt.AcceptChanges();
dt.Rows[0][0] = "1002";
dt.Rows[0][1] = "***";
BatchUpdate(dt, 10);
}
在该函数中注意各语句的执行顺序,因为执行顺序不同DataRow的RowState值是不一样的。尤其适当循环改变数据时。
另外注意:两处为褐色的StuID,这说明,adapter.UpdateCommand.Parameters.Add方法中的第四个参数源数据值得是dataTable中对应列的值。
下面附上行状态的说明。
每个 DataRow 对象都具有 RowState 属性,您可以检查此属性来确定行的当前状态。下表提供了对每个 RowState 枚举值的简短说明。
RowState 值 |
说明 |
Unchanged |
自上次调用 AcceptChanges 以来或由 DataAdapter.Fill 创建该行以来,没有进行任何更改。 |
Added |
已将该行添加到表中,但尚未调用 AcceptChanges。 |
Modified |
已更改了行的某个元素。 |
Deleted |
已从表中删除该行,并且尚未调用 AcceptChanges。 |
Detached |
该行不是任何 DataRowCollection 的一部分。新创建的行的 RowState 设置为 Detached。通过调用 Add 方法将新的 DataRow 添加到 DataRowCollection 后,RowState 属性的值设置为 Added。 将使用 Remove 方法,或使用 Delete 方法接着使用 AcceptChanges 方法从 DataRowCollection 中移除的行也设置为 Detached。 |
对 DataSet、DataTable 或 DataRow 调用 AcceptChanges 时,会移除行状态为 Deleted 的所有行。剩余行的行状态为 Unchanged,并且 Original 行版本中的值将被 Current 行版本值覆盖。调用 RejectChanges 时,会移除行状态为 Added 的所有行。剩余行的行状态为 Unchanged,并且 Current 行版本中的值将被 Original 行版本值覆盖。