Чи можете ви отримати імена стовпців від SqlDataReader?


276

Після підключення до бази даних я можу отримати назву всіх стовпців, які були повернуті в моєму SqlDataReader?

Відповіді:


460
var reader = cmd.ExecuteReader();

var columns = new List<string>();

for(int i=0;i<reader.FieldCount;i++)
{
   columns.Add(reader.GetName(i));
}

або

var columns = Enumerable.Range(0, reader.FieldCount).Select(reader.GetName).ToList();

71
це божевільно, що не існує численного інтерфейсу, який дозволяє переглядати стовпці.
JohnFx

61
Трохи коротше:columns = Enumerable.Range(0, reader.FieldCount) .Select(reader.GetName).ToList();
Алекс

2
Це чудово працює. Я також з’ясував, що назви моїх стовпців - це великі регістри, якщо я не використовую лапки навколо назви стовпця. SELECT id AS "MyId" FROM table;
styfle

сер повертає всі імена стовпців в малі літери. Назви стовпців у таблиці - всі великі регістри, як OBJECTID, і читач повертається з малих літер, як об’єктид
Muneem Habib

2
його стовпці Dim () As String = Enumerable.Range (0, cTab.FieldCount) .Select (Функція (n) cTab.GetName (n)). ToArray
swe

77

Існує GetNameфункція, SqlDataReaderяка приймає індекс стовпця і повертає ім'я стовпця.

І навпаки, існує те, GetOrdinalщо приймає ім'я стовпця і повертає індекс стовпця.


3
Дві причини: по-перше, оригінальний плакат ще не обрав відповіді, по-друге, є й інші відповіді, які дають більш детальний опис «рішення» проблеми, а потім просто існування функціоналу. Особисто мені найбільше подобається відповідь Стівена Лайона, оскільки вона не тільки розповідає про GetName, але також переходить у FieldType та DataType.
Стівен Врігтон

1
GetOrdinalбув ідеальним. Я шукав GetName, але набагато більш чітке рішення для своєї проблеми GetOrdinal.
goodeye

43

Ви можете отримати імена стовпців від DataReader.

Ось важлива частина:

  for (int col = 0; col < SqlReader.FieldCount; col++)
  {
    Console.Write(SqlReader.GetName(col).ToString());         // Gets the column name
    Console.Write(SqlReader.GetFieldType(col).ToString());    // Gets the column type
    Console.Write(SqlReader.GetDataTypeName(col).ToString()); // Gets the column database type
  }

15

Вже згадувалося. Просто відповідь LINQ :

var columns = reader.GetSchemaTable().Rows
                                     .Cast<DataRow>()
                                     .Select(r => (string)r["ColumnName"])
                                     .ToList();

//Or

var columns = Enumerable.Range(0, reader.FieldCount)
                        .Select(reader.GetName)
                        .ToList();

Другий - чистіший і набагато швидший. Навіть якщо ви кешуєте GetSchemaTableза першого підходу, запит буде дуже повільним.


Чи є спосіб це зробити з цінностями?
Тревіс Хетер

@TravisHeeter Я не розумію тебе. Знайдіть назви стовпців із значень чого?
nawfal

Я маю на увазі просто східний спосіб перерахування значень результату, встановлених у списку, або, можливо, все це до об'єкта IEnumerable <dynamic>.
Тревіс Хетер

@TravisHeeter так міг би зробити reader.Cast<IDataRecord>().ToList(). Я вважаю, що ви можете використовувати dynamicключове слово там, IDataRecordале без користі. DataTableбув розроблений для полегшення одноразового завантаження, тому ви можете також використовувати це, але втрачаєте перевагу завантаження на вимогу (за допомогою зчитувача даних ви можете зупинити завантаження в будь-якій точці), наприклад var dt = new DataTable(); dt.Load(reader); return dt.AsEnumerable().ToList();. Є багато бібліотек , які можуть автоматизувати це для вас, знайти їх тут stackoverflow.com/questions/11988441 і тут stackoverflow.com/questions/1464883
Навфал

