65.9K
CodeProject 正在变化。 阅读更多。
Home

详细演练:创建包含两个关系表的 Dataset 和 Database。TableAdapterManager 上的 UpdateAll 方法。

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.19/5 (10投票s)

2017年3月16日

CPOL

20分钟阅读

viewsIcon

24458

详细演练如何使用 C# .NET 无代码创建关系型数据库应用程序。

引言

创建 1)数据库 和 2)数据集 并不是一个新话题,但我试图在不编写代码的情况下详细地概述这个工作项目。(请注意顺序:1)数据库 和 2)数据集。)

必备组件


*Microsoft Visual Studio 2012-2015 (我使用的是 Visual Studio Community 2015)
*SQL Server 2012-2015 

本演练中演示的任务包括

*创建一个新的 Windows 应用程序项目。
*创建一个新的本地 SQL Server 数据库文件
*创建表、列、主键和外键。
*使用 Dataset 设计器创建一个包含两个关系表的新数据集对象。
*用数据填充表,并保存它们。
*插入、更新和删除操作,并将更改保存回数据库。

Application

1.创建一个新的 Windows 窗体应用程序项目。
  1.1 文件>新建>项目>Visual C#>Windows 窗体应用程序>命名为 "DBExample">确定
  1.2 "DBExample" 项目已创建并添加到解决方案资源管理器中。

2.创建一个附加到本地实例的新 SQL Server 数据库文件。
  2.1 项目>添加新项>数据 (已安装)>基于服务的数据库 (模板)>命名为 Database1.mdf>添加

 2.2 如果数据源配置向导打开,点击完成

 2.3 "Database1.mdf" 文件已添加到项目中。(它位于你的 "DBExample" 项目文件夹中)

 2.4 重要!这将帮你解决这个问题: 
      “我的数据库没有更新,但没有任何错误。”
      在解决方案资源管理器中点击 Database1.mdf。
      编辑属性 生成操作=无 和 复制到输出目录=不复制


      2.4.1 你可以使用 Database1.mdf "文件属性来指定项目系统
               应该对文件执行哪些操作。例如,你可以设置文件属性来指示
               文件是否应被编译或作为资源嵌入到生成输出中。
               2.4.1.1 生成操作属性指示 Visual Studio 在执行生成时
                           对文件执行的操作(主要属性)。
                         * 无 - 文件不包含在项目输出组中,
                           并且在生成过程中不进行编译。一个例子是自述文本文件。
                         * 编译 - 文件被编译到生成输出中。此设置用于代码文件。
                         * 内容 - 文件不被编译,但包含在内容输出组中。
                            例如,此设置是 .htm 或其他类型 Web 文件的默认值。
                         * 嵌入的资源 - 此文件作为 DLL 或                                          可执行文件嵌入到主项目生成输出中。它通常用于资源文件。
                         * 其他属性主要用于 WPF。
                2.4.1.2 复制到输出目录属性
                           指定在何种条件下将所选源文件
                           复制到输出目录 (.../bin/Debug/...)。
                          * 不复制 - 如果文件永远不复制到输出目录。
                          * 始终复制 - 如果文件总是要复制到输出目录。
                          * 如果较新则复制 - 如果文件仅在比输出目录中
                            同名的现有文件更新时才复制。" (MSDN 来源)

2.5 在解决方案资源管理器中双击 Database1.mdf。你将打开服务器资源管理器窗口。

 2.6 选择 Database1.mdf 并点击刷新。 
      Refresh 方法从 SQL Server 实例更新 Database 对象的属性。    
      2.6.1 数据库的属性窗口显示了连接字符串 
               以及数据库主 .mdf 文件的位置。 

