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 中,推理过程将确定这些表的列。对于嵌套表,推理过程会生成嵌套的 DataRelation 和 ForeignKeyConstraint 对象。
下面是推理规则的简要概述:
- 具有属性的元素会被推断为表。
- 具有子元素的元素会被推断为表。
- 重复的元素会被推断为单个表。
- 如果文档元素或根元素不具有将被推断为列的属性和子元素,则该元素将被推断为 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 - 推断关系
- 描述为嵌套的推断表创建的 DataRelation 和 ForeignKeyConstraint 对象。
如果元素包含文本但不包含被推断为表的子元素(如具有属性或重复元素的元素),一个名为“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 关系结构。