如何用DataSet.GetChanges来提升数据库资料更新效率。
(華版)
一般我们都是直接用回同一个DataSet来更新数据库里的资料,但有没有想过这样是很没有效率的做法!因为SqlDataAdapter要扫描整个DataSet里的数据的RowState;只有以下三个State的数据才传送回去数据库:
DataRowState.Added
DataRowState.Deleted
DataRowState.Modified
所以就要用DataSet.GetChanges方法来读取所指定(Added,Deleted或Modified)的数据,然后存到另一个新的DataSet(比如说:dsChanges)。这一来,当执行SqlDataAdapter.Update方法时就不再需要扫描那么多的数据了(比如说:Unchanged的DataRow)。
Private ds As DataSet
Private dsChanges As DataSet
'(前)
'刷新数据库里的资料
da.Update(ds)
'(后)
'实列化DataSet Class
dsChanges = New DataSet
'读取所有更改,新添加,删除的数据
dsChanges = ds.GetChanges(DataRowState.Added Or DataRowState.Deleted Or DataRowState.Modified)
'刷新数据库里的资料
da.Update(dsChanges)
而且每一个DataRow都会保存两份数据;一份是原本的数据(在还没有更改时)和更改后的数据(RowState = DataRowState.Modified)。这也是SqlDataAdapter用来面对数据conflict时的重点数据。因为DataSet是保存在用户端的数据(就是ADO.NET的设计重点"Disconnected Environment");所以存在数据库里的数据随时都可以被另一个程序更改而没有反映在别的用户端里的DataSet。
如果没有了Original的数据,那SqlDataAdapter里的UpdateCommand的CommandText就如以下:
UPDATE Customers SET ContactName = @ContactName WHERE CustomerID = @CustomerID
但是如果有了Original的数据后;整个CommandText就会复杂多了(尤其是那些读取整个table的数据那种!)和更加保险:
UPDATE Customers SET ContactName = @ContactName WHERE CustomerID = @CustomerID AND ContactName = @OrigContactName
而@ContactName就是读取自DataRow.Item("ContactName", DataRowVersion.Current)和@OrigContactName就读取自DataRow.Item("ContactName", DataRowVersion.Original)。当然SqlDataAdapter.UpdateCommand里的CommandText就会复杂多一些了。。。
prm(2) = New SqlParameter
With prm(2)
.ParameterName = "@ContactName"
.Direction = ParameterDirection.Input
.SqlDbType = SqlDbType.NVarChar
.Size = 40
.SourceColumn = "ContactName"
.SourceVersion = DataRowVersion.Current
End With
prm(3) = New SqlParameter
With prm(3)
.ParameterName = "@OrigContactName"
.Direction = ParameterDirection.Input
.SqlDbType = SqlDbType.NVarChar
.Size = 40
.SourceColumn = "ContactName"
.SourceVersion = DataRowVersion.Original
End With
prm(4) = New SqlParameter
With prm(4)
.ParameterName = "@CustomerID"
.Direction = ParameterDirection.Input
.SqlDbType = SqlDbType.NChar
.Size = 5
.SourceColumn = "CustomerID"
.SourceVersion = DataRowVersion.Original
End With
'实列化SqlCommand Class
cmd(1) = New SqlCommand
'设定SqlCommand对象的属性
With cmd(1)
.Connection = cn
.CommandTimeout = 10
.CommandText = "UPDATE Customers SET ContactName = @ContactName WHERE CustomerID = @CustomerID AND ContactName = @OrigContactName"
.CommandType = CommandType.Text
.Parameters.Add(prm(2))
.Parameters.Add(prm(3))
.Parameters.Add(prm(4))
End With
'实列化SqlDataAdapter Class
da = New SqlDataAdapter
da.UpdateCommand = cmd(1)