3.创建基于 Customers 和 Orders 表(带关系)的数据库。
  3.1 在服务器资源管理器中,展开“数据连接”节点,然后展开 Database1.mdf 节点。 
        如果服务器资源管理器没有出现,你可以通过在菜单栏上选择“视图”>“服务器资源管理器”来显示它。
  3.2 右键点击 Database1.mdf 下的“表”节点

        3.2.1 如果你在下拉菜单中看不到“添加新表”,如下所示

                一种可能是需要安装与 Visual Studio 版本相适应的SQL Server Data Tools (SSDT)

                


  3.3 从下拉菜单中点击“添加新表”(设计界面正在加载)


       “表设计器是一个可视化工具,允许你设计
        和可视化你所连接的数据库表。
        表设计器打开并显示一个带有一行默认行的网格,
        该行代表你正在创建的表中的单个列。 
        通过向网格中添加行,你将在表中添加列。”(MSDN 来源)

   3.4 在 T-SQL 脚本窗格中重命名新表(Customers)

   3.5 以下表和字段应在 SQL Express 数据库中创建。

    3.5.1 “在新版 SQL Server 2012 中,你可以通过
            图形界面或直接在脚本窗格中更改表定义。 
            如果你使用图形界面,表的定义会自动在
            脚本窗格中更新。要应用脚本窗格中的 SQL 代码,请选择‘更新’按钮。”(MSDN 来源)

 3.6 选中 CustomerID 行以设置主键。

 3.7 选择 CustomerID 列,并在列被选中时,在属性窗口中编辑这些属性。
      编辑 Is Identity=True,Identity Increment=1,Identity Seed=1。

      3.7.1 “Is Identity 指示此列是否为标识列。
      3.7.2 Identity Seed 显示创建此标识列时指定的种子值。
      3.7.3 Identity Increment 显示创建此标识列时指定的增量值。”
                   (MSDN 来源)

3.8 在表设计器的左上角,选择“更新”按钮。
      在“预览数据库更新”对话框中,选择“更新数据库”按钮。
      你的更改将保存到本地数据库文件中。
      3.8.1 一个选项“包含事务脚本”用于保存事务脚本
      3.8.1 使用“生成脚本”时,你可以选择在
            使用表设计器时保存更改脚本。

3.9 在服务器资源管理器中刷新 Database1.mdf,打开“表”节点。 
      你会看到新的 Customers 表出现了。

3.10 对名为 Orders 的新表重复 3.1-3.9 的步骤。

3.11 创建上一步中创建的表之间的关系。              
       对于 Orders 表,在网格右侧的上下文窗格中,
       打开“外键”的快捷菜单,然后选择“添加新外键”。 
       点击 Enter。

  3.11.1 SQL Server 2012-2015 不支持数据库关系图设计器。
            然而,SQL Server 2005、SQL Server 2008 和 SQL Server 2008 R2 
            确实支持此功能。

3.12 在 T-SQL 窗格中,用以下内容更新外键行的默认定义引用。
  CONSTRAINT [FK_Orders_Customers] FOREIGN KEY (CustomerID) REFERENCES Customers(CustomerID)

 3.13 在表设计器的左上角,点击“更新”按钮。

 3.14 文件>全部保存 或 全部保存(Ctrl+Shift+S) 按钮。

4. 你可以通过创建一个数据集来轻松地在你的应用程序中显示本地数据库文件中的数据。
   你将使用 Database1.mdf 中的 Customers 和 Orders 关系表来创建和配置一个数据集。
   数据集是一个包含数据表的对象,你可以在其中临时存储数据以供应用程序使用。
   DataSet 的结构类似于关系型数据库
   它公开了一个包含表、行、列、约束和关系的层级对象模型。

  4.1 点击 Form1.cs[设计]视图。
  4.2 创建一个新的 DataSet 对象。
       项目>添加新项>数据(已安装)>DataSet(模板)>命名为 DataSet1.xsd>添加

