演练:保存相关数据表中的数据(分层更新)

在使用单个数据表且不需要考虑任何外键约束的情况下,将应用程序中的数据存回到数据库中非常简单。 但当您需要保存包含两个或更多相关数据表的数据集中的数据时,为了避免违反约束,必须将对数据表的更改以特定顺序发送到数据库。 在相关表中更新修改过的数据时,可以提供编程逻辑来从每个数据表中提取特定的数据子集,并以正确的顺序将更新发送到数据库,也可以使用 TableAdapterManager 组件。

本演练演示如何使用 TableAdapterManager 组件保存相关数据。 有关手动编写相关数据表更新的代码的信息,请参见演练:将数据保存到数据库(多个表)

系统必备

若要完成本演练,您需要:

创建基于 Windows 的应用程序

本演练的第一步是创建新的基于 Windows 的应用程序。

创建新的基于 Windows 的应用程序

  1. 从**“文件”**菜单创建一个新的项目。

    提示

    由于 Visual Basic 项目和 C# 项目都支持分层更新,所以可以使用这两种语言中的任意一种来创建新项目。

  2. 将项目命名为 HierarchicalUpdateWalkthrough。

  3. 选择**“Windows 窗体应用程序”,然后单击“确定”**。 有关更多信息,请参见创建基于 Windows 的应用程序

    **“HierarchicalUpdateWalkthrough”项目即被创建并添加到“解决方案资源管理器”**中。

创建数据集

由于您需要相关表来演示分层更新,因此下一步要从 Northwind 数据库创建包含 Customers 和 Orders 表的数据集。 使用**“数据源配置向导”**来创建数据集。 必须具有访问 Northwind 示例数据库的权限才能创建连接。 有关如何设置 Northwind 示例数据库的信息,请参见如何:安装示例数据库

创建数据集

  1. 在**“数据”菜单上,单击“显示数据源”**。

  2. 在**“数据源”窗口中,单击“添加新数据源”,启动“数据源配置向导”**。

  3. 在**“选择数据源类型”页上,单击“数据库”,然后单击“下一步”**。

  4. 在**“选择您的数据连接”**页上执行下列操作之一:

    • 如果下拉列表框中包含与 Northwind 示例数据库的数据连接,请单击该连接。

      - 或 -

    • 单击**“新建连接”,打开“添加/修改连接”**对话框。 有关更多信息,请参见“添加/修改连接”对话框(通用)

  5. 如果数据库需要密码,请选择该选项以包括敏感数据,再单击**“下一步”**。

  6. 在**“将连接字符串保存到应用程序配置文件中”页上单击“下一步”**。

  7. 在**“选择数据库对象”页面上展开“表”**节点。

  8. 单击**“Customers”“Orders”表的复选框,然后单击“完成”**。

    **“NorthwindDataSet”将被创建并添加到您的项目中,并在“数据源”**窗口中显示这些表。

更改要创建的默认数据绑定控件

填充**“数据源”窗口后,可以选择将项拖到 Windows 窗体时要创建的控件。 对于本演练,Customers 表中的数据将在单独的控件(“Details”)中显示。 Orders 表中的数据将在 DataGridView 控件(“DataGridView”**)中显示。

为“数据源”窗口中的项设置控件

  1. 在**“数据源”窗口中展开“Customers”**节点。

  2. 在**“Customers”节点的控件列表中单击“Details”,将要为“Customers”**表创建的控件更改为单独的控件。 有关更多信息,请参见如何:设置从“数据源”窗口中拖动时要创建的控件

    提示

    “Orders”表将使用默认控件“DataGridView”

创建数据绑定窗体

在**“数据源”**窗口中选择控件后,可以通过将某些项拖到窗体上来创建数据绑定控件。

为 Customers 和 Orders 数据创建数据绑定控件

  1. 将主**“Customers”节点从“数据源”窗口拖到“Form1”**上。

    带有描述性标签的数据绑定控件会出现在窗体上,同时还显示一个**“TableAdapterManager”**组件和一个用于在记录间进行导航的工具栏 (BindingNavigator)。 组件栏中将出现一个类型化的 DataSetTableAdapter 和一个 BindingSource

  2. 将相关的**“Orders”节点从“数据源”窗口拖动到“Form1”**上。

    提示

    相关的“Orders”节点是“Customers”节点的子节点,位于 customers 表的“Fax”节点下。 与“Customers”节点同级的“Orders”节点表示表中的所有订单。 作为“Customers”节点的子节点的“Orders”节点表示相关订单。

    一个 DataGridView 控件和一个用于在记录间进行导航的工具栏 (BindingNavigator) 出现在窗体上。 TableAdapterBindingSource 出现在组件栏中。

修改生成的保存代码以执行分层更新

通过调用 TableAdapterManager.UpdateAll 方法并传入包含相关表的数据集的名称,可将数据集中相关数据表的更改保存到数据库。 例如,运行 TableAdapterManager.UpdateAll(NorthwindDataset) 方法将 NorthwindDataset 中所有表的更新发送到后端数据库。

