ADO.NET中使用DataSet类

ADO.NET中使用DataSet类
ADO.NET DataSet 是数据的一种内存驻留表示形式,无论它包含的数据来自什么数据源,都会提供一致的关系编程模型。DataSet 表示整个数据集,其中包含对数据进行包含、排序和约束的表以及表间的关系。

使用 DataSet 的方法有若干种,这些方法可以单独应用,也可以结合应用。您可以:
以编程方式在 DataSet 中创建 DataTable、DataRelation 和 Constraint,并使用数据填充表。
通过 DataAdapter 用现有关系数据源中的数据表填充 DataSet。
使用 XML 加载和保持 DataSet 内容。
强类型化的 DataSet 也可以使用 XML Web 服务来进行传输。
DataSet 的设计使其成为使用 XML Web 服务传输数据的理想选择。

创建 DataSet   
可以通过调用 DataSet 构造函数来创建 DataSet 的实例。可以选择指定一个名称参数。如果没有为 DataSet 指定名称,则该名称会设置为“NewDataSet”。
也可以基于现有的 DataSet 来创建新的 DataSet。新的 DataSet 可以是:现有 DataSet 的原样副本;DataSet 的复本,它复制关系结构(即架构)但不包含现有 DataSet 中的任何数据;或 DataSet 的子集,它仅包含现有 DataSet 中已使用 GetChanges 方法修改的行。
以下代码示例演示了如何构造 DataSet 的实例。
Visual Basic
Dim customerOrders As DataSet = New DataSet("CustomerOrders")
C#
DataSet customerOrders = new DataSet("CustomerOrders");

向 DataSet 添加 DataTable  

ADO.NET 使您能够创建 DataTable 对象并将其添加到现有 DataSet 中。可以使用 PrimaryKey 和 Unique 属性为 DataTable 设置约束信息。

区分大小写
DataSet 中可以存在两个或两个以上的同名但是大小写不同的表或关系。在这种情况下,通过名称对表和关系的引用将区分大小写。例如,如果 DataSet dataSet 包含表 Table1 和 table1,则将通过名称将 Table1 作为 dataSet.Tables["Table1"] 来引用,而将 table1 作为 dataSet.Tables["table1"] 来引用。如果试图将其中任一个表作为 dataSet.Tables["TABLE1"] 来引用,则会生成异常。

注 意
DataSet 的 CaseSensitive 属性不影响此行为。CaseSensitive 属性应用于 DataSet 中的数据,并会影响排序、搜索、筛选、执行约束,等等。

命名空间支持
在早期版本的 ADO.NET 中,两个表不能同名,即使是处于不同的命名空间。ADO.NET 2.0 中已经取消了此限制。DataSet 可以包含具有相同 TableName 属性值但是具有不同 Namespace 属性值的两个表。

如果只有一个具有特定名称的表或关系,则区分大小写行为不适用。例如,如果 DataSet 只包含 Table1,则可以使用 dataSet.Tables["TABLE1"] 来引用。

添加表间关系   
在包含多个 DataTable 对象的 DataSet 中,可以使用 DataRelation 对象来使一个表与另一个表相关,在多个表之间导航,以及从相关表中返回子行或父行。

创建 DataRelation 所需的参数是所创建的 DataRelation 的名称以及对用作关系中父列和子列的那些列的一个或多个 DataColumn 引用的数组。当创建 DataRelation 后,可以使用它在多个表之间导航和检索值。
默认情况下,向 DataSet 中添加 DataRelation 会将一个 UniqueConstraint 添加到父表中并将一个 ForeignKeyConstraint 添加到子表中。有关这些默认约束的更多信息,请参见将约束添加到表。

