繁体   English   中英

以XML存储关系数据

[英]Storing Relational Data in XML

我想知道在XML中存储关系数据结构的最佳实践是什么。 特别是,我想知道执行节点顺序的最佳实践。 例如,假设我有三个对象: SchoolCourseStudent ,它们的定义如下:

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名单。 这将为我提供一个对象引用,以添加到StudentEnrolledIn列表中。 但是,如果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文件的一部分中做过“事物”的基础集合,并使用模式功能keyrefRefer 引用了它们 我在这里找到了一些例子。 如果这不是您想要的,我深表歉意。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM