¿Puedes obtener los nombres de columna de un SqlDataReader?


276

Después de conectarme a la base de datos, ¿puedo obtener el nombre de todas las columnas que se devolvieron en mi SqlDataReader?

Respuestas:


460
var reader = cmd.ExecuteReader();

var columns = new List<string>();

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

o

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

71
Es una locura que no haya una interfaz enumerable que le permita recorrer las columnas.
JohnFx

61
Un poco más corto:columns = Enumerable.Range(0, reader.FieldCount) .Select(reader.GetName).ToList();
Alex

2
Esto funciona muy bien. También descubrí que los nombres de mis columnas estaban en mayúsculas a menos que usara comillas alrededor del nombre de la columna. SELECT id AS "MyId" FROM table;
styfle

sir está devolviendo todos los nombres de columna en minúsculas. Los nombres de las columnas en la tabla están en mayúsculas como OBJECTID y el lector está regresando en minúsculas como objectid
Muneem Habib

2
sus columnas Dim () As String = Enumerable.Range (0, cTab.FieldCount) .Select (Function (n) cTab.GetName (n)). ToArray
swe

77

Hay una GetNamefunción en la SqlDataReaderque acepta el índice de columna y devuelve el nombre de la columna.

Por el contrario, hay una GetOrdinalque toma el nombre de una columna y devuelve el índice de la columna.


3
Dos razones: en primer lugar, el póster original aún no ha elegido una respuesta y, en segundo lugar, hay otras respuestas que dan una descripción más detallada de la 'solución' del problema y luego solo la existencia de la funcionalidad. Personalmente, me gusta la respuesta de Steven Lyons, ya que no solo habla sobre GetName sino que también entra en FieldType y DataType.
Stephen Wrighton el

1
GetOrdinalfue perfecto. Estaba buscando GetName, pero una solución mucho más limpia para mi problema con GetOrdinal.
goodeye

43

Puede obtener los nombres de columna de un DataReader.

Aquí está la parte importante:

  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

Ya mencionado. Solo una respuesta 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();

El segundo es más limpio y mucho más rápido. Incluso si almacena GetSchemaTableen caché en el primer enfoque, la consulta será muy lenta.


¿Hay alguna manera de hacer esto con los valores?
Travis Heeter

@TravisHeeter No te entiendo. ¿Encontrar nombres de columnas a partir de valores de qué?
nawfal

Me refiero a solo una forma este de obtener los valores en el conjunto de resultados en una lista, o tal vez todo en un objeto IEnumerable <dynamic>.
Travis Heeter

@TravisHeeter sí podría hacer reader.Cast<IDataRecord>().ToList(). Creo que podría usar dynamicpalabras clave allí en lugar de hacerlo, IDataRecordpero sin ningún beneficio. DataTablefue diseñado para facilitar la carga de una vez, por lo que también puede usarlo, pero pierde el beneficio de cargar a pedido (con el lector de datos puede detener la carga en cualquier momento), como var dt = new DataTable(); dt.Load(reader); return dt.AsEnumerable().ToList();. Hay muchas bibliotecas que pueden automatizar esto para usted, encuéntrelas aquí stackoverflow.com/questions/11988441 y aquí stackoverflow.com/questions/1464883
nawfal

Lo intenté reader.Cast<IEnumerable<dynamic>>y .Cast<dynamic>, pero dice, Cannot convert method group 'Cast' to non-delegate type 'dynamic'. Did you intend to invoke the method?¿qué hice mal allí? (Miré sus fuentes, pero le exigieron que supiera el nombre de la columna, lo cual no sé)
Travis Heeter

6

Si solo desea los nombres de columna, puede hacer:

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"));
    }
}

Pero si solo necesita una fila, me gusta mi adición AdoHelper. Esta adición es excelente si tiene una consulta de una sola línea y no desea tratar con la tabla de datos en su código. Está devolviendo un diccionario de mayúsculas y minúsculas de nombres y valores de columna.

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;Es una peor práctica.
asawyer

2
es solo un ejemplo
Yakir Manor el

55
Asawyer, al menos deberías decir por qué. Asumo que vas a decir que deberías usar "tirar"; en su lugar, para que no pierda los detalles originales del seguimiento de la banda.
Brent Rittenhouse


3

Use un método de extensión:

    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

Seguro que puedes.


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(" ");
  }

}

Esto es originalmente de: http://www.dotnetjunkies.ddj.com/Article/B82A22D1-8437-4C7A-B6AA-C6C9BE9DB8A6.dcik


1

Es más fácil lograrlo en 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();
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.