0

这将是一个冗长的问题——我整天都在试图解决这个问题,所以也许你们可以帮忙!我试图通过允许在以新结构(以 XML 格式)呈现时更改数据库结构来对我的数据库应用程序进行未来验证。

目前我正在设法将数据库结构导出到 XML 中。请参阅下面的工作代码:

    public void generateXMLStructureCompactDB(string fileName)
    {
        DataTable table = new DataTable();
        int position;
        FileStream fsWrite;
        StreamWriter sw;

        string version = "1.1.1.0";
        table.Columns.Add("TableName", Type.GetType("System.String"));
        table.Columns.Add("ColName", Type.GetType("System.String"));
        table.Columns.Add("Position", Type.GetType("System.Int32"));
        table.Columns.Add("DataType", Type.GetType("System.String"));
        table.Columns.Add("MaximumLength", Type.GetType("System.Int32"));
        table.Columns.Add("Precision", Type.GetType("System.Int32"));
        table.Columns.Add("Scale", Type.GetType("System.Int32"));
        table.Columns.Add("Nullable", Type.GetType("System.Boolean"));
        table.Columns.Add("Identity", Type.GetType("System.Boolean"));
        table.Columns.Add("IdentitySeed", Type.GetType("System.Int32"));
        table.Columns.Add("IdentityIncrement", Type.GetType("System.Int32"));

        string sql = "select Table_Name, Column_Name, Ordinal_Position, Data_Type, " +
            "Character_Maximum_Length, Numeric_Precision, Numeric_Scale, Is_Nullable, " +
            "case when AutoInc_Seed is null then 0 else 1 end as IS_IDENTITY, " +
            "AutoInc_Seed, AutoInc_Increment from information_schema.columns";
        runSQL(sql, out table);

        if (File.Exists(fileName))
            File.Delete(fileName);

        fsWrite = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite);
        sw = new StreamWriter(fsWrite, Encoding.ASCII);

        XmlWriter writer = new XmlTextWriter(sw);
        writer.WriteStartDocument(false);
        writer.WriteRaw(Environment.NewLine);
        writer.WriteComment("DBVersion=" + DBVersion + ", created=" + DateTime.Now.ToString());
        writer.WriteRaw(Environment.NewLine);

        writer.Close();
        sw.Close();
        fsWrite.Close();

        fsWrite = new FileStream(fileName, FileMode.Append, FileAccess.Write, FileShare.ReadWrite);
        sw = new StreamWriter(fsWrite, Encoding.ASCII);

        DataTable indexes = new DataTable();
        indexes.Columns.Add("TableName", Type.GetType("System.String"));
        indexes.Columns.Add("Schema", Type.GetType("System.String"));
        indexes.Columns.Add("IndexName", Type.GetType("System.String"));
        indexes.Columns.Add("Clustered", Type.GetType("System.Boolean"));
        indexes.Columns.Add("Unique", Type.GetType("System.Boolean"));
        indexes.Columns.Add("IndexColName", Type.GetType("System.String"));
        sql = "select Table_Name, Table_Schema, Index_Name, [Clustered], [Unique], " + 
            "Column_Name from information_schema.indexes";
        runSQL(sql, out indexes);

        table.TableName = "Tables";
        indexes.TableName = "Indexes";

        table.WriteXml(sw);
        sw.WriteLine("");
        indexes.WriteXml(sw);
        sw.Close();
        fsWrite.Close();
    }

下面是我生成的 XML 文件(实际版本要大得多,但我已将其剥离为单个表和单个索引):

