2008-09-26 10 views
1

Je me demande quelles sont les meilleures pratiques pour stocker une structure de données relationnelle en XML. Particulièrement, je m'interroge sur les meilleures pratiques pour faire respecter l'ordre des nœuds. Par exemple, dire que j'ai trois objets: School, Course et Student, qui sont définis comme suit:Stockage de données relationnelles en XML

class School 
{ 
    List<Course> Courses; 
    List<Student> Students; 
} 

class Course 
{ 
    string Number; 
    string Description; 
} 

class Student 
{ 
    string Name; 
    List<Course> EnrolledIn; 
} 

Je stockerait une telle structure de données en XML comme ceci:

<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> 

Avec la XML ordonné de cette façon, je peux d'abord analyser Courses. Ensuite, lorsque j'analyse Students, je peux rechercher chaque Course répertorié dans EnrolledIn (par son Number) dans la liste School.Courses. Cela me donnera une référence d'objet à ajouter à la liste EnrolledIn dans Student. Si Students, cependant, vient avantCourses, une telle recherche pour obtenir une référence d'objet n'est pas possible. (Puisque School.Courses n'a pas encore été rempli.)

Alors, quelles sont les meilleures pratiques pour stocker des données relationnelles en XML? - Devrais-je exiger que Courses doive toujours précéder Students? - Dois-je tolérer toute commande et créer un objet Course chaque fois que j'en rencontre un que je n'ai pas encore vu? (A être étendu lorsque la définition du Course sera finalement atteinte plus tard.) - Existe-t-il un autre moyen de persister/charger mes objets de/vers XML? (Je suis actuellement implémenté Save et Load méthodes sur tous mes objets métier et de faire tout cela manuellement à l'aide System.Xml.XmlDocument et ses classes associées.)

Je suis habitué à travailler avec des données relationnelles sur SQL, mais c'est ma première expérience éprouvante pour stocker une structure de données relationnelle non triviale en XML. Tout conseil que vous pourriez fournir sur la façon dont je devrais procéder serait grandement apprécié.

Répondre

2

Ne pensez pas en SQL ou relationnel lorsque vous travaillez avec XML, car il n'y a pas de contraintes de commande.

Vous pouvez toutefois interroger XPath sur n'importe quelle partie du document XML à tout moment. Vous voulez les cours d'abord, puis "// Cours/Cours". Vous voulez les inscriptions des étudiants ensuite, puis "// Students/Student/EnrolledIn/Course". La ligne du bas étant ... juste parce que XML est stocké dans un fichier, ne soyez pas pris en pensant que tous vos accès sont en série.


J'ai posté une question distincte, "Can XPath do a foreign key lookup across two subtrees of an XML?", afin de clarifier ma position. La solution montre comment vous pouvez utiliser XPath pour effectuer des requêtes relationnelles sur des données XML.

0

Par expérience, XML n'est pas le meilleur pour stocker des données relationnelles. Avez-vous enquêté YAML? Avez-vous l'option? Si vous ne le faites pas, un moyen sûr serait d'avoir une DTD stricte pour le XML et de l'appliquer de cette façon. Vous pourriez également, comme vous le suggérez, garder un hachage d'objets créés. De cette façon, si un étudiant crée un cours, vous le gardez pour une prochaine mise à jour lorsque le tag est frappé. N'oubliez pas que vous pouvez utiliser des requêtes XPath pour accéder directement à des nœuds spécifiques, afin de pouvoir appliquer d'abord l'analyse des cours, quelle que soit leur position dans le document XML. (en donnant une réponse plus complète grâce à dacracot)

+0

J'ai entendu parler de YAML, mais je ne l'ai pas utilisé. A-t-il intégré le support dans .NET? –

+0

Il existe une implémentation sourceforge .NET de YAML: http://yaml-net-parser.sourceforge.net/default.html – Instantsoup

2

Bien que vous puissiez spécifier l'ordre des éléments enfants en utilisant une séquence xsd: <>, en demandant aux objets enfants de venir dans un ordre spécifique, vous rendre votre système moins flexible (c.-à-d. mettre à jour en utilisant le bloc-notes).

La meilleure chose à faire est d'analyser toutes vos données, puis d'effectuer les actions que vous devez faire. N'agissez pas pendant l'analyse.


De toute évidence, la conception du XML et les données derrière elle empêche la sérialisation d'un seul POCO XML. Vous devez contrôler la logique de sérialisation et de désérialisation afin de décrocher et de reconnecter les objets ensemble.

Je suggère de créer un sérialiseur personnalisé qui construit la représentation XML de ce graphe d'objet. Il peut ainsi contrôler non seulement l'ordre de sérialisation, mais aussi gérer les situations où les nœuds ne sont pas dans l'ordre attendu. Vous pouvez faire d'autres choses telles que l'ajout d'attributs personnalisés à utiliser pour lier des objets ensemble qui n'existent pas en tant que propriétés publiques sur les objets en cours de sérialisation. Créer le fichier XML serait aussi simple que de répéter plusieurs fois vos objets, en créant des collections de XElements avec la représentation attendue des objets en tant que xml. Lorsque vous avez terminé, vous pouvez les assembler dans un XDocument et en extraire le XML. Vous pouvez faire plusieurs passes sur le xml au verso pour recréer votre graphe d'objet et restaurer toutes les références.

+0

Bonne idée. Comment cela est-il habituellement mis en œuvre? Créez-vous une structure de données intermédiaire complète pour conserver les valeurs de votre analyse avant de les convertir en objets métier? –

+0

En utilisant une analyse DOM plutôt qu'une analyse SAX, vous aurez toute la structure en mémoire et pourrez ensuite effectuer des requêtes d'accès aléatoire en utilisant XPath. – dacracot

+0

Oh oui vous pouvez imposer l'ordre des enfants en XML en utilisant un schéma XML (XSD) et en spécifiant une séquence. –

0

La commande n'est généralement pas importante en XML. Dans ce cas, le Courses pourrait venir après Students. Vous analysez le XML et ensuite vous faites vos requêtes sur l'ensemble des données.

0

XML n'est certainement pas un endroit convivial pour les données relationnelles.

Si vous avez absolument besoin de faire cela, alors je recommanderais un genre de logique inversée funky. Dans votre exemple, vous avez Schools, qui propose de nombreux cours, pris par de nombreux étudiants.

Votre XML peut suivre en tant que tel:

<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> 

Ceci est évidemment pas la moindre façon répétitive le faire (ses données relationnelles!), Mais il est en mesure parse-facilement.

+0

Voir ci-dessous où vous pouvez faire une recherche de clé étrangère en utilisant XPath dans XML. – dacracot

1

La commande de noeud est importante uniquement si vous devez effectuer un traitement uniquement en avant des données, par ex. en utilisant un XmlReader ou un analyseur SAX. Si vous voulez lire le XML dans un DOM avant de le traiter (ce que vous êtes si vous utilisez XmlDocument), l'ordre des nœuds n'a pas vraiment d'importance. Ce qui importe le plus, c'est que le XML soit structuré de sorte que vous puissiez l'interroger efficacement avec XPath, c'est-à-dire sans devoir utiliser "//".

Si vous examinez le schéma produit par DataSetGenerator, vous verrez qu'il n'y a aucun ordre associé aux éléments de niveau DataTable. Il se peut qu'ADO traite des éléments dans une séquence non représentée dans le schéma (par exemple, un DataTable à la fois) ou ADO effectue un traitement uniquement en avant et n'applique pas les contraintes relationnelles jusqu'à ce que le DataSet soit entièrement lu. Je ne sais pas. Mais il est clair qu'ADO ne couple pas l'ordre de traitement à l'ordre du document.

(Et oui, vous pouvez spécifier l'ordre des éléments enfants dans un schéma XML, c'est ce que fait xs: sequence.Si vous ne voulez pas que l'ordre des nœuds soit appliqué, vous utilisez un choix xs: non borné.)

0

Vous pouvez également utiliser deux fichiers XML, un pour les cours et un second pour les étudiants. Ouvrez et analysez le premier avant de faire le second.

0

J'a été un certain temps, mais je crois me souvenir faire une collection de base de « choses » dans une partie d'un fichier xml, et en se référant à eux dans un autre en utilisant le schéma caractéristiques keyref et se réfèrent. J'ai trouvé quelques exemples here. Mes excuses si ce n'est pas ce que vous cherchez.

Questions connexes