[原文作者]: Beth Massi
[原文链接]: The New TableAdapterManager in Visual Studio 2008
在我以前的TableAdapters and Transactions文章中,我展示了一套关于如何在多层数据表结构的数据集中完成事务内部的分等级更新。我在这里给出的例子演示了Visual Studio 2005中如何用数据库事务或者TransactionScope去更新数据。这需要一些代码来管理行的正确更新顺序,TableAdapters上的连接和处理,以及在回滚的情况下,你希望保持数据集中原有的变化。
幸运的是,在Visual Studio 2008中DataSet生成器有了新的提高,它创建了一个新的类通过只有几行代码自动处理所有这些事情!进入TableAdapterManager。
在这篇文章中,我将要借用以前的应用程序同时把它升级到Visual Studio 2008,要清楚的一点是,我将不会去升级它的目标框架,因为我希望程序能继续在NET Framework 2.0上运行。(Visual Studio 2008 可以通过一个叫做Multi-Targeting的特性去开发支持NET 2.0, 3.0 and 3.5 Frameworks的应用程序。关于这方面的更多使用方法,请看这里)
当你在 Visual Studio 2008中打开NorthwindTransaction.sln文件,它将会启动一个升级项目向导,使sln项目文件兼容于Visual Studio 2008. 启动以后,在资源管理器中双击OrdersDataSet 以打开数DataSet Designer。在属性视窗中会看到“分等级的更新” 选择True并保存. 这表示告诉数据集发生器去生成了TableAdapterManager 类. 注意每当你创建新的数据集时,默认的就是True。
现在,展开OrderForm以打开Windows Form设计器,删除工具箱顶部的Dropdown控件(TransactionToolStripDropDownButton)因为我们现在只要有一个简单的Save() 方法。右键点击窗体察看代码,在OrdersBindingNavigatorSaveItem的click事件中移掉Case语句,用Me.Save()代替:
Private Sub OrdersBindingNavigatorSaveItem_Click() Handles OrdersBindingNavigatorSaveItem.Click
Me.Validate()
'Commit all data to the OrdersDataSet
Me.OrdersBindingSource.EndEdit()
Me.Order_DetailsBindingSource.EndEdit()
If Not Me.OrdersDataSet.HasErrors Then
If Me.OrdersDataSet.HasChanges Then
If Me.Save() Then
MessageBox.Show("Your changed have been saved.", Me.Text, _
MessageBoxButtons.OK, MessageBoxIcon.Information)
Else
MessageBox.Show("Your changes could not be saved!", Me.Text, _
MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
End If
Else
MessageBox.Show("Please make changes first.", Me.Text, _
MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
End If
Else
MessageBox.Show("Please correct the errors with this data first.", Me.Text, _
MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
End If
End Sub
现在到了很有趣的部分。我们将删除所有的Savexxx()方法并且改写成使用新的TableAdapterManager的简单的Save()方法。这个代码和以前用的SaveInDatabaseTransaction() 方法的效果是一样的。
''' <summary>
''' Performs an ordered save so that keys are properly updated in
''' the child table and so that deleted child rows are submitted
''' to the database first inside a database transaction automatically.
''' VS 2008 generates code that takes care of the saving in the proper
''' order in a database transaction.
''' </summary>
''' <returns></returns>
''' <remarks></remarks>
Private Function Save() As Boolean
Dim saved As Boolean = False
If Me.OrdersDataSet.HasChanges Then
Try
Dim manager As New OrdersDataSetTableAdapters.TableAdapterManager
'Back up the dataset so that if the transaction fails, then the entire
' dataset is restored to it's original state.
manager.BackupDataSetBeforeUpdate = True
manager.Order_DetailsTableAdapter = Me.Order_DetailsTableAdapter
manager.OrdersTableAdapter = Me.OrdersTableAdapter
saved = (manager.UpdateAll(Me.OrdersDataSet) > 0)
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End If
Return saved
End Function
发现没有,现在的代码简洁多了。以前我们必须去管理Order的更新,连接和事务处理,以及回卷的状态。现在所有这些都照顾到了。既然我们不再需要用到它,我们也可以在form中移掉MergeAfterSave方法以及TableAdapter partial 类中的AssignConnection方法。注意,如果我们已经创建了一个新的窗体,那么它就已经为我们创建了TableAdapterManager实例,预置了TableAdapter实例。
运行应用程序选择一个客户的订单,然后在窗体上添加、更新和删除父子行。当我们点击保存按钮,这些行将会被更新和插入到parent-child order中,而在child-parent order中删除,所有的这些都在数据库事务内部完成。一旦你打开SQL Server Profiler,我们可以看到:

你也可以通过设置UpdateOrder属性来指示TableAdapterManager你想先处理更新过程。更多信息请查看TableAdapterManager文档。
TableAdapterManager为我们省去了很多代码,但是你仍需要确认你已经完全地设置好你的数据集去处理foreign-key约束,就像我在这片文章中提到的,在TableAdapters里按特定的顺序调用Fill方法。更多详细信息请阅读这篇文章,关于在你的数据集中使用foreign-key约束,这样能够通过TableAdapterManager完全更新。我已经附上更新好的程序了.
Enjoy!
Attachment(s):NorthwindTransaction2008.zip