65.9K
CodeProject 正在变化。 阅读更多。
Home

Enum 代码生成器 - 从数据库查找表中自动生成 enum 代码

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.08/5 (15投票s)

2006年11月2日

3分钟阅读

viewsIcon

95298

downloadIcon

1884

该实用程序将查找表中 ID 和 CODE 列的数据转换为 C#(或 VB.NET)中的枚举类型。

Sample Image

引言

在编写代码时,我们经常使用枚举;枚举是一组命名的整数常量,用有意义的名称替换“幻数”。在设计关系数据库时,我们使用查找表来实现相同的目的。查找表通常使用两个字段建模,例如 ID 和 Code。通常,代码中也需要相同的查找信息。这导致在代码中以枚举类型的形式复制此查找数据。虽然数据库中的查找信息不像其他数据那样具有动态性,但它确实会不时发生变化。一位谨慎的开发人员会在相应的查找表发生更改时更新枚举。如果只有几行,这不是什么大问题,但是当有很多行时,它就变得很麻烦。此 EnumGenerator 工具通过从查找表自动生成 .NET 代码(C# 和 VB.NET)来缓解这种痛苦。

连接到数据源

Microsoft 将一个名为 DataLinksClass 的 COM 控件打包为“MS Data Access Components”库的一部分,以连接到各种数据源。要使用此控件,您需要添加对 COM 组件“Microsoft OLE DB Service Component 1.0 Type Library”的引用。由于此组件在成功连接后返回 ADO(而不是 ADO.NET)Connection 对象,因此您还需要添加对“Microsoft ActiveX Data Objects 2.8 Library”的引用。只要您引用的库包含 ADO Connection 对象,库版本就无关紧要。以下代码显示了如何建立连接。成功连接后,将使用来自 ADO 对象的连接字符串来创建新的 ASP.NET 连接。

DataLinksClass dl = new DataLinksClass();
_Connection conn = dl.PromptNew() as _Connection;

读取数据库架构

要生成枚举代码,首先需要确定表名和列名。ASP.NET 的 Connection 类为此目的提供了一个方法 'GetOleDbSchemaTable'。

//Get table names
DataTable schemaTable = oleDbConn.GetOleDbSchemaTable(
                        OleDbSchemaGuid.Tables, 
                        new object[] { null, null, null, "TABLE" });

// Display the table name from each row in the schema
foreach (DataRow row in schemaTable.Rows)
{
    tableList.Items.Add(row["TABLE_NAME"]);
}

要获取表的所有列,请将方法 GetOleDbSchemaTable 的第一个参数设置为 OleDbSchemaGuid.Columns,并将表名作为第二个参数的对象集合中的最后一个对象传递。

//Get column names
DataTable schemaTable = oleDbConn.GetOleDbSchemaTable(
                        OleDbSchemaGuid.Columns, 
                        new object[] { null, null, tableName });

// Display the table name from each row in the schema
foreach (DataRow row in schemaTable.Rows)
{
    fieldList.Items.Add(row["COLUMN_NAME"]);
}

读取数据

GUI 中的 DataView 通过对表的选定列执行动态 SQL 来显示查找数据。查询中只能有两列,其中一列必须为整数类型。通常,这是主键。由于 enum 基于两个必需字段(名称和值),因此代码中有一个验证检查,始终检查所选字段是否为两个。 GetDynamicSql 方法组合这些选定字段以构建 SELECT 查询。

private string GetDynamicSql()
{
    // create dynamic sql
    StringBuilder sb = new StringBuilder();
    sb.Append("Select ");

    int i = 0;
    foreach (string fieldName in fieldList.SelectedItems)
    {
        i++;
        sb.Append("[");
        sb.Append(fieldName);
        sb.Append("]");
        if (fieldList.SelectedItems.Count != i)
            sb.Append(", ");
    }
    sb.Append(" from ");
    sb.Append(tableName);

    return sb.ToString();
}

代码生成

最初,我只是从 C# 代码生成开始。由于 C# 和 VB.NET 之间只有几个关键字差异,因此我决定稍后也添加 VB.NET 代码生成。数据视图显示来自查找表的行以供查看。如果存在任何数据,代码视图将显示相应的枚举代码。以下代码显示了如何做到这一点。要在您的代码中使用生成的枚举,只需将代码视图中的文本剪切并粘贴到您的 C# 或 VB.NET 项目中,并进行必要的更改。

private void PopulateData(bool isVBDotNet)
{
    try
    {
        if (fieldList.SelectedItems.Count == 2)
        {
            oleDbConn.Open();
            string strSql = GetDynamicSql();
            //Get table names
            OleDbCommand command = new OleDbCommand(strSql, oleDbConn);
            OleDbDataReader dataReader = command.ExecuteReader(
                            CommandBehavior.CloseConnection);

            int nFields = dataReader.FieldCount;

            if (nFields == 2)
            {
                // Setup the columns in the listview
                // using the fields in the table
                dataView.Clear();
                for (int i = 0; i < nFields; i++)
                {
                    dataView.Columns.Add(dataReader.GetName(i), 100, 
                                         HorizontalAlignment.Left);
                }

                StringBuilder sb = new StringBuilder();

                if (isVBDotNet)
                {
                    sb.AppendLine("Public Enum " + tableName);
                }
                else
                {
                    sb.AppendLine("public enum " + tableName);
                    sb.AppendLine("{");
                }

                // Fill the rows in the listview
                // using the data in the rows
                while (dataReader.Read())
                {
                    // Create an array of subitems for quick insertion
                    // The subitems will be all fields in the row except for 
                    // the first field
                    String[] subitems = new String[nFields];
                    int val;
                    if (Int32.TryParse(dataReader[0].ToString(), out val))
                    {
                        subitems[0] = dataReader[1].ToString();
                        subitems[1] = dataReader[0].ToString();
                    }
                    else if (Int32.TryParse(dataReader[1].ToString(), out val))
                    {
                        subitems[0] = dataReader[0].ToString();
                        subitems[1] = dataReader[1].ToString();
                    }
                    else
                    {
                        MessageBox.Show("There are no ID columns " + 
                            "with integer values in the selection");
                        codeView.Text = "";
                        dataReader.Close();
                        return;
                    }

                    string eunumName = subitems[0];
                    if (eunumName.Length == 0)
                        eunumName = "None";

                    sb.Append("\t");
                    eunumName = eunumName.Replace(' ', '_');
                    eunumName = eunumName.Replace('/', '_');
                    eunumName = eunumName.Replace('.', '_');
                    sb.Append(eunumName + " = " + subitems[1]);

                    if (!isVBDotNet)
                    {
                        sb.Append(",");
                    }

                    sb.Append("\n");

                    // Insert a new item into the listview,
                    // and add the subitems at 
                    // the same time. The item will
                    // be the first field in the row
                    ListViewItem item = new ListViewItem(subitems, -1);
                    dataView.Items.Add(item);
                }
                dataReader.Close();

                if (isVBDotNet)
                {
                    sb.AppendLine("End Enum");
                }
                else
                {
                    sb.Remove(sb.Length - 2, 1);
                    sb.AppendLine("}");
                }

                codeView.Text = sb.ToString();
            }
        }
        else
        {
            MessageBox.Show("Please select two(and only" + 
                            " two fields) from the field list");
            dataView.Clear();
            codeView.Text = "";
        }
    }
    finally
    {
        if ((oleDbConn != null) && 
            (oleDbConn.State == ConnectionState.Open))
            oleDbConn.Close();
    }
}

注意

在某些情况下,查找表中的 Name 或 Code 列可能包含空格或其他特殊字符作为文本数据的一部分。由于“enum' 不允许空格或特殊字符,因此代码生成器会将它们替换为下划线。

© . All rights reserved.