<?xml version="1.0" encoding="us-ascii" standalone="no"?>
<!--DBVersion=1.0.0.0, created=14/03/2013 13:18:20-->
<DocumentElement>
  <Tables>
    <TABLE_NAME>ContactLog</TABLE_NAME>
    <COLUMN_NAME>ContactLogId</COLUMN_NAME>
    <ORDINAL_POSITION>1</ORDINAL_POSITION>
    <DATA_TYPE>int</DATA_TYPE>
    <NUMERIC_PRECISION>10</NUMERIC_PRECISION>
    <IS_NULLABLE>NO</IS_NULLABLE>
    <IS_IDENTITY>1</IS_IDENTITY>
    <AUTOINC_SEED>1</AUTOINC_SEED>
    <AUTOINC_INCREMENT>1</AUTOINC_INCREMENT>
  </Tables>
  <Tables>
    <TABLE_NAME>ContactLog</TABLE_NAME>
    <COLUMN_NAME>CustomerId</COLUMN_NAME>
    <ORDINAL_POSITION>2</ORDINAL_POSITION>
    <DATA_TYPE>int</DATA_TYPE>
    <NUMERIC_PRECISION>10</NUMERIC_PRECISION>
    <IS_NULLABLE>YES</IS_NULLABLE>
    <IS_IDENTITY>0</IS_IDENTITY>
  </Tables>
  <Tables>
    <TABLE_NAME>ContactLog</TABLE_NAME>
    <COLUMN_NAME>ContactDate</COLUMN_NAME>
    <ORDINAL_POSITION>3</ORDINAL_POSITION>
    <DATA_TYPE>datetime</DATA_TYPE>
    <NUMERIC_PRECISION>23</NUMERIC_PRECISION>
    <NUMERIC_SCALE>3</NUMERIC_SCALE>
    <IS_NULLABLE>YES</IS_NULLABLE>
    <IS_IDENTITY>0</IS_IDENTITY>
  </Tables>
  <Tables>
    <TABLE_NAME>ContactLog</TABLE_NAME>
    <COLUMN_NAME>ContactTypeId</COLUMN_NAME>
    <ORDINAL_POSITION>4</ORDINAL_POSITION>
    <DATA_TYPE>int</DATA_TYPE>
    <NUMERIC_PRECISION>10</NUMERIC_PRECISION>
    <IS_NULLABLE>YES</IS_NULLABLE>
    <IS_IDENTITY>0</IS_IDENTITY>
  </Tables>
  <Tables>
    <TABLE_NAME>ContactLog</TABLE_NAME>
    <COLUMN_NAME>AuditText</COLUMN_NAME>
    <ORDINAL_POSITION>5</ORDINAL_POSITION>
    <DATA_TYPE>nvarchar</DATA_TYPE>
    <CHARACTER_MAXIMUM_LENGTH>2048</CHARACTER_MAXIMUM_LENGTH>
    <IS_NULLABLE>YES</IS_NULLABLE>
    <IS_IDENTITY>0</IS_IDENTITY>
  </Tables>
  <Tables>
    <TABLE_NAME>ContactType</TABLE_NAME>
    <COLUMN_NAME>ContactTypeId</COLUMN_NAME>
    <ORDINAL_POSITION>1</ORDINAL_POSITION>
    <DATA_TYPE>int</DATA_TYPE>
    <NUMERIC_PRECISION>10</NUMERIC_PRECISION>
    <IS_NULLABLE>NO</IS_NULLABLE>
    <IS_IDENTITY>1</IS_IDENTITY>
    <AUTOINC_SEED>1</AUTOINC_SEED>
    <AUTOINC_INCREMENT>1</AUTOINC_INCREMENT>
  </Tables>
</DocumentElement>
<DocumentElement>
  <Indexes>
    <TABLE_NAME>ContactLog</TABLE_NAME>
    <INDEX_NAME>PK_ContactLog</INDEX_NAME>
    <CLUSTERED>false</CLUSTERED>
    <UNIQUE>true</UNIQUE>
    <COLUMN_NAME>ContactLogId</COLUMN_NAME>
  </Indexes>
</DocumentElement>