4.3 打开数据集设计器窗口。
       数据集设计器是一套可视化工具,你可以用它来创建
       和编辑类型化数据集及其包含的各个项目。
       将 Customers 和 Orders 两个表从服务器资源管理器拖到数据集设计器区域
       4.3.1 注意数据集设计器已创建 CustomersTablesAdapter 和 OrdersTablesAdapter
               它们带有 Fill,GetData() 主查询,定义了表的 SQL 架构。

               “TableAdapter 提供应用程序和数据库之间的通信。 
               它们连接到数据库,运行查询或存储过程,然后返回
               一个新的数据表或用返回的数据填充一个现有的 DataTable。 
               TableAdapter 也可以将应用程序中更新的数据发送回数据库”。(MSDN 来源)


       4.3.2 注意 Customers 和 Orders 表通过外键 FK_Orders_Customers 建立了关系。 

     4.3.3 自动生成的连接字符串并将其保存
             在应用程序配置文件中(应用程序设置)。
             在解决方案资源管理器中点击 App.Config 文件进行检查

            连接字符串是用于打开数据库的“密钥字符串”。

 4.4 打开数据源面板并展开 Customers 节点。
       如果数据源窗口未显示,请在菜单栏上选择“视图”>“其他窗口”>“显示数据源”。
       在 Customers 表中,你会看到一个 Orders 表的节点。

  4.5 在数据集设计器中,对于 Customers DataTable 中的 CustomerID DataColumn 对象,
       打开属性窗口并更改 AutoIncrement=True 
       AutoIncrementSeed=1 AutoIncrementStep=1 属性。
       这表示该列是否为添加到表中的新行自动递增列的值。

 4.6 更改 AutoIncrement=True AutoIncrementSeed=1 AutoIncrementStep=1 属性
       对于 Orders DataTable 中的 OrderID DataColumn 对象。

 4.7 在菜单栏上,选择“生成”并选择“重新生成解决方案”以“清理”
       解决方案,然后生成所有项目文件和组件。

       注意:数据库文件(Database1.mdf, Database1_log.ldf) 
       不会复制到项目的输出文件夹(.../bin/Debug/)。

5. 通过从数据源窗口拖动代表数据表或对象的项来设计 UI。
   5.1 确保 Windows 窗体设计器已打开,选择 Form1.cs[设计]视图。
   5.2 在数据源窗口中,选择代表数据表的 DataGridView。

 信息参考
     5.2.1 要在单独的控件中显示每个数据字段,请单击“详细信息”。 
             当您将数据项拖动到设计器时,此操作将
             为父数据表或对象的每个列或属性创建一个不同的数据绑定控件,
             以及每个控件的标签。
    5.2.2 选择您想要为其设置要创建的控件的每个列或属性

5.3 将主 Customers 节点作为 DataGridView 从数据源窗口拖到 Form1 上。
       数据绑定控件 customersDataGridView 会出现在窗体上,
       同时还有一个用于导航记录的工具条 customersBindingNavigator

   5.4 将主 Orders 节点作为 DataGridView 从数据源窗口拖到 Form1 上。

   5.5 将关系 Orders 节点作为 DataGridView 从数据源窗口拖到 Form1 上。

  5.6 一个 dataSet1, customersTableAdapter, customersBindingSource, tableAdapterManager,
       customersBindingNavigator, ordersBindingSource, ordersTableAdapter 和 ordersBindingSource1

       会出现在组件栏中。

     5.6.1 点击 orderBindingSource (orderBindingSource1) 并打开属性窗口。
             注意 ordersBindingSource 和 ordersBindingSource1 之间
             在属性 DataMember 和 AllowNew 上的区别。
    5.6.2 “默认情况下,当您创建
             一个包含相关表且 Hierarchical Update=true 属性的数据集时,会生成一个 TableAdapterManager 类。
             默认情况下,数据集将相关表视为‘仅关系’,
             这意味着它不强制执行外键约束。 
             您可以在设计时使用数据集设计器修改该设置。
             选择两个表之间的关系线并双击
             以打开‘关系’对话框。
             您在这里所做的更改将决定 TableAdapterManager
             在将相关表中的更改发送回数据库时的行为。”(MSDN 来源)

  5.7 右键单击 Form1 并选择“查看代码”。

  5.8 从数据源窗口拖动项目到窗体上时,
       用数据填充数据表的代码会自动添加到 Form_Load 事件处理程序中。
       在代码编辑器中打开您的窗体,以查看填充特定表的确切语法。


  5.9 默认情况下,BindingNavigator 的“保存”按钮的事件处理程序会被添加
       到窗体的代码中,以将更新发送到数据库。 

