Linq to XML для генерации DDL

2

Мы сохраняем определение базы данных как XML в формате в конце этого вопроса. Проблема, с которой я сталкиваюсь, - это получить список схем, таблицы в этих схемах, столбцы в этих таблицах (все с их связанной информацией). Мой текущий код (включенный ниже образца 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>

Код С#:

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

Любые идеи о том, как сохранить структуру вложенности? У меня также возникают проблемы с обработкой дополнительных XML-элементов (таких как комментарий таблицы или поле размера, которое не распространяется на все типы данных).

Спасибо!

Теги:
linq
linq-to-xml
ddl

1 ответ

1
Лучший ответ

Вот как сохранить вашу вложенную структуру. Добавьте 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(";");
            }
        }

Один из способов обработки необязательных элементов состоит в том, чтобы ваш xml содержал пустые элементы, когда в этом комментарии столбца нет значения:

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

Это вернет пустую строку в ваш запрос, поэтому измените код на это:

if (!string.IsNullOrEmpty(c.comment))
    {
        column_create += " COMMENT '" + c.comment + "'";
    }
  • 0
    Это фантастично! Работает как шарм!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню