DataSet 的关系结构(即架构)由表、列、约束和关系组成。当从 XML 中加载 DataSet 时,可以预定义架构,或者可以从所加载的 XML 显式(或通过推断)创建架构。有关从 XML 中加载 DataSet 的架构和内容的更多信息,如果正在从 XML 创建 DataSet 的架构,首选方法是使用 XML 架构定义语言 (XSD)或 XML 简化数据 (XDR) 来显式指定架构。如果 XML 中没有可用的 XML 架构或 XDR 架构,则可以从 XML 元素和属性的结构推断 DataSet 的架构。
本节通过显示 XML 元素和属性及其结构以及生成的推断 DataSet 架构来描述推断 DataSet 架构的规则。
指定要推断的属性
并非所有出现在 XML 文档中的属性都应包含在推理过程中。由命名空间限定的属性可以包含对 XML 文档重要但对 DataSet 架构不重要的元数据。使用 DataSet.InferXmlSchema,您可以设置要在推理过程中忽略的特定命名空间。
推理过程首先从 XML 文档中确定将哪些元素推断为表。从剩余的 XML 中,推理过程将确定这些表的列。对于嵌套表,推理过程会生成嵌套的 DataRelation 和 ForeignKeyConstraint 对象。
下面是推理规则的简要概述:
- 具有属性的元素会被推断为表。
- 具有子元素的元素会被推断为表。
- 重复的元素会被推断为单个表。
- 如果文档元素或根元素不具有将被推断为列的属性和子元素,则该元素将被推断为 DataSet。否则,文档元素会被推断为表。
- 属性会被推断为列。
- 不具有属性或子元素且不重复的元素会被推断为列。
- 如果元素被推断为表,而这些表嵌套在同样被推断为表的其他元素中,则将在两个表之间创建嵌套的 DataRelation。两个表中都将添加一个名为“TableName_Id”的新主键列,该列由 DataRelation 来使用。两个表之间的 ForeignKeyConstraint 使用“TableName_Id”列来创建。
- 对于被推断为表的元素和包含文本但不包含子元素的元素,将为每个元素的文本创建一个名为“TableName_Text”的新列。如果元素被推断为表并包含文本和子元素,则将忽略文本。
当从 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 文档推断 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
Text2
如果被推断为表的元素具有一个同样被推断为表的子元素,则将在这两个表之间创建 DataRelation。一个名为“ParentTableName_Id”的新列将添加到为父元素创建的表以及为子元素创建的表中。该标识列的 ColumnMapping 属性将设置为 MappingType.Hidden。该列将成为父表的自动递增主键,并将用于两个表之间的 DataRelation。所添加的标识列的数据类型将为 System.Int32,这与其他所有推断的列的数据类型(System.String)不同。还将使用父表和子表中的新列来创建一个 DeleteRule = Cascade 的 ForeignKeyConstraint。
例如,考虑以下 XML:
<DocumentElement>
<Element1>
<ChildElement1 attr1="value1" attr2="value2"/>
<ChildElement2>Text2</ChildElement2>
</Element1>
</DocumentElement>
推理过程将生成两个表:“Element1”和“ChildElement1”。
“Element1”表包含两个列:“Element1_Id”和“ChildElement2”。“Element1_Id”列的 ColumnMapping 属性将设置为 MappingType.Hidden。“ChildElement2”列的 ColumnMapping 属性将设置为 MappingType.Element。“Element1_Id”列将设置为“Element1”表的主键。
“ChildElement1”表将包含三个列:“attr1”、“attr2”和“Element1_Id”。“attr1”列和“attr2”列的 ColumnMapping 属性将设置为 MappingType.Attribute。“Element1_Id”列的 ColumnMapping 属性将设置为 MappingType.Hidden。
DataRelation 和 ForeignKeyConstraint 将使用两个表中的“Element1_Id”列来创建。
数据集:DocumentElement
表:Element1
Element1_Id
ChildElement2
0
Text2
表:ChildElement1
attr1
attr2
Element1_Id
value1
value2
0
数据关系 (DataRelation):Element1_ChildElement1
父表:Element1
父列:Element1_Id
子表:ChildElement1
子列:Element1_Id
嵌套 (Nested):True
外键约束 (ForeignKeyConstraint):Element1_ChildElement1
列:Element1_Id
父表:Element1
子表:ChildElement1
删除规则:级联 (DeleteRule: Cascade)
接受拒绝规则:无 (AcceptRejectRule: None)
如果元素包含文本但不包含被推断为表的子元素(如具有属性或重复元素的元素),一个名为“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 的架构时,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 | Text2 |
如果被推断为表的元素具有一个同样被推断为表的子元素,则将在这两个表之间创建 DataRelation。一个名为“ParentTableName_Id”的新列将添加到为父元素创建的表以及为子元素创建的表中。该标识列的 ColumnMapping 属性将设置为 MappingType.Hidden。该列将成为父表的自动递增主键,并将用于两个表之间的 DataRelation。所添加的标识列的数据类型将为 System.Int32,这与其他所有推断的列的数据类型(System.String)不同。还将使用父表和子表中的新列来创建一个 DeleteRule = Cascade 的 ForeignKeyConstraint。
例如,考虑以下 XML:
<DocumentElement>
<Element1>
<ChildElement1 attr1="value1" attr2="value2"/>
<ChildElement2>Text2</ChildElement2>
</Element1>
</DocumentElement>
推理过程将生成两个表:“Element1”和“ChildElement1”。
“Element1”表包含两个列:“Element1_Id”和“ChildElement2”。“Element1_Id”列的 ColumnMapping 属性将设置为 MappingType.Hidden。“ChildElement2”列的 ColumnMapping 属性将设置为 MappingType.Element。“Element1_Id”列将设置为“Element1”表的主键。
“ChildElement1”表将包含三个列:“attr1”、“attr2”和“Element1_Id”。“attr1”列和“attr2”列的 ColumnMapping 属性将设置为 MappingType.Attribute。“Element1_Id”列的 ColumnMapping 属性将设置为 MappingType.Hidden。
DataRelation 和 ForeignKeyConstraint 将使用两个表中的“Element1_Id”列来创建。
数据集:DocumentElement
表:Element1
Element1_Id
ChildElement2
0
Text2
表:ChildElement1
attr1
attr2
Element1_Id
value1
value2
0
数据关系 (DataRelation):Element1_ChildElement1
父表:Element1
父列:Element1_Id
子表:ChildElement1
子列:Element1_Id
嵌套 (Nested):True
外键约束 (ForeignKeyConstraint):Element1_ChildElement1
列:Element1_Id
父表:Element1
子表:ChildElement1
删除规则:级联 (DeleteRule: Cascade)
接受拒绝规则:无 (AcceptRejectRule: None)
如果元素包含文本但不包含被推断为表的子元素(如具有属性或重复元素的元素),一个名为“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) 显式地指定架构。
如果被推断为表的元素具有一个同样被推断为表的子元素,则将在这两个表之间创建 DataRelation。一个名为“ParentTableName_Id”的新列将添加到为父元素创建的表以及为子元素创建的表中。该标识列的 ColumnMapping 属性将设置为 MappingType.Hidden。该列将成为父表的自动递增主键,并将用于两个表之间的 DataRelation。所添加的标识列的数据类型将为 System.Int32,这与其他所有推断的列的数据类型(System.String)不同。还将使用父表和子表中的新列来创建一个 DeleteRule = Cascade 的 ForeignKeyConstraint。
例如,考虑以下 XML:
<DocumentElement> <Element1> <ChildElement1 attr1="value1" attr2="value2"/> <ChildElement2>Text2</ChildElement2> </Element1> </DocumentElement>
推理过程将生成两个表:“Element1”和“ChildElement1”。
“Element1”表包含两个列:“Element1_Id”和“ChildElement2”。“Element1_Id”列的 ColumnMapping 属性将设置为 MappingType.Hidden。“ChildElement2”列的 ColumnMapping 属性将设置为 MappingType.Element。“Element1_Id”列将设置为“Element1”表的主键。
“ChildElement1”表将包含三个列:“attr1”、“attr2”和“Element1_Id”。“attr1”列和“attr2”列的 ColumnMapping 属性将设置为 MappingType.Attribute。“Element1_Id”列的 ColumnMapping 属性将设置为 MappingType.Hidden。
DataRelation 和 ForeignKeyConstraint 将使用两个表中的“Element1_Id”列来创建。
数据集:DocumentElement
表:Element1
| Element1_Id | ChildElement2 |
|---|---|
| 0 | Text2 |
表:ChildElement1
| attr1 | attr2 | Element1_Id |
|---|---|---|
| value1 | value2 | 0 |
数据关系 (DataRelation):Element1_ChildElement1
父表:Element1
父列:Element1_Id
子表:ChildElement1
子列:Element1_Id
嵌套 (Nested):True
外键约束 (ForeignKeyConstraint):Element1_ChildElement1
列:Element1_Id
父表:Element1
子表:ChildElement1
删除规则:级联 (DeleteRule: Cascade)
接受拒绝规则:无 (AcceptRejectRule: None)
如果元素包含文本但不包含被推断为表的子元素(如具有属性或重复元素的元素),一个名为“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) 显式地指定架构。
浙公网安备 33010602011771号