以下代码示例使用 DataSet 中的两个 DataTable 对象来创建一个 DataRelation。每个 DataTable 包含一个名为 CustID 的列,它用作两个 DataTable 对象之间的链接。该示例将单个 DataRelation 添加到 DataSet 的 Relations 集合中。该示例中的第一个参数指定所创建的 DataRelation 的名称。第二个参数设置父 DataColumn,第三个参数设置子 DataColumn。
Visual Basic
  customerOrders.Relations.Add(/"CustOrders/", _
  customerOrders.Tables(/"Customers/").Columns(/"CustID/"), _
  customerOrders.Tables(/"Orders/").Columns(/"CustID/"))

C#
  customerOrders.Relations.Add(/"CustOrders/",
  customerOrders.Tables[/"Customers/"].Columns[/"CustID/"],
  customerOrders.Tables[/"Orders/"].Columns[/"CustID/"]);

DataRelation 也具有 Nested 属性,如果该属性设置为 true,则来自子表的行会在使用 WriteXml 以 XML 元素形式编写时嵌套在来自父表的关联行中。

浏览表间关系
DataRelation 的一项主要功能就是在 DataSet 中从一个 DataTable 浏览到另一个。它使您能够在给定相关 DataTable 中的单个 DataRow 的情况下检索一个 DataTable 中的所有相关 DataRow 对象。例如,当建立客户表和订单表之间的 DataRelation 后,可以使用 GetChildRows 检索特定客户行的所有订单行。

如果子列可能包含父列不包含的值,添加 DataRelation 时请将 createConstraints 标志设置为 false。

将 DataSet 与现有数据一起使用  
DataSet 是数据的一种内存中关系表示形式,它独立于任何数据源。但是,当用于 .NET Framework 数据提供程序时,DataSet 可以与数据源中的现有数据一起使用。.NET Framework 数据提供程序通过 DataAdapter 使用数据和架构信息填充 DataSet,并将更改解析回数据源中的数据。

合并DataSet 内容
可以使用 DataSet 的 Merge 方法将 DataSet、DataTable 或 DataRow 数组的内容并入现有 DataSet。以下几个因素和选项会影响新数据并入现有 DataSet 的方式。

主键
如果从合并中接收新数据和架构的表具有主键,则传入数据中的新行将与相应的现有行进行匹配,这些现有行与传入数据中的行具有相同的 original 主键值。如果传入架构中的列匹配现有架构的相应列,则会修改现有行中的数据。对于不匹配现有架构的列,将根据 MissingSchemaAction 参数(请参见本主题后面部分的“MissingSchemaAction”)来忽略或添加。如果新行的主键值不匹配任何现有行,则会将新行追加到现有表。

如果传入行或现有行的行状态为 Added,由于不存在 original 行版本,所以会使用 Added 行的 Current 主键值匹配这些行的主键值。

如果传入表和现有表包含名称相同但数据类型不同的列,则将引发异常并引发 DataSet 的 MergeFailed 事件。如果传入表和现有表都已定义键,但主键用于不同的列,则将引发异常并引发 DataSet 的 MergeFailed 事件。

如果从合并中接收新数据的表不具有主键,传入数据中的新行将无法与该表中的现有行匹配,而这些新行则会追加到现有表。

preserveChanges
当您将 DataSet、DataTable 或 DataRow 数组传递给 Merge 方法时,可以包含一些可选参数,指定是否在现有 DataSet 中保留更改以及如何处理传入数据中的新架构元素。传入数据之后第一个这样的参数为布尔标志 preserveChanges,指定是否在现有 DataSet 中保留更改。如果 preserveChanges 标志设置为 true,传入值将不会重写现有行 Current 行版本中的现有值。如果 preserveChanges 标志设置为 false,传入值则将重写现有行 Current 行版本中的现有值。如果未指定 preserveChanges 标志,将设置为默认值 false。有关行版本的更多信息,请参见行状态与行版本。

当 preserveChanges 为 true 时,现有行中的数据在现有行的 Current 行版本中进行维护,而传入行 original 行版本中的数据将重写现有行 original 行版本中的数据。现有行的 RowState 设置为 Modified。存在以下例外:

