ADO.NET DataSet 的内容可以从 XML 流或文档创建。 此外,利用 .NET Framework,您可以相当灵活地控制从 XML 中加载哪些信息以及如何创建 DataSet 的架构(即关系结构)。
若要使用 XML 中的数据填充 DataSet ,请使用 DataSet 对象的 ReadXml 方法。 该方法 ReadXml 从文件、流或 XmlReader 中读取,并采用 XML 的源和可选 XmlReadMode 参数作为参数。 有关 XmlReader的详细信息,请参阅 用 XmlTextReader 读取 XML 数据。 该方法 ReadXml 读取 XML 流或文档的内容并加载 DataSet 数据。 它还将根据指定的XmlReadMode以及关系架构是否已存在来创建DataSet的关系架构。
下表描述了参数的选项 XmlReadMode 。
| 选项 | 说明 |
|---|---|
| 自动 | 这是默认值。 检查 XML 并按如下顺序选择最适合的选项: - 如果 XML 是 DiffGram,则使用 DiffGram。- 如果 DataSet 包含架构或 XML 包含内联架构,则使用 ReadSchema。- 如果 DataSet 不包含架构,并且 XML 不包含内联架构, InferSchema 则使用。如果知道要读取的 XML 的格式,为了获得最佳性能,建议设置显式 XmlReadMode,而不是接受 Auto 默认值。 |
| ReadSchema | 读取内联架构并加载数据和架构。 如果 DataSet 已包含架构,则新表将从内联架构添加到 DataSet 中的现有架构。 如果 DataSet 中已存在内联架构中的任何表,则将引发异常。 您将无法使用 XmlReadMode.ReadSchema 来修改现有表的架构。 如果 DataSet 不包含架构,并且没有内联架构,则不会读取任何数据。 内联架构可以使用 XML 架构定义语言 (XSD) 架构来定义。 有关将内联架构作为 XML 架构写入的详细信息,请参阅从 Xml 架构派生数据集关系结构 (XSD)。 |
| IgnoreSchema | 忽略任何内联架构并将数据加载到现有的 DataSet 架构中。 任何与现有架构不匹配的数据都将被丢弃。 如果 DataSet 中不存在任何架构,则不会加载任何数据。 如果数据是 DiffGram, IgnoreSchema 则具有与 DiffGram相同的功能。 |
| InferSchema | 忽略任何内联架构并按照 XML 数据的结构推断架构,然后加载数据。 如果 DataSet 已经包含架构,则会通过向现有表中添加列来扩展当前架构。 如果不存在表,则不会添加其他表。 如果已存在具有不同命名空间的推断表或者任何推断表与现有列发生冲突,则会引发异常。 有关如何从 XML 文档推断架构的详细信息 ReadXmlSchema ,请参阅 从 XML 推断数据集关系结构。 |
| DiffGram | 读取 DiffGram 并将数据添加到当前架构中。
DiffGram 将新行与唯一标识符值匹配的现有行合并。 请参见本主题末尾的“合并 XML 中的数据”。 有关 DiffGrams 的更多信息,请参见 DiffGrams。 |
| 片段 | 持续读取多个 XML 片断,直至到达流的末尾。 与 DataSet 架构匹配的片断会追加到相应的表。 与 DataSet 架构不匹配的片断将被丢弃。 |
备注
如果将定位在 XML 文档中某个位置的 XmlReader 传递给 ReadXml,那么 ReadXml 将读取到下一个元素节点,并将其视为根元素,只读取到元素节点的末尾。 这在指定 XmlReadMode.Fragment 时不适用。
DTD 实体
如果您的 XML 包含在文档类型定义(DTD)模式中定义的实体,当您尝试通过传递文件名、流或非验证方式的 XmlReader 来加载 DataSet 到 ReadXml 时,将会引发异常。 相反,您必须创建一个 XmlValidatingReader,并将其EntityHandling设置为 EntityHandling.ExpandEntities,然后将您的XmlValidatingReader传递给 ReadXml。
XmlValidatingReader将在被DataSet读取之前展开这些实体。
以下代码示例显示如何从 XML 流中加载 DataSet。 第一个示例显示要传递给方法的 ReadXml 文件名。 第二个示例显示一个字符串,包含使用 StringReader 加载的 XML。
Dim dataSet As DataSet = New DataSet
dataSet.ReadXml("input.xml", XmlReadMode.ReadSchema)
DataSet dataSet = new DataSet();
dataSet.ReadXml("input.xml", XmlReadMode.ReadSchema);
Dim dataSet As DataSet = New DataSet
Dim dataTable As DataTable = New DataTable("table1")
dataTable.Columns.Add("col1", Type.GetType("System.String"))
dataSet.Tables.Add(dataTable)
Dim xmlData As String = "<XmlDS><table1><col1>Value1</col1></table1><table1><col1>Value2</col1></table1></XmlDS>"
Dim xmlSR As System.IO.StringReader = New System.IO.StringReader(xmlData)
dataSet.ReadXml(xmlSR, XmlReadMode.IgnoreSchema)
DataSet dataSet = new DataSet();
DataTable dataTable = new DataTable("table1");
dataTable.Columns.Add("col1", typeof(string));
dataSet.Tables.Add(dataTable);
string xmlData = "<XmlDS><table1><col1>Value1</col1></table1><table1><col1>Value2</col1></table1></XmlDS>";
System.IO.StringReader xmlSR = new System.IO.StringReader(xmlData);
dataSet.ReadXml(xmlSR, XmlReadMode.IgnoreSchema);
备注
如果调用 ReadXml 加载非常大的文件,可能会遇到性能缓慢的问题。 为确保最佳的 ReadXml 性能,对于大文件,请为 中的每个表调用 BeginLoadData 方法,然后调用 ReadXml。 最后,为 EndLoadData 中的每个表调用 DataSet,如下面的示例所示。
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
foreach (DataTable dataTable in dataSet.Tables)
dataTable.BeginLoadData();
dataSet.ReadXml("file.xml");
foreach (DataTable dataTable in dataSet.Tables)
dataTable.EndLoadData();
备注
如果您的DataSet的 XSD 架构中包含targetNamespace,则可能无法读取数据,并且在调用ReadXml以加载包含无限定命名空间元素的 XML 时,可能会遇到异常。 若要在此示例中读取不限定元素,请在 XSD 架构中将 elementFormDefault 设置为 “qualified”。 例如:
<xsd:schema id="customDataSet"
elementFormDefault="qualified"
targetNamespace="http://www.tempuri.org/customDataSet.xsd"
xmlns="http://www.tempuri.org/customDataSet.xsd"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
</xsd:schema>
合并 XML 中的数据
如果 DataSet 已经包含数据,则会向已存在于 DataSet 中的数据添加 XML 中的新数据。
ReadXml 不会将具有匹配主键的任何行信息从 XML 中合并到 DataSet。 若要使用 XML 中的新信息覆盖现有行信息,请使用 ReadXml 创建新 DataSet行信息,然后将 Merge 新 DataSet 信息添加到现有 DataSet行中。 请注意,使用 ReadXML 和 XmlReadModeDiffGram 将合并具有相同唯一标识符的行。