现在这是读取 XML 文件的代码部分。XML 文件包含两个单独表的列 - tables(实际上是列列表)和indexes- 索引列表。它根据 的位置将文件一分为二<DocumentElement>,然后将这两个 XML 元素放入两个单独的表中。请参见下面的代码:

    static bool VerifyStructure()
    {
        FileStream fsWrite;
        int i;
        StreamWriter sw;
        string DBStructureVersion = "0.0.0.0";
        string xmlFile;
        string s;
        string tmp = Environment.GetEnvironmentVariable("TEMP");
        if (tmp == "")
            tmp = Environment.GetEnvironmentVariable("SystemDrive");
        try
        {
            xmlFile = tmp + @"\dbStructure.xml";
            if (File.Exists(xmlFile))
                File.Delete(xmlFile);

            fsWrite = new FileStream(xmlFile, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite);
            sw = new StreamWriter(fsWrite, Encoding.ASCII);
            sw.Write(syntos.Properties.Resources.dbStructure);
            sw.Close();
            fsWrite.Close();
        }
        catch (Exception ex)
        {
            MessageBox.Show("Error reading structure xml file: " + ex.Message);
            return false;
        }
        if (!File.Exists(xmlFile))
        {
            MessageBox.Show("XML Structure file '" + xmlFile + "' does not exist.");
            return false;
        }
        StreamReader sr = new StreamReader(xmlFile);
        s = sr.ReadLine();
        while (s != null)
        {
            if (s.Contains("DBVersion="))
            {
                i = s.IndexOf("DBVersion=");
                DBStructureVersion = s.Substring(i + 10);
                i = DBStructureVersion.IndexOf(",");
                DBStructureVersion = DBStructureVersion.Substring(0, i);
                break;
            }
            s = sr.ReadLine();
        }
        sr.Close();

        // Split the remaining XML file into two: table datatable file and index datatable file
        // Write out to file1 all the table information and to file2 all the index information
        string file1path;
        string file2path;

        try
        {
            file1path = tmp + @"\tables.xml";
            file2path = tmp + @"\indexes.xml";
            if (File.Exists(file1path))
                File.Delete(file1path);

            if (File.Exists(file2path))
                File.Delete(file2path);

            FileStream fsw1 = new FileStream(file1path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite);
            FileStream fsw2 = new FileStream(file2path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite);
            StreamWriter sw1 = new StreamWriter(fsw1, Encoding.ASCII);
            StreamWriter sw2 = new StreamWriter(fsw2, Encoding.ASCII);

            // Create a file containing just the table / column definitions
            sr = new StreamReader(xmlFile);
            s = sr.ReadToEnd();
            sr.Close();

            i = s.IndexOf("<DocumentElement>");
            s = s.Substring(i);
            i = s.IndexOf("</DocumentElement>");
            s = s.Substring(0, i + 18);
            sw1.Write(s);
            sw1.Close();
            fsw1.Close();

            // Create a file containing the index column definitions
            sr = new StreamReader(xmlFile);
            s = sr.ReadToEnd();
            sr.Close();

            i = s.IndexOf("</DocumentElement>");
            s = s.Substring(i + 18);
            sw2.Write(s);
            sw2.Close();
            fsw2.Close();
            sr.Close();
        }
        catch (Exception ex)
        {
            MessageBox.Show("Error producing the table and index XML file. " + ex.Message);
            return false;
        }

        DataTable table = new DataTable();
        table.Columns.Add("TableName", Type.GetType("System.String"));
        table.Columns.Add("ColName", Type.GetType("System.String"));
        table.Columns.Add("Position", Type.GetType("System.Int32"));
        table.Columns.Add("DataType", Type.GetType("System.String"));
        table.Columns.Add("MaximumLength", Type.GetType("System.Int32"));
        table.Columns.Add("Precision", Type.GetType("System.Int32"));
        table.Columns.Add("Scale", Type.GetType("System.Int32"));
        table.Columns.Add("Nullable", Type.GetType("System.Boolean"));
        table.Columns.Add("Identity", Type.GetType("System.Boolean"));
        table.Columns.Add("IdentitySeed", Type.GetType("System.Int32"));
        table.Columns.Add("IdentityIncrement", Type.GetType("System.Int32"));
        table.TableName = "Tables";

        DataTable indexes = new DataTable();
        indexes.Columns.Add("TableName", Type.GetType("System.String"));
        indexes.Columns.Add("Schema", Type.GetType("System.String"));
        indexes.Columns.Add("IndexName", Type.GetType("System.String"));
        indexes.Columns.Add("Clustered", Type.GetType("System.Boolean"));
        indexes.Columns.Add("Unique", Type.GetType("System.Boolean"));
        indexes.Columns.Add("IndexColName", Type.GetType("System.String"));
        indexes.TableName = "Indexes";

        // Read in the XML for the table / columns
        sr = new StreamReader(file1path);
        table.ReadXml(sr);
        sr.Close();
        if (table.Rows.Count == 0)
        {
            MessageBox.Show("No loadable table rows found in XML file");
            sw.Close();
            fsWrite.Close();
            return false;
        }
        sr = new StreamReader(file2path);
        indexes.ReadXml(sr);
        sr.Close();
        if (indexes.Rows.Count == 0)
        {
            MessageBox.Show("No loadable index rows found in XML file");
            sw.Close();
            fsWrite.Close();
            return false;
        }
        DbFunctions.BackupDatabase();
        bool success1 = CreateTempTables(table);
        return true;
    }

通过使用断点和调试语句,我可以看到表正在填充正确数量的行和列 - 但是所有这些都是空的。只是空单元格。我曾经table.Rows.Count看到这个表中实际上有行。

如果有人能看到我在这里是否正确,我将永远感激不尽!提前致谢 :)

编辑:我已经用不同的 XML 表对此进行了测试,它可以工作。我生成 XML 文件的方式一定有问题,但我看不到是什么。

只要允许我这样做,我就会在这个问题上增加赏金;)

问题总结:将系统生成的XML文件(第一个代码块)再次导入程序(第三个代码块)时,行和列都存在,但所有单元格都是空白的。

4

1 回答 1

1

列名不匹配 - 名称区分大小写。您可以在空表上导入XML,该方法将为您创建列。http://msdn.microsoft.com/es-es/library/system.data.datatable.readxml(v=vs.100).aspx

于 2013-03-14T15:30:29.263 回答