如果现有行的 RowState 为 Deleted,此 RowState 将仍为 Deleted 而不会设置为 Modified。在这种情况下,传入行中的数据仍存储在现有行的 original 行版本中,并重写现有行的 original 行版本(除非传入行的 RowState 为 Added)。

如果传入行的 RowState 为 Added,由于传入行不具有 original 行版本,传入行中的数据将不会重写现有行 original 行版本中的数据。

当 preserveChanges 为 false 时,传入行中的数据将重写现有行中的 Current 和 original 行版本,而现有行的 RowState 将设置为传入行的 RowState。存在以下例外:

如果传入行的 RowState 为 Unchanged 而现有行的 RowState 为 Modified、Deleted 或 Added,则现有行的 RowState 将设置为 Modified。

如果传入行的 RowState 为 Added 而现有行的 RowState 为 Unchanged、Modified 或 Deleted,则现有行的 RowState 将设置为 Modified。另外,由于传入行不具有 original 行版本,传入行中的数据不会重写现有行 original 行版本中的数据。

MissingSchemaAction
可以使用 Merge 方法的可选 MissingSchemaAction 参数来指定 Merge 如何处理传入数据中不属于现有 DataSet 的架构元素。

约束
当使用 Merge 方法时,直到所有新数据都已添加到现有 DataSet 中后,才会检查约束。数据一旦添加,将对 DataSet 中的当前值强制约束。您必须确保您的代码可以处理可能因约束冲突而引发的任何异常。

请考虑以下示例:DataSet 中的现有行是主键值为 1 的 Unchanged 行。在与 original 主键值为 2 并且 Current 主键值为 1 的 Modified 传入行合并的过程中,由于 original 主键值不同,因此不认为现有行与传入行匹配。不过,当完成合并并检查约束后,由于 Current 主键值违反主键列的唯一约束,因此将引发异常。

Visual Basic
Using connection As SqlConnection = New SqlConnection( _
   connectionString)

    Dim adapter As SqlDataAdapter = New SqlDataAdapter( _
      /"Select CustomerID, CompanyName FROM Customers/", connection)

    connection.Open()

    Dim customers As DataSet = New DataSet()
    adapter.FillSchema(customers, SchemaType.Source, /"Customers/")
    adapter.Fill(customers, /"Customers/")

    Dim orders As DataSet = New DataSet()
    orders.ReadXml(/"Orders.xml/", XmlReadMode.ReadSchema)
    orders.AcceptChanges()

    customers.Merge(orders, True, MissingSchemaAction.AddWithKey)


