[英]Storing Relational Data in XML
我想知道在XML中存储关系数据结构的最佳实践是什么。 特别是,我想知道执行节点顺序的最佳实践。 例如,假设我有三个对象: School
, Course
和Student
,它们的定义如下:
class School
{
List<Course> Courses;
List<Student> Students;
}
class Course
{
string Number;
string Description;
}
class Student
{
string Name;
List<Course> EnrolledIn;
}
我将这样的数据结构存储在XML中,如下所示:
<School>
<Courses>
<Course Number="ENGL 101" Description="English I" />
<Course Number="CHEM 102" Description="General Inorganic Chemistry" />
<Course Number="MATH 103" Description="Trigonometry" />
</Courses>
<Students>
<Student Name="Jack">
<EnrolledIn>
<Course Number="CHEM 102" />
<Course Number="MATH 103" />
</EnrolledIn>
</Student>
<Student Name="Jill">
<EnrolledIn>
<Course Number="ENGL 101" />
<Course Number="MATH 103" />
</EnrolledIn>
</Student>
</Students>
</School>
通过这种方式订购XML,我可以首先解析Courses
。 然后,当我分析Students
,我可以查看每个Course
中列出EnrolledIn
(其Number
在) School.Courses
名单。 这将为我提供一个对象引用,以添加到Student
的EnrolledIn
列表中。 但是,如果Students
在 Courses
之前来了,则无法进行这种查找以获取对象引用。 (自School.Courses
以来尚未填充。)
那么在XML中存储关系数据的最佳实践是什么? -我是否应该强制要求Courses
必须始终摆在Students
面前? -每当遇到未见过的对象时,是否应该允许任何顺序并创建存根Course
对象? (将在稍后最终定义Course
时进行扩展。)-是否还有其他方法可以将对象持久化到XML中或从XML中加载对象? (我目前正在所有业务对象上实现Save
and Load
方法,并使用System.Xml.XmlDocument
及其关联的类手动完成所有操作。)
我习惯于使用SQL之外的关系数据,但这是我第一次尝试以XML存储非平凡的关系数据结构的经验。 您能提供有关我应该如何进行的任何建议,将不胜感激。
虽然可以使用<xsd:sequence>指定子元素的顺序,但是通过要求子对象按特定顺序排列,则会使系统的灵活性降低(即,更难使用记事本更新)。
最好的办法是解析所有数据,然后执行需要执行的操作。 在解析期间不要行动。
显然,XML的设计及其背后的数据使得无法将单个POCO序列化为XML。 您需要控制序列化和反序列化逻辑,以将对象解钩和重新钩在一起。
我建议创建一个自定义的序列化程序,以构建该对象图的xml表示形式。 因此,它不仅可以控制序列化的顺序,还可以处理节点不在预期顺序中的情况。 您可以执行其他操作,例如添加自定义属性以将对象链接在一起,而这些属性在序列化对象上不作为公共属性存在。
创建xml就像遍历对象几次一样简单,使用对象的预期表示形式以xml的形式构建XElement的集合。 完成后,您可以将它们缝合在一起成为XDocument并从中获取xml。 您可以在反面的xml上进行多次传递,以重新创建对象图并恢复所有引用。
使用XML时不要考虑使用SQL或关系式,因为没有顺序限制。
但是,您可以随时使用XPath查询XML文档的任何部分。 您首先要课程,然后是“ //课程/课程”。 您要接下来的学生入学,然后是“ //学生/学生/已入学/课程”。
最重要的是...仅仅因为XML存储在文件中,所以不要以为您的所有访问都是串行访问就可以了。
我发布了一个单独的问题, “ XPath可以在XML的两个子树之间执行外键查找吗?” ,以阐明我的立场。 该解决方案说明了如何使用XPath对XML数据进行关系查询。
仅当您需要对数据进行仅前向处理(例如,使用XmlReader或SAX解析器)时,节点顺序才重要。 如果要在处理XML之前将XML读取到DOM中(如果使用的是XmlDocument,则是XML),则节点顺序并不重要。 更重要的是XML的结构使得您可以有效地使用XPath查询它,即不必使用“ //”。
如果您看一下DataSetGenerator生成的模式,您会发现与DataTable级元素没有任何关联。 可能是ADO以某种未在架构中表示的顺序处理元素(例如,一次只能处理一个DataTable),也可能是ADO执行仅前向处理并且不强制执行关系约束,直到完全读取DataSet为止。 我不知道。 但是很明显,ADO不会将处理顺序与文档顺序耦合在一起。
(是的,您可以在XML模式中指定子元素的顺序;这就是xs:sequence的作用。如果您不希望强制执行节点顺序,请使用无限制的xs:choice。)
从经验来看,XML并不是存储关系数据的最佳方法。 您调查过YAML吗? 你有选择吗?
如果您不这样做,一种安全的方法是为XML设置严格的DTD并强制执行该方法。 如您所建议,您还可以保留创建的对象的哈希。 这样,如果学生创建课程,则可以保留该课程,以便将来在命中标签时进行更新。
还要记住,您可以使用XPath查询直接访问特定的节点,因此无论XML文档中的位置如何,都可以首先强制进行课程分析。 (感谢dacracot,使答案更加完整)
在XML中,顺序通常并不重要。 在这种情况下, Courses
可以紧随Students
之后。 您解析XML,然后对整个数据进行查询。
XML绝对不是关系数据的友好之地。
如果您绝对需要这样做,那么我建议您使用一种时髦的倒置逻辑。
在您的示例中,您拥有学校,该学校提供许多学生参加的许多课程。
您的XML可能如下所示:
<School>
<Students>
<Student Name="Jack">
<EnrolledIn>
<Course Number="CHEM 102" Description="General Inorganic Chemistry" />
<Course Number="MATH 103" Description="Trigonometry" />
</EnrolledIn>
</Student>
<Student Name="Jill">
<EnrolledIn>
<Course Number="ENGL 101" Description="English I" />
<Course Number="MATH 103" Description="Trigonometry" />
</EnrolledIn>
</Student>
</Students>
</School>
这显然不是执行此操作的最重复的方法(它是关系数据!),但是它很容易解析。
您还可以使用两个XML文件,一个用于课程,另一个用于学生。 打开并解析第一个,然后再执行第二个。
我已经有一段时间了,但是我似乎还记得在xml文件的一部分中做过“事物”的基础集合,并使用模式功能keyref和Refer 引用了它们 。 我在这里找到了一些例子。 如果这不是您想要的,我深表歉意。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.