从**“数据源”窗口拖放项后,代码会自动添加到 Form_Load 事件以填充每个表(TableAdapter.Fill 方法)。 系统还会向 BindingNavigator“保存”**按钮单击事件添加代码,将数据集中的数据存回数据库中(TableAdapterManager.UpdateAll 方法)。

生成的保存代码还包含调用 CustomersBindingSource.EndEdit 方法的一行代码。 更具体地说,它调用添加到窗体的第一个 BindingSourceEndEdit 方法。 也就是说,此代码只是为从**“数据源”窗口拖到窗体上的第一个表生成的。 EndEdit 调用将提交当前正在编辑的任何数据绑定控件中的所有更改。 因此,如果焦点仍在数据绑定控件上并且您单击了“保存”**按钮,则会先提交该控件中所有挂起的编辑,再执行真正的保存(TableAdapterManager.UpdateAll 方法)。

提示

设计器只为拖放到窗体上的第一个表添加 BindingSource.EndEdit 代码。 因此,必须对窗体上的每个相关表添加一行调用 BindingSource.EndEdit 方法的代码。 对于本演练,这意味着您必须添加一个对 OrdersBindingSource.EndEdit 方法的调用。

更新代码以在保存前提交对相关表的更改

  1. 双击 BindingNavigator 上的**“保存”按钮以在代码编辑器中打开“Form1”**。

  2. 在调用 CustomersBindingSource.EndEdit 方法的代码行后添加一行调用 OrdersBindingSource.EndEdit 方法的代码。 **“保存”**按钮单击事件中的代码应如下所示:

    Me.Validate()
    Me.CustomersBindingSource.EndEdit()
    Me.OrdersBindingSource.EndEdit()
    Me.TableAdapterManager.UpdateAll(Me.NorthwindDataSet)
    
    this.Validate();
    this.customersBindingSource.EndEdit();
    this.ordersBindingSource.EndEdit();
    this.tableAdapterManager.UpdateAll(this.northwindDataSet);
    

除了在将数据保存到数据库之前提交对相关子表的更改外,您可能还需要在向数据集添加新子记录之前先提交新创建的父记录。 也就是说,您可能需要先向数据集添加新父记录 (Customer),然后外键约束才允许将新子记录 (Orders) 添加到数据集中。 为实现这一点,可以使用子 BindingSource.AddingNew 事件。

提示

提交新父记录不是必需的;具体取决于用于绑定到数据源的控件的类型。 在本演练中,您使用单独的控件绑定到父表;这需要额外的代码来提交新的父记录。 如果父记录在类似于 DataGridView 的复杂绑定控件中显示,则对该父记录的额外 EndEdit 调用不是必需的。 这是因为这类控件的基础数据绑定功能可以提交新记录。

添加代码以在添加新子记录之前在数据集中提交父记录

  1. 为 OrdersBindingSource.AddingNew 事件创建一个事件处理程序。

    • 在设计视图中打开**“Form1”,在组件栏中单击“OrdersBindingSource”,在“属性”窗口中选择“事件”,然后双击“AddingNew”**事件。
  2. 向事件处理程序添加调用 CustomersBindingSource.EndEdit 方法的一行代码。 OrdersBindingSource_AddingNew 事件处理程序中的代码应如下所示:

    Me.CustomersBindingSource.EndEdit()
    
    this.customersBindingSource.EndEdit();
    

验证分层更新已启用

通过设置数据集的**“分层更新”属性可打开或关闭分层更新。 默认情况下启用分层更新,因此对于本演练,不需要更改“分层更新”**属性的值。

验证分层更新已启用

  1. 在**“解决方案资源管理器”中双击“NorthwindDataSet.xsd”文件,以在“数据集设计器”**中打开该数据集。

  2. 选择设计图面上的空白区域。

  3. “属性”窗口中找到**“分层更新”属性,然后检查它是否设置为“True”**。

    提示

    “分层更新”属性设置用于控制生成的代码是否带有 TableAdapterManager 和执行分层更新所需的逻辑。 将“HierarchicalUpdate”设置为“True”将生成 TableAdapterManager;将“HierarchicalUpdate”设置为“False”则不生成 TableAdapterManager。

测试应用程序

测试应用程序

  1. 按 F5。

  2. 对每个表中的一条或多条记录的数据执行一些更改。

  3. 添加新客户,然后添加该客户的新订单。

  4. 单击**“保存”**按钮。 TableAdapterManager 将处理所有相关更新所需的逻辑。

  5. 检查数据库中的值以验证更改已保存到每个表中。

后续步骤

根据应用程序的要求,在基于 Windows 的应用程序中保存相关数据后,可能还要执行一些步骤。 您可以对此应用程序进行的增强包括:

  • 添加第三个表,例如 OrderDetails 表,体验一下三个表的层次结构。

  • 添加验证代码以验证数据满足应用程序的要求和数据库约束。 有关更多信息,请参见验证数据

请参见

任务

如何:配置数据集中的外键约束

如何:设置分层更新的执行顺序

如何:在保存数据前提交数据绑定控件中正在进行的编辑

如何:在现有 Visual Studio 项目中实现分层更新

演练:保存相关数据表中的数据(分层更新)

其他资源

分层更新

保存数据

DataSet、DataTable 和 DataView (ADO.NET)