DataSet 的关系结构(即架构)由表、列、约束和关系组成。当从 XML 中加载 DataSet 时,可以预定义架构,或者可以从所加载的 XML 显式(或通过推断)创建架构。有关从 XML 中加载 DataSet 的架构和内容的更多信息,请参见从 XML 中加载 DataSet从 XML 中加载 DataSet 架构信息

如果正在从 XML 创建 DataSet 的架构,首选方法是使用 XML 架构定义语言 (XSD)(在从 XML 架构 (XSD) 生成 DataSet 关系结构中描述)或 XML 简化数据 (XDR) 来显式指定架构。如果 XML 中没有可用的 XML 架构或 XDR 架构,则可以从 XML 元素和属性的结构推断 DataSet 的架构。

本节通过显示 XML 元素和属性及其结构以及生成的推断 DataSet 架构来描述推断 DataSet 架构的规则。

指定要推断的属性

并非所有出现在 XML 文档中的属性都应包含在推理过程中。由命名空间限定的属性可以包含对 XML 文档重要但对 DataSet 架构不重要的元数据。使用 DataSet.InferXmlSchema,您可以设置要在推理过程中忽略的特定命名空间。有关更多信息,请参见从 XML 中加载 DataSet 架构信息

本节内容

DataSet 架构推理过程概述
提供从 XML 推断 DataSet 架构的规则的简要概述。 

推理过程首先从 XML 文档中确定将哪些元素推断为表。从剩余的 XML 中,推理过程将确定这些表的列。对于嵌套表,推理过程会生成嵌套的 DataRelationForeignKeyConstraint 对象。

下面是推理规则的简要概述:

  • 具有属性的元素会被推断为表。
  • 具有子元素的元素会被推断为表。
  • 重复的元素会被推断为单个表。
  • 如果文档元素或根元素不具有将被推断为列的属性和子元素,则该元素将被推断为 DataSet。否则,文档元素会被推断为表。
  • 属性会被推断为列。
  • 不具有属性或子元素且不重复的元素会被推断为列。
  • 如果元素被推断为表,而这些表嵌套在同样被推断为表的其他元素中,则将在两个表之间创建嵌套的 DataRelation。两个表中都将添加一个名为“TableName_Id”的新主键列,该列由 DataRelation 来使用。两个表之间的 ForeignKeyConstraint 使用“TableName_Id”列来创建。
  • 对于被推断为表的元素和包含文本但不包含子元素的元素,将为每个元素的文本创建一个名为“TableName_Text”的新列。如果元素被推断为表并包含文本和子元素,则将忽略文本。
推断表
描述被推断为 DataSet 中的表的 XML 元素。

当从 XML 文档推断 DataSet 的架构时,ADO.NET 首先会确定哪些 XML 元素表示表。以下 XML 结构将为 DataSet 架构生成一个表。

具有属性的元素

在其中指定了属性的元素将生成推断表。例如,考虑以下 XML:

<DocumentElement>
  <Element1 attr1="value1"/>
  <Element1 attr1="value2">Text1</Element1>
</DocumentElement>

推理过程将生成名为“Element1”的表。

数据集:DocumentElement

表:Element1

attr1 Element1_Text
value1    
value2 Text1

具有子元素的元素

具有子元素的元素将生成推断表。例如,考虑以下 XML:

<DocumentElement>
  <Element1>
    <ChildElement1>Text1</ChildElement1>
  </Element1>
</DocumentElement>

推理过程将生成名为“Element1”的表。

数据集:DocumentElement

表:Element1

ChildElement1
Text1

如果文档元素或根元素具有将被推断为列的属性或子元素,它将生成推断表。如果文档元素不具有将被推断为列的属性和子元素,则该元素将被推断为 DataSet。例如,考虑以下 XML:

<DocumentElement>
  <Element1>Text1</Element1>
  <Element2>Text2</Element2>
</DocumentElement>

推理过程将生成名为“DocumentElement”的表。

数据集:NewDataSet

表:DocumentElement

Element1 Element2
Text1 Text2

或者,考虑以下 XML:

<DocumentElement>
  <Element1 attr1="value1" attr2="value2"/>
</DocumentElement>

推理过程将生成一个名为“DocumentElement”的 DataSet,它包含名为“Element1”的表。

数据集:DocumentElement

表:Element1

attr1 attr2
value1 value2

重复元素

重复的元素将生成单个推断表。例如,考虑以下 XML:

<DocumentElement>
  <Element1>Text1</Element1>
  <Element1>Text2</Element1>
</DocumentElement>

推理过程将生成名为“Element1”的表。

数据集:DocumentElement

表:Element1

Element1_Text
Text1
Text2

推断列
描述被推断为表列的 XML 元素和属性。

当从 XML 文档推断 DataSet 的架构时,ADO.NET 首先确定将哪些元素推断为表,然后从剩余的 XML 元素和属性中确定为这些表推断出哪些列。由于数据类型信息仅在内联架构中才可用,所以推断列的数据类型为 System.String。以下 XML 结构将生成表列。

属性

正如推断表中的定义,具有属性的元素将被推断为表。然后,该元素的属性将被推断为该表的列。这些列的 ColumnMapping 属性将设置为 MappingType.Attribute,以确保列名称将在架构写回 XML 时被写为属性。这些属性的值在表的一行中进行排序。例如,考虑以下 XML:

<DocumentElement>
  <Element1 attr1="value1" attr2="value2"/>
</DocumentElement>