6. 现在我们有了用于填充 Customers 和 Orders 关系表的 UI 设计。
   “在数据集填充数据之后,您通常会执行某种类型的数据操作,
   然后才将其发送回数据源或发送给另一个进程或应用程序。 
   由于数据集中的每条记录都由一个 DataRow 对象表示,
   对数据集的更改是通过更新和删除单个行来完成的。”(MSDN 来源)

 6.1 在“调试”菜单上,点击“启动”以运行项目或按 F5。
       6.1.1 触发 Form1_Load 事件处理程序。TableAdapter 的 Fill 方法用数据填充数据集。
       6.1.2 数据集是数据源的内存副本。默认情况下它是空的。

  6.2 像这个例子一样填充 Customers 表(dataSet1)的第一行
       然后点击 customersBindingNavigator 的“保存”按钮(将 dataSet1 中的数据保存到 Database1.mdf 中)。

  6.3 糟糕!出现了“类型为 'System.Data.SqlClient.SqlException' 的未处理异常
       在 System.Data.dll 中发生”。尝试附加一个自动命名的 Database1.mdf 失败。

       点击“停止调试”。

     6.3.1 在解决方案资源管理器中打开 App.Config 文件。
             查看字符串 AttachDbFilename=|DataDirectory|\Database1.mdf;
             SqlClient 和 OleDb 托管提供程序支持此连接字符串语法。
             “默认情况下,|DataDirectory| 变量将按如下方式扩展:
             * – 对于放置在用户机器上目录中的应用程序,这将是应用程序的 (.exe) 文件夹。
             * – 对于在 ClickOnce 下运行的应用程序,这将是 ClickOnce 创建的一个特殊数据文件夹。
             * – 对于 Web 应用程序,这将是 App_Data 文件夹。  
   
  6.4 我们将数据文件路径替换为项目外部的硬编码路径 AttachDbFilename=Myproject\Data.mdf;
       通过这种方式,设计时和运行时都将使用相同的数据
       文件,但缺点是连接字符串中的路径将被硬编码,
       因此共享项目和部署应用程序会更困难。 
       在部署应用程序之前,只需确保将设置中的完整路径替换为相对路径即可。”                                                                                                                                                           (MSDN 来源)

 6.5 重复 6.2。填充 Customs 表(dataSet1)的第一行,然后点击 customersBindingNavigator 的“保存”按钮。
       现在,一切正常!
       在服务器资源管理器窗口中右键单击 Customers 表,然后选择“显示表数据”。
       点击“刷新”并注意 Database1 和 dataSet1 都已更新。
       检查 Customers 表的数据是否已保存。

 6.6 像这个例子一样填充 Customs 和 Orders 表,然后点击 customersBindingNavigator 的“保存”按钮。

 6.7 选择 Customers 表中 CustomerID=3 的行
       关系表 FK_Orders_Customers 仅显示 CustomerID=3 的两个订单。

  6.8 选择 Customers 表中 CustomerID=4 的行。
       Orders 表中没有 CustomerID=4 的行,因此关系表 FK_Orders_Customers 是空的。

 6.9 类似地,选择 Customers 表中 CustomerID=5 的行
       关系表 FK_Orders_Customers 仅显示 CustomerID=5 的一个订单。

