Как получить имена столбцов при сохранении SQL-запроса в текстовый файл

Я написал метод, который сохраняет содержимое определенной таблицы в текстовый файл. К сожалению, имена столбцов не извлекаются. «Только» данные каждой ячейки записываются в текстовый файл.

Как мне адаптировать свой код, чтобы он также включал имена столбцов?

private void WriteSQLQueryOutputToTextFile(string DBUser, string DBUserPassword, string sqlQuery, string databaseName, string nameOfOutputFile, string nameOfRow0, string nameOfRow1, string nameOfRow2)
{
  StreamWriter outputFile = new StreamWriter(dWTestResult + "\\DatabaseUpgradeCheck\\" + nameOfOutputFile);

  using (SqlConnection sqlCon = new SqlConnection("Data Source = " + GetEnvironmentVariable.MachineName + "; Initial Catalog = " + databaseName + "; User ID = " + DBUser + "; Password = " + DBUserPassword + ";"))
  {
      SqlCommand command = new SqlCommand(sqlQuery, sqlCon);
      sqlCon.Open();
      SqlDataReader reader = command.ExecuteReader();
      try
      {
          while (reader.Read())
          {
              outputFile.WriteLine(String.Format("{0}, {1}, {2}",
              reader[nameOfRow0], reader[nameOfRow1], reader[nameOfRow2]));
          }
      }
      catch (Exception ex)
      {
          logger.Debug(ex, "Writing Database Output to the text file failed");
      }
      finally
      {
          reader.Close();
          outputFile.Close();
      }     
   }
}

Вариант для вас: если вы используете DataAdapter и заполните DataTable, вы получите заголовки столбцов в DataTable

JayV 15.03.2019 11:10
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
1
538
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

привет, я думаю, вы можете использовать: reader.GetName('index') например, для первого столбца: reader.GetName(0)

Подробнее по этой ссылке: https://docs.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqldatareader.getname?view=netframework-4.7.2

Ответ принят как подходящий

Добавьте переменную count, а если count == 0 добавьте имена столбцов. Похоже, вы уже знаете имена столбцов, поэтому у вас есть несколько вариантов.

Первый вариант: Просто напишите имя.

try
{
    int count = 0;
    while (reader.Read())
    {
        if (count == 0)
        {
            outputFile.WriteLine(String.Format("{0}, {1}, {2}",
                nameOfRow0, nameOfRow1, nameOfRow2));
        }

        outputFile.WriteLine(String.Format("{0}, {1}, {2}",
            reader[nameOfRow0], reader[nameOfRow1], reader[nameOfRow2]));

        count++;    
    }
}

Или (если вы не знаете названия столбцов) используйте reader.GetName(i):

try
{
    int count = 0;
    while (reader.Read())
    {
        // if this is the first row, read the column names
        if (count == 0)
        {
            outputFile.WriteLine(String.Format("{0}, {1}, {2}",
               reader.GetName(0), reader.GetName(1), reader.GetName(2)));
        }

        // otherwise just the data (including 1st row)
        outputFile.WriteLine(String.Format("{0}, {1}, {2}",
           reader.GetValue(0), reader.GetValue(1), reader.GetValue(2)));

        count++;         
    }
}

Привет, Халдо, мне очень нравятся твои подходы. Я использовал тот, где имя столбца неизвестно, потому что это делает метод более гибким. Несмотря на то, что я скопировал ваш пример (позор мне), он извлекает только имена столбцов. Есть идеи, почему?

fabian09 15.03.2019 12:20

@ fabian09 Да, у меня была ошибка в коде. Теперь исправлено - else не нужен, так как вы всегда хотите читать данные в первой строке, но вы хотите читать только имена столбцов для первой итерации. С оператором else он пропускал первую строку данных. Теперь он должен прочитать первую строку данных и прочитать имена столбцов. Дайте мне знать, если это все еще не работает.

haldo 15.03.2019 12:32

Теперь это работает :). Еще один вопрос. Есть ли у вас какие-либо идеи, можно ли получить точный формат БД в текстовый файл? Значение: та же структура БД. Сейчас каждая строка выровнена по левому краю. Вот почему содержимое столбца не подходит к именам столбцов

fabian09 15.03.2019 12:44

@ fabian09 Это сложная задача, потому что каждый столбец может иметь разную длину. Если все столбцы разделены ,, вы можете переименовать файл, чтобы использовать расширение .csv, тогда вы можете открыть его в Excel, и столбцы/строки будут выглядеть так же, как база данных.

haldo 15.03.2019 12:49

Хорошо. Спасибо.

fabian09 15.03.2019 12:59

мне нужно задать еще один вопрос. Дело в том, что я хочу прочитать шесть таблиц базы данных с разным количеством столбцов. Ваши предложения привязаны к трем столбцам. Если я хочу прочитать таблицу только с двумя столбцами, я получаю System.IndexOutOfRangeException: индекс был за пределами массива. Есть ли способ сделать ваш код более гибким, чтобы я мог обрабатывать разные типы таблиц с разным количеством столбцов?

fabian09 02.04.2019 10:43

@ fabian09 вы можете использовать FieldCount средства чтения данных или использовать SqlDataAdapter и DataTable вместо средства чтения данных sql. Оба эти варианта вам, вероятно, потребуются, чтобы перебрать столбцы, чтобы создать желаемый результат.

haldo 02.04.2019 17:57

Пожалуйста, попробуйте это и установите имя строки и столбца данных в соответствии с вашими потребностями.

using (SqlConnection sqlCon = new SqlConnection("Data Source = " + GetEnvironmentVariable.MachineName + "; Initial Catalog = " + databaseName + "; User ID = " + DBUser + "; Password = " + DBUserPassword + ";"))
  {
      SqlCommand command = new SqlCommand(sqlQuery, sqlCon);
      sqlCon.Open();
      SqlDataAdapter da = new SqlDataAdapter();
      da.SelectCommand = cmd; 
      DataTable dt = new DataTable(); 
      da.fill(dt);
      try
      {
         if (dt != null && dt.Rows.Count > 0)
         {
            string columnName = dt.Columns[0].ToString();
            DataRow dr = dt.Rows[0];
         }
      }
      catch (Exception ex)
      {
          logger.Debug(ex, "Writing Database Output to the text file failed");
      }
      finally
      {
          reader.Close();
          outputFile.Close();
      }     
   }

Другие вопросы по теме