推理过程将生成一个名为“Element1”的表,它包含两个列:“attr1”和“attr2”。这两个列的 ColumnMapping 属性都将设置为 MappingType.Attribute

数据集:DocumentElement

表:Element1

attr1 attr2
value1 value2

不具有属性或子元素的元素

如果元素不具有子元素或属性,它将被推断为列。该列的 ColumnMapping 属性将设置为 MappingType.Element。子元素的文本存储在表的一行中。例如,考虑以下 XML:

<DocumentElement>
  <Element1>
    <ChildElement1>Text1</ChildElement1>
    <ChildElement2>Text2</ChildElement2>
  </Element1>
</DocumentElement>

推理过程将生成一个名为“Element1”的表,它包含两个列:“ChildElement1”和“ChildElement2”。这两个列的 ColumnMapping 属性将设置为 MappingType.Element

数据集:DocumentElement

表:Element1

ChildElement1 ChildElement2
Text1
推断关系
描述为嵌套的推断表创建的 DataRelationForeignKeyConstraint 对象。

如果元素包含文本但不包含被推断为表的子元素(如具有属性或重复元素的元素),一个名为“TableName_Text”的新列将添加到为该元素推断的表中。该元素中包含的文本将添加到此表中的一行,并存储在新列中。新列的 ColumnMapping 属性将设置为 MappingType.SimpleContent

例如,考虑以下 XML:

<DocumentElement>
  <Element1 attr1="value1">Text1</Element1>
</DocumentElement>

推理过程将生成一个名为“Element1”的表,它包含两个列:“attr1”和“Element1_Text”。“attr1”的 ColumnMapping 属性将设置为 MappingType.Attribute。“Element1_Text”列的 ColumnMapping 属性将设置为 MappingType.SimpleContent

数据集:DocumentElement

表:Element1

attr1 Element1_Text
value1 Text1

如果某元素包含文本,并且还具有包含文本的子元素,则不会将列添加到表中来存储该元素所包含的文本。该元素中包含的文本将被忽略,但子元素中的文本将包含在表的一行中。例如,考虑以下 XML:

<Element1>
  Text1
  <ChildElement1>Text2</ChildElement1>
  Text3
</Element1>

推理过程将生成一个名为“Element1”的表,它包含一个名为“ChildElement1”的列。“ChildElement1”元素的文本将包含在表的一行中。其他文本则将被忽略。“ChildElement1”列的 ColumnMapping 属性将设置为 MappingType.Element

数据集:DocumentElement

表:Element1

ChildElement1
Text2
推断元素文本
描述为 XML 元素中的文本创建的列,并解释何时会忽略 XML 元素中的文本。

如果元素包含文本但不包含被推断为表的子元素(如具有属性或重复元素的元素),一个名为“TableName_Text”的新列将添加到为该元素推断的表中。该元素中包含的文本将添加到此表中的一行,并存储在新列中。新列的 ColumnMapping 属性将设置为 MappingType.SimpleContent

例如,考虑以下 XML:

<DocumentElement>
  <Element1 attr1="value1">Text1</Element1>
</DocumentElement>

推理过程将生成一个名为“Element1”的表,它包含两个列:“attr1”和“Element1_Text”。“attr1”的 ColumnMapping 属性将设置为 MappingType.Attribute。“Element1_Text”列的 ColumnMapping 属性将设置为 MappingType.SimpleContent

数据集:DocumentElement

表:Element1

attr1 Element1_Text
value1 Text1

如果某元素包含文本,并且还具有包含文本的子元素,则不会将列添加到表中来存储该元素所包含的文本。该元素中包含的文本将被忽略,但子元素中的文本将包含在表的一行中。例如,考虑以下 XML:

<Element1>
  Text1
  <ChildElement1>Text2</ChildElement1>
  Text3
</Element1>

推理过程将生成一个名为“Element1”的表,它包含一个名为“ChildElement1”的列。“ChildElement1”元素的文本将包含在表的一行中。其他文本则将被忽略。“ChildElement1”列的 ColumnMapping 属性将设置为 MappingType.Element

数据集:DocumentElement

表:Element1

ChildElement1
Text2
推断限制
讨论架构推断的限制。

从 XML 推断 DataSet 的过程不是确定性的,因为根据每个文档中 XML 元素的不同,具有相同预期架构的不同 XML 文档实例可能会生成不同的架构。例如,考虑以下 XML 文档:

Document1:

<DocumentElement>
  <Element1>Text1</Element1>
  <Element1>Text2</Element1>
</DocumentElement>

Document2:

<DocumentElement>
  <Element1>Text1</Element1>
</DocumentElement>

对于“Document1”,由于“Element1”是重复元素,推理过程将生成一个名为“DocumentElement”的 DataSet 和一个名为“Element1”的表。

数据集:DocumentElement

表:Element1

Element1_Text
Text1
Text2

但是,对于“Document2”,推理过程将生成一个名为“NewDataSet”的 DataSet 和一个名为“DocumentElement”的表。由于“Element1”不具有属性和子元素,它将被推断为列。

数据集:NewDataSet

表:DocumentElement

Element1
Text1

这两个 XML 文档可能本应生成相同的架构,但根据每个文档中包含的不同元素,推理过程生成了极不相同的结果。

若要避免在从 XML 文档生成架构时可能出现的差异,建议在从 XML 中加载 DataSet 时使用 XML 架构定义语言 (XSD) 或 XML 简化数据 (XDR) 显式地指定架构。有关使用 XML 架构显式指定 DataSet 架构的更多信息,请参见从 XML 架构 (XSD) 生成 DataSet 关系结构