DataSet因子表同名导致XML数据在DataGridView1中显示异常
解决DataSet读取XML时同名子表合并导致的数据显示问题
DataSet默认会根据XML元素名称推断表结构,当不同父节点下存在同名子元素(如示例中Gases和Actions下的Record)时,会将这些子元素合并到同一个DataTable中,导致无法直接通过子表名区分数据。以下是无需指定固定表名的通用解决方案:
修改后的核心代码
调整comboBox1_SelectedIndexChanged方法,利用DataSet自动生成的层级数据关系,精准获取对应父节点下的子数据:
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) { if (comboBox1.SelectedIndex == 0) { dataGridView1.DataSource = dataSet.Tables[comboBox1.SelectedIndex].DefaultView; return; } string parentTableName = comboBox1.Text; DataTable parentTable = dataSet.Tables[parentTableName]; if (parentTable == null || parentTable.ParentRelations.Count == 0) { dataGridView1.DataSource = null; return; } // 获取父表与主表(Language)的关联关系 DataRelation parentRelation = parentTable.ParentRelations[0]; DataTable mainTable = parentRelation.ParentTable; if (mainTable.Rows.Count == 0) { dataGridView1.DataSource = null; return; } // 获取主表行对应的父表(Gases/Actions)行 DataRow[] parentRows = mainTable.Rows[0].GetChildRows(parentRelation); if (parentRows.Length == 0) { dataGridView1.DataSource = null; return; } DataRow parentRow = parentRows[0]; // 获取父表与子表(Record)的关联关系 if (parentRow.Table.ChildRelations.Count == 0) { dataGridView1.DataSource = null; return; } DataRelation childRelation = parentRow.Table.ChildRelations[0]; // 获取当前父节点下的所有Record子行 DataRow[] childRows = parentRow.GetChildRows(childRelation); if (childRows.Length == 0) { dataGridView1.DataSource = null; return; } // 将子行转换为DataTable并绑定到DataGridView DataTable childTable = childRows.CopyToDataTable(); dataGridView1.DataSource = childTable.DefaultView; }
原理说明
- DataSet读取XML时会自动生成层级关联关系:主表
Language与Gases、Actions分别存在关联,Gases、Actions又各自与Record存在关联。 - 通过
ParentRelations获取父表(Gases/Actions)与主表的关联,再通过GetChildRows拿到主表对应的父表行。 - 接着通过父表的
ChildRelations获取与Record的关联,再次调用GetChildRows拿到当前父节点下的所有Record数据,避免直接读取合并后的Record表。
可选优化(固定结构场景)
如果XML结构固定,可以通过自定义XSD Schema让DataSet直接生成不同的子表名(如GasesRecord、ActionsRecord)。示例XSD片段:
<xs:element name="Gases"> <xs:complexType> <xs:sequence> <xs:element name="Record" type="RecordType" maxOccurs="unbounded" table="GasesRecord"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="Actions"> <xs:complexType> <xs:sequence> <xs:element name="Record" type="RecordType" maxOccurs="unbounded" table="ActionsRecord"/> </xs:sequence> </xs:complexType> </xs:element>
读取时先加载Schema再读取XML:
dataSet.ReadXmlSchema("your-schema.xsd"); dataSet.ReadXml(xmlFile);
内容的提问来源于stack exchange,提问作者Difyaaa Difyaaa
相关产品推荐
相关产品推荐