Я спробував reader.Cast<IEnumerable<dynamic>>і .Cast<dynamic>, але він каже, Cannot convert method group 'Cast' to non-delegate type 'dynamic'. Did you intend to invoke the method?що ж я зробив поганого? (Я переглянув ваші джерела, але вони вимагали, щоб ви знали назву стовпця, чого я не знаю)
Тревіс Хетер

6

Якщо ви хочете лише імена стовпців, ви можете зробити:

List<string> columns = new List<string>();
using (SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SchemaOnly))
{
    DataTable dt = reader.GetSchemaTable();
    foreach (DataRow row in dt.Rows)
    {
        columns.Add(row.Field<String>("ColumnName"));
    }
}

Але якщо вам потрібен лише один ряд, мені подобається моє доповнення AdoHelper. Це доповнення чудово, якщо ви маєте однорядний запит і не хочете мати справу з таблицею даних у вашому коді. Він повертає нечутливий до регістру словник імен стовпців та значень.

public static Dictionary<string, string> ExecuteCaseInsensitiveDictionary(string query, string connectionString, Dictionary<string, string> queryParams = null)
{
    Dictionary<string, string> CaseInsensitiveDictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
    try
    {
        using (SqlConnection conn = new SqlConnection(connectionString))
        {
            conn.Open();
            using (SqlCommand cmd = new SqlCommand())
            {
                cmd.Connection = conn;
                cmd.CommandType = CommandType.Text;
                cmd.CommandText = query;

                // Add the parameters for the SelectCommand.
                if (queryParams != null)
                    foreach (var param in queryParams)
                        cmd.Parameters.AddWithValue(param.Key, param.Value);

                using (SqlDataReader reader = cmd.ExecuteReader())
                {
                    DataTable dt = new DataTable();
                    dt.Load(reader);
                    foreach (DataRow row in dt.Rows)
                    {
                        foreach (DataColumn column in dt.Columns)
                        {
                            CaseInsensitiveDictionary.Add(column.ColumnName, row[column].ToString());
                        }
                    }
                }
            }
            conn.Close();
        }
    }
    catch (Exception ex)
    {
        throw ex;
    }
    return CaseInsensitiveDictionary;
}

1
throw ex;- найгірша практика.
asawyer

2
це лише приклад
садиба Якір

5
Бачучи, ти повинен хоча б сказати, чому. Я припускаю, що ти скажеш, що ти повинен використовувати "кинути;" натомість, щоб ви не втратили оригінальні деталі слідів смуги.
Brent Rittenhouse


3

Використовуйте метод розширення:

    public static List<string> ColumnList(this IDataReader dataReader)
    {
        var columns = new List<string>();
        for (int i = 0; i < dataReader.FieldCount; i++)
        {
            columns.Add(dataReader.GetName(i));
        }
        return columns;
    }

2

Ви впевнені, що можете.


protected void GetColumNames_DataReader()
{
  System.Data.SqlClient.SqlConnection SqlCon = new System.Data.SqlClient.SqlConnection("server=localhost;database=northwind;trusted_connection=true");
  System.Data.SqlClient.SqlCommand SqlCmd = new System.Data.SqlClient.SqlCommand("SELECT * FROM Products", SqlCon);

  SqlCon.Open();

  System.Data.SqlClient.SqlDataReader SqlReader = SqlCmd.ExecuteReader();
  System.Int32 _columncount = SqlReader.FieldCount;

  System.Web.HttpContext.Current.Response.Write("SqlDataReader Columns");
  System.Web.HttpContext.Current.Response.Write(" ");

  for ( System.Int32 iCol = 0; iCol < _columncount; iCol ++ )
  {
    System.Web.HttpContext.Current.Response.Write("Column " + iCol.ToString() + ": ");
    System.Web.HttpContext.Current.Response.Write(SqlReader.GetName( iCol ).ToString());
    System.Web.HttpContext.Current.Response.Write(" ");
  }

}

Це спочатку від: http://www.dotnetjunkies.ddj.com/Article/B82A22D1-8437-4C7A-B6AA-C6C9BE9DB8A6.dcik


1

Простіше досягти цього в SQL

var columnsList = dbContext.Database.SqlQuery<string>("SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'SCHEMA_OF_YOUE_TABLE' AND TABLE_NAME = 'YOUR_TABLE_NAME'").ToList();
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.