C#
using (SqlConnection connection =
           new SqlConnection(connectionString))
{
    SqlDataAdapter adapter =
        new SqlDataAdapter(
        /"Select CustomerID, CompanyName FROM dbo.Customers/",
        connection);

    connection.Open();

    DataSet customers = new DataSet();
    adapter.FillSchema(customers, SchemaType.Source, /"Customers/");
    adapter.Fill(customers, /"Customers/");

    DataSet orders = new DataSet();
    orders.ReadXml(/"Orders.xml/", XmlReadMode.ReadSchema);
    orders.AcceptChanges();

    customers.Merge(orders, true, MissingSchemaAction.AddWithKey);


使用 DataSet 事件
DataSet 提供 MergeFailed 事件,该事件在所合并的 DataSet 对象的架构发生冲突时引发。例如,如果所合并的表的主键列在两个 DataSet 对象中的表之间有所不同,则将引发异常并引发 MergeFailed 事件。传递给 MergeFailed 事件的 MergeFailedEventArgs 具有 Conflict 属性(标识两个 DataSet 对象之间的架构冲突)和 Table 属性(标识发生冲突的表的名称)。
以下代码示例将 MergeFailed 事件添加到一个事件处理程序中。

Visual Basic
Dim workDS As DataSet = New DataSet

AddHandler workDS.MergeFailed, New MergeFailedEventHandler( _
  AddressOf DataSetMergeFailed)

Private Shared Sub DataSetMergeFailed(  _
  sender As Object,args As MergeFailedEventArgs)
  Console.WriteLine(/"Merge failed for table /" & args.Table.TableName)
  Console.WriteLine(/"Conflict = /" & args.Conflict)
End Sub


C#
DataSet workDS = new DataSet();

workDS.MergeFailed += new MergeFailedEventHandler(DataSetMergeFailed);

private static void DataSetMergeFailed(
  object sender, MergeFailedEventArgs args)
{
  Console.WriteLine(/"Merge failed for table /" + args.Table.TableName);
  Console.WriteLine(/"Conflict = /" + args.Conflict);
}


在 DataSet 中使用 XML  
通过 ADO.NET,您可以从 XML 流或文档填充 DataSet。可以使用 XML 流或文档向 DataSet 提供数据和/或架构信息。从 XML 流或文档中提供的信息可以与已存在于 DataSet 中的现有数据或架构信息进行组合。

为了通过 HTTP 将 DataSet 传输给其他应用程序或启用了 XML 的平台来使用,ADO.NET 还允许您创建 DataSet 的 XML 表示形式(包含或不包含架构)。在 DataSet 的 XML 表示形式中,数据以 XML 形式编写,而架构若以内联形式包含在该表示形式中时,则使用 XML 架构定义语言 (XSD) 来编写。XML 和 XML 架构提供一种方便的格式与远程客户端之间来回传输 DataSet 的内容。

ADO.NET DataSet 的内容可以从 XML 流或文档创建。此外,利用 .NET Framework,您可以相当灵活地控制从 XML 中加载哪些信息以及如何创建 DataSet 的架构(即关系结构)。

若要使用 XML 中的数据填充 DataSet,请使用 DataSet 对象的 ReadXml 方法。该 ReadXml 方法将从文件、流或 XmlReader 中进行读取,并将 XML 的源以及可选的 XmlReadMode 参数用作参数。ReadXml 方法读取 XML 流或文档的内容并将数据加载到 DataSet 中。根据所指定的 XmlReadMode 以及关系架构是否已存在,它还将创建 DataSet 的关系架构。

如果调用 ReadXml 来加载非常大的文件,则性能可能会下降。为确保最佳的 ReadXml 性能,对于大文件,请为 DataSet 中的每个表调用 BeginLoadData 方法,然后调用 ReadXml。最后,为 DataSet 中的每个表调用 EndLoadData,如下面的示例所示。
Visual Basic
Dim dataTable As DataTable

For Each dataTable In dataSet.Tables
   dataTable.BeginLoadData()
Next

dataSet.ReadXml(/"file.xml/")

For Each dataTable in dataSet.Tables
   dataTable.EndLoadData()
Next


C#
foreach (DataTable dataTable in dataSet.Tables)
   dataTable.BeginLoadData();

dataSet.ReadXml(/"file.xml/");

foreach (DataTable dataTable in dataSet.Tables)
   dataTable.EndLoadData();


如果您的 DataSet 的 XML 架构包含 targetNamespace,则可能无法读取数据,而且在调用 ReadXml 以加载所含 XML 中包含的元素有非限定命名空间的 DataSet 时,可能会发生异常。在这种情况下,若要读取未限定的元素,请在 XSD 架构中将 elementFormDefault 设置为等于“qualified”。

合并 XML 中的数据
如果 DataSet 已经包含数据,则会向已存在于 DataSet 中的数据添加 XML 中的新数据。ReadXml 不会从 XML 向 DataSet 中并入任何具有匹配主键的行信息。若要使用 XML 中的新信息重写现有行信息,请使用 ReadXml 创建一个新的 DataSet,然后使用 Merge 将新 DataSet 并入现有 DataSet。请注意,如果使用 XmlReadMode 为 DiffGram 的 ReadXML 来加载 DiffGram,则将合并具有相同唯一标识符的行。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值