2009-05-15 10 views
2

Nous stockons la définition de base de données au format XML à la fin de cette question. Le problème que j'ai est obtenant une liste de schémas, les tables dans ces schémas, les colonnes dans ces tables (toutes avec leurs informations associées). Mon code actuel (inclus sous l'exemple XML) saisit tout, ignorant complètement l'imbrication et, en raison des multiples schémas, renvoie chaque table/colonne plusieurs fois.Linq to XML pour générer des DDL

XML Exemple:

<schemas> 
    <schema> 
     <name>schema_name1</name> 
     <tables> 
      <table> 
       <name>table_name2</name> 
       <comment>comment string2</comment> 
       <type>innodb2</type> 
       <columns> 
        <column> 
         <name>column_name3</name> 
         <type>data_type3</type> 
         <size>3</size> 
         <nullable>not null3</nullable> 
         <comment>comment string3</comment> 
        </column> 
        <column> 
         <name>column_name4</name> 
         <type>data_type4</type> 
         <size>4</size> 
         <nullable>not null4</nullable> 
         <comment>comment string4</comment> 
        </column> 
       </columns> 
      </table> 
     </tables> 
    </schema> 
    <schema> 
     <name>schema_name5</name> 
     <tables> 
      <table> 
       <name>table_name6</name> 
       <comment>comment string6</comment> 
       <type>innodb6</type> 
       <columns> 
        <column> 
         <name>column_name7</name> 
         <type>data_type7</type> 
         <size>7</size> 
         <nullable>not null7</nullable> 
         <comment>comment string7</comment> 
        </column> 
       </columns> 
      </table> 
     </tables> 
    </schema> 
</schemas> 

C# Code:

XDocument xml_input = XDocument.Load(FILE_IN); 
    string column_create = ""; 
    //build a list of all schemas in xml 
    var schemas = from s in xml_input.Descendants("schema") 
        select new 
        { 
         name = s.Element("name").Value 
        }; 
    //loop through all schemas 
    foreach (var s in schemas) 
    { 
     //write the schema creation lines 
     Console.WriteLine("DROP SCHEMA IF EXISTS " + s.name + ";"); 
     Console.WriteLine("CREATE SCHEMA " + s.name + ";"); 
     //build a list of all tables in schema 
     var tables = from t in xml_input.Descendants("schema") 
             .Descendants("table") 
        select new 
        { 
         name = t.Element("name").Value, 
         comment = t.Element("comment").Value, 
         type = t.Element("type").Value 
        }; 
     //loop through all tables in schema 
     foreach (var t in tables) 
     { 
      //write the beginning of the table creation lines 
      Console.WriteLine("CREATE TABLE " + s.name + "." + t.name + " ("); 
      //build a list of all columns in the schema 
      var columns = from c in xml_input.Descendants("schema") 
              .Descendants("table") 
              .Descendants("column") 
          select new 
          { 
           name = c.Element("name").Value, 
           type = c.Element("type").Value, 
           size = c.Element("size").Value, 
           comment = c.Element("comment").Value 
          }; 
      //loop through all columns in table 
      foreach (var c in columns) 
      { 
       //build the column creation line 
       column_create = c.name + " " + c.type; 
       if (c.size != null) 
       { 
        column_create += "(" + c.size + ")"; 
       } 
       if (c.comment != null) 
       { 
        column_create += " COMMENT '" + c.comment + "'"; 
       } 
       column_create += ", "; 
       //write the column creation line 
       Console.WriteLine(column_create); 
      } 
      //write the end of the table creation lines 
      Console.WriteLine(")"); 
      if (t.comment != null) 
      { 
       Console.WriteLine("COMMENT '" + t.comment + "'"); 
      } 
      if (t.type != null) 
      { 
       Console.WriteLine("TYPE = " + t.type); 
      } 
      Console.WriteLine(";"); 
     } 
    } 

Toutes les idées sur la façon de préserver la structure de nidification? J'ai aussi du mal à gérer les éléments XML optionnels (tels que le commentaire de table ou le champ de taille, qui ne s'appliquerait pas à tous les types de données).

Merci!

Répondre

1

Voici comment préserver votre structure imbriquée. Ajoutez le XElement à votre type anonyme pour l'utiliser comme source de vos requêtes imbriquées.

XDocument xml_input = XDocument.Load(FILE_IN); 
     string column_create = ""; 
     //build a list of all schemas in xml 
     var schemas = from s in xml_input.Descendants("schema") 
         select new 
         { 
          schema = s, 
          name = s.Element("name").Value 
         }; 
     //loop through all schemas 
     foreach (var s in schemas) 
     { 
      //write the schema creation lines 
      Console.WriteLine("DROP SCHEMA IF EXISTS " + s.name + ";"); 
      Console.WriteLine("CREATE SCHEMA " + s.name + ";"); 
      //build a list of all tables in schema 
      var tables = from t in s.schema.Descendants("table") 
         select new 
         { 
          table = t, 
          name = t.Element("name").Value, 
          comment = t.Element("comment").Value, 
          type = t.Element("type").Value 
         }; 
      //loop through all tables in schema 
      foreach (var t in tables) 
      { 
       //write the beginning of the table creation lines 
       Console.WriteLine("CREATE TABLE " + s.name + "." + t.name + " ("); 
       //build a list of all columns in the schema 
       var columns = from c in t.table.Descendants("column") 
           select new 
           { 
            name = c.Element("name").Value, 
            type = c.Element("type").Value, 
            size = c.Element("size").Value, 
            comment = c.Element("comment").Value 
           }; 
       //loop through all columns in table 
       foreach (var c in columns) 
       { 
        //build the column creation line 
        column_create = c.name + " " + c.type; 
        if (c.size != null) 
        { 
         column_create += "(" + c.size + ")"; 
        } 
        if (c.comment != null) 
        { 
         column_create += " COMMENT '" + c.comment + "'"; 
        } 
        column_create += ", "; 
        //write the column creation line 
        Console.WriteLine(column_create); 
       } 
       //write the end of the table creation lines 
       Console.WriteLine(")"); 
       if (t.comment != null) 
       { 
        Console.WriteLine("COMMENT '" + t.comment + "'"); 
       } 
       if (t.type != null) 
       { 
        Console.WriteLine("TYPE = " + t.type); 
       } 
       Console.WriteLine(";"); 
      } 
     } 

Une façon de traiter avec les éléments facultatifs est votre xml pour contenir des éléments vides quand il n'y a pas de valeur que dans le commentaire de cette colonne:

 <column> 
     <name>column_name4</name> 
     <type>data_type4</type> 
     <size>4</size> 
     <nullable>not null4</nullable> 
     <comment/> 
     </column> 

Ceci renverra une chaîne vide dans votre requête , donc changez le code à ceci:

if (!string.IsNullOrEmpty(c.comment)) 
    { 
     column_create += " COMMENT '" + c.comment + "'"; 
    } 
+0

C'est fantastique! Fonctionne comme un charme! – Mike