6.10 尝试更改相关的 FK_Orders_Customers 表中的数据。
       选择新行并像这样填充数据。

6.11 按下键盘上的 Enter 键。新行已传递到 Orders 表。
        关系表 FK_Orders_Customers 仍然只显示 CustomerID=5 的一个订单。   

6.12 选择 CustomerID=3 的行,然后点击 customersBindingNavigator 的“删除”按钮。 
       dataSet1 已更新。点击 customersBindingNavigator 的“保存”按钮。

 6.13  糟糕!出现“SqlException was unhandled”。Database1.mdf 未更新。


       点击“停止调试”。

       “您可以通过从表相关的集合中删除相应的 LINQ to SQL 对象来删除数据库中的行。
       LINQ to SQL 将您的更改转换为相应的 SQL DELETE 命令。
       LINQ to SQL 不支持或识别级联删除操作。 
       如果要删除表中存在约束的行,您必须完成以下任务之一
       * - 在数据库的外键约束中设置 ON DELETE CASCADE 规则。
       * - 使用您自己的代码首先删除阻止父对象被删除的子对象。
       否则,将引发异常。” (MSDN 来源)

6.14 我们将使用第一条规则。
       在服务器资源管理器中刷新 Database1.mdf 并双击 Orders 表。
       dbo.Orders[设计]已打开。
       将引用操作 ON DELETE CASCADE 添加到 T-SQL 脚本字段中。
       然后点击“更新”按钮。

6.15 重试 6.12,删除 Customers 表中 CustomerID=3 的行。
       点击 customersBindingNavigator 的“删除”按钮。
       Customers 和 FK_Orders_Customers 表已更新。
        这表明 dataSet1 已更新。

        6.15.1  “当您通过更新、插入和删除记录来对数据集中的记录进行更改时,
                   数据集会维护记录的原始版本和当前版本。
                   此外,每行的 RowState 属性会跟踪记录是处于
                   原始状态,还是已被更新、插入或删除。
                   由于此更改,该行的 RowState 属性的值会从
                   Unchanged 变为 Modified。
                   在数据集中进行更改时,已更改行的 RowState 属性会被设置。” (MSDN 来源)


       点击 customersBindingNavigator 的“保存”按钮后,Database1.mdf 也已更新。
       但要显示最新的更新,请打开服务器资源管理器,右键单击 Customers 或 Orders 节点
       并选择“显示表数据”。别忘了点击“刷新”按钮!

  6.17 在 Customers 和 Orders 表中插入新行。
       然后新行将出现在 FK_Orders_Customers 表中。

        点击“保存”按钮以保存所有从 dataSet1 到 Database1.mdf 的更改。

6.18  我和 MSDN 给了你基础。请自己尝试对表进行实验。

         祝你编程愉快!

来源

  所有评论均取自以下来源

Visual Studio 中的数据集工具

演练:在 Visual Studio 中创建本地数据库文件

Database.Refresh 方法 ()

如何:生成更改脚本

创建和配置 TableAdapters

演练:创建数据表之间的关系

如何:编辑连接字符串

如何:使用数据集设计器创建 DataRelations

DataRelation 对象简介

关系对话框:仅关系,还是带外键约束?

关系对话框

如何:用数据填充数据集

分层更新

DataColumn.AutoIncrement 属性

将数据保存回数据库

DataGridView.DataSource 属性

在 Visual Studio 中使用数据集

演练:将数据保存到数据库(单表)

使用设计器创建 SQL 数据库

文件属性

使用本地数据库

如何:将数据集更改保存到数据库

如何:从数据库中删除行

13.1.17.5 使用 FOREIGN KEY 约束

SQL Server 中的错误和事务处理

SQL Server Data Tools (SSDT 和 SSDT-BI) 的先前版本

历史

* 发布于 2017年3月15日

* 重新发布于 2017年3月16日

* 更新于 2017年11月29日

© . All rights reserved.