简体   繁体   English

Linq to XML生成DDL

[英]Linq to XML to Generate DDLs

We're storing out database definition as XML in the format at the end of this question. 我们以问题末尾的格式将数据库定义存储为XML。 The problem I'm having is getting a list of schemas, the tables in those schemas, the columns in those tables (all with their associated information). 我遇到的问题是获取模式列表,这些模式中的表,这些表中的列(所有及其相关信息)。 My current code (included below the sample XML) grabs everything, completely ignoring nesting and, due to the multiple schemas, returns each table/column multiple times. 我当前的代码(包括在示例XML下面)捕获了所有内容,完全忽略了嵌套,并且由于存在多个模式,因此多次返回每个表/列。

Sample XML: 样本XML:

<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: C#代码:

    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(";");
        }
    }

Any ideas on how to preserve the nesting structure? 关于如何保留嵌套结构的任何想法? I'm also having trouble handling optional XML elements (such as the table comment or the size field, which wouldn't apply to all data types). 我还无法处理可选的XML元素(例如,表注释或size字段,这不适用于所有数据类型)。

Thanks! 谢谢!

Here is how to preserve your nested structure. 这是保存嵌套结构的方法。 Add the XElement to your anonymous type to use as the source of your nested queries. 将XElement添加到您的匿名类型中,以用作嵌套查询的源。

    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(";");
            }
        }

One way to deal with the optional elements is for your xml to contain empty elements when there is no value as in this column's comment: 处理可选元素的一种方法是,在没有值的情况下,xml包含空元素,如本专栏的注释所示:

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

This will return an empty string in your query, so change the code to this: 这将在您的查询中返回一个空字符串,因此将代码更改为此:

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

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

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