Получение ширины столбца из SqlDataReader - PullRequest
1 голос
/ 09 марта 2009

Я пришел в StackOverflow раньше с этим квестом: MS SQL2005 Запрос / сохраненные результаты процесса в текст, используя SqlCommand или любой другой метод

Мне сказали построить строку самостоятельно, чтобы я получал те же результаты, что и из результатов в текстовую версию SQL Managment Studio (Cntrl + T)

Я столкнулся с проблемой, как я могу динамически определить ширину столбца? А как насчет столбцов, которые VARCHAR (MAX)? Я абсолютно не знаю, что войдет в SqlDataReader заранее.

Вот код, который у меня есть до сих пор, мне необходимо исключить PADDING_LENGTH и динамически заменить его значение.

Я взял основной код из сети где-то. (Кто бы это ни написал первым, спасибо вам)

StringBuilder sb = new StringBuilder(); 
 private void GenerateResultsText(SqlDataReader reader)
    {
        const int PADDING_LENGTH = 40;

        do
        {
            // Create new data table
            DataTable schemaTable = reader.GetSchemaTable();

            if (schemaTable != null)
            {
                // A query returning records was executed
                for (int i = 0; i < schemaTable.Rows.Count; i++)
                {
                    DataRow dataRow = schemaTable.Rows[i];
                    // Create a column name that is unique in the data table
                    string columnName = (string)dataRow["ColumnName"];
                    //Add to Results String.
                    sb.Append(String.Format("{0, " + -1 * PADDING_LENGTH + "}", columnName));
                }
                sb.Append(Environment.NewLine);

                //Add markers to seperate Row entries from Column names. 
                const string columnRowSeperator = "-----"; //Keep it to a multiple of 5.
                for (int i = 0; i < schemaTable.Rows.Count; i++)
                {
                    for (int j = 0; j < PADDING_LENGTH / columnRowSeperator.Length; j++)
                        sb.Append(columnRowSeperator);
                }
                sb.Append(Environment.NewLine);

                // Fill the data table we just created
                while (reader.Read())
                {
                    Object temp;

                    for (int i = 0; i < reader.FieldCount; i++)
                    {
                        temp = reader.GetValue(i);
                        sb.Append(String.Format("{0, " + -1 * PADDING_LENGTH + "}", temp.ToString()));
                    }
                    sb.Append(Environment.NewLine);
                }

                //Add newlines to seperate tables.
                sb.Append(Environment.NewLine + Environment.NewLine);
            }
        }
        while (reader.NextResult());

        reader.Close();
        reader.Dispose();
    }

Cheers, Кай.

Ответы [ 2 ]

4 голосов
/ 10 марта 2009

EDIT

Вот пример использования DataReader. Вы могли бы быть еще более конкретным, глядя на столбцы NumericPrecision и тому подобное в таблице схемы, но я думаю, что это поможет вам начать.

using (SqlConnection conn = new SqlConnection("Data Source=server;Initial Catalog=db;User Id=user;Password=pass;"))
{
    using (SqlCommand cmd = new SqlCommand("select * from table", conn))
    {
        conn.Open();
        StreamWriter sw = new StreamWriter(File.Open("test.txt", FileMode.Append));        
        DataTable schema = null;

        using (SqlDataReader rdr = cmd.ExecuteReader())
        {
            schema = rdr.GetSchemaTable();


            for (int i = 0; i < rdr.FieldCount; i++)
            {
                string name = schema.Rows[i]["ColumnName"].ToString();
                sw.Write(name.PadRight(name.Length + Convert.ToInt32(schema.Rows[i]["ColumnSize"])) + " ");
            }

            sw.WriteLine();

            for (int i = 0; i < rdr.FieldCount; i++)
            {
                string name = schema.Rows[i]["ColumnName"].ToString();
                sw.Write(new string('-', name.Length + Convert.ToInt32(schema.Rows[i]["ColumnSize"])) + " ");
            }

            rdr.Close();//can't have two open datareaders on the same connection
            rdr.Dispose();

            sw.WriteLine();

            while (dataReader.Read())
            {
                for (int i = 0; i < dataReader.FieldCount; i++)
                {
                    string name = schema.Rows[i]["ColumnName"].ToString();
                    sw.Write(dataReader[i].ToString().PadRight(name.Length + Convert.ToInt32(schema.Rows[i]["ColumnSize"])) + " ");
                }
                sw.WriteLine();
            }

        }

        sw.Close();
        sw.Dispose();
    }
}

Я не мог потратить достаточно времени, чтобы узнать, как это сделать с помощью DataReader, но если вы вместо этого используете DataAdapter, вы можете сделать это:

    using (SqlConnection conn = new SqlConnection("Data Source=someserver;Initial Catalog=somedb;User Id=user;Password=password;"))
    {
        using (SqlCommand cmd = new SqlCommand("select * from sometable", conn))
        {
            conn.Open();
            using (SqlDataAdapter adapter = new SqlDataAdapter(cmd))
            {
                DataSet set = new DataSet();
                set.Tables.Add("Schema");
                set.Tables.Add("Data");

                adapter.Fill(set, "Data");
                adapter.FillSchema(set, SchemaType.Source, "Schema");

                StreamWriter sw = new StreamWriter(File.Open("test.txt", FileMode.Append));        

                for(int i = 0; i < set.Tables["Schema"].Columns.Count; i++)
                {

                    sw.Write(set.Tables["Schema"].Columns[i].ColumnName.PadRight(set.Tables["Schema"].Columns[i].MaxLength + set.Tables["Schema"].Columns[i].ColumnName.Length, ' ') + " ");
                }
                sw.WriteLine();

                for(int i = 0; i < set.Tables["Schema"].Columns.Count; i++)
                {
                    sw.Write(new string('-', set.Tables["Schema"].Columns[i].MaxLength + set.Tables["Schema"].Columns[i].ColumnName.Length) + " ");
                }
                sw.WriteLine();

                foreach(DataRow row in set.Tables["Data"].Rows)
                {
                    foreach(DataColumn col in set.Tables["Data"].Columns)
                    {
                        sw.Write(row[col].ToString().PadRight(set.Tables["Schema"].Columns[col.ColumnName].MaxLength + col.ColumnName.Length) + " ");
                    }
                    sw.WriteLine();
                }

                sw.Close();
                sw.Dispose();






            }
        }
    }
0 голосов
/ 09 марта 2009

Вы не можете определить ширину столбца, который будет отображаться на экране, только из Sql Data Reader - в конце концов, ширина столбца сильно зависит от того, какой экранный шрифт вы используете, какой размер, жирный или нет, и и пр.

Что вам нужно сделать, это визуализировать текст в вашем пользовательском интерфейсе, где вы хотите его отобразить - там, на стороне пользовательского интерфейса, вы можете измерить пространство, необходимое для отображения данного текста, используя заданный шрифт, размер и характеристики шрифта.

Марк

...