Können Sie die Spaltennamen von einem SqlDataReader erhalten?

276

Kann ich nach dem Herstellen einer Verbindung zur Datenbank den Namen aller Spalten abrufen, die in meinem zurückgegeben wurden SqlDataReader?

Blankman
quelle

Antworten:

460
var reader = cmd.ExecuteReader();

var columns = new List<string>();

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

oder

var columns = Enumerable.Range(0, reader.FieldCount).Select(reader.GetName).ToList();
Rob Stevenson-Leggett
quelle
71
Es ist verrückt, dass es keine aufzählbare Schnittstelle gibt, mit der Sie durch die Spalten iterieren können.
JohnFx
61
Etwas kürzer:columns = Enumerable.Range(0, reader.FieldCount) .Select(reader.GetName).ToList();
Alex
2
Das funktioniert super. Ich fand auch heraus, dass meine Spaltennamen alle in Großbuchstaben geschrieben waren, es sei denn, ich verwendete Anführungszeichen um den Spaltennamen. SELECT id AS "MyId" FROM table;
Styfle
Sir, es gibt alle Spaltennamen in Kleinbuchstaben zurück. Spaltennamen in der Tabelle sind alle in Großbuchstaben wie OBJECTID und der Leser gibt Kleinbuchstaben wie objectid zurück
Muneem Habib
2
. seine Dim Spalten () As String = Enumerable.Range (0, cTab.FieldCount) .Select (Funktion (n) cTab.GetName (n)) ToArray
swe
77

Es gibt eine GetNameFunktion, SqlDataReaderdie den Spaltenindex akzeptiert und den Namen der Spalte zurückgibt.

Umgekehrt gibt es eine, GetOrdinaldie einen Spaltennamen aufnimmt und den Spaltenindex zurückgibt.

Stephen Wrighton
quelle
3
Zwei Gründe: Erstens hat das Originalplakat noch keine Antwort ausgewählt, und zweitens gibt es andere Antworten, die eine detailliertere Beschreibung der „Lösung“ des Problems liefern als nur das Vorhandensein der Funktionalität. Ich persönlich mag die Antwort von Steven Lyons am besten, da sie nicht nur über GetName spricht, sondern auch über FieldType und DataType.
Stephen Wrighton
1
GetOrdinalwar perfekt. Ich suchte GetName, aber viel sauberere Lösung für mein Problem mit GetOrdinal.
Goodeye
43

Sie können die Spaltennamen von einem DataReader abrufen.

Hier ist der wichtige Teil:

  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
  }
Steven Lyons
quelle
15

Schon erwähnt. Nur eine LINQ- Antwort:

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

Der zweite ist sauberer und viel schneller. Selbst wenn Sie GetSchemaTablebeim ersten Ansatz zwischenspeichern, wird die Abfrage sehr langsam sein.

nawfal
quelle
Gibt es eine Möglichkeit, dies mit Werten zu tun?
Travis Heeter
@TravisHeeter Ich verstehe dich nicht. Finden Sie Spaltennamen aus Werten von was?
Nawfal
Ich meine nur einen östlichen Weg, um die Werte in der Ergebnismenge in eine Liste zu bringen, oder vielleicht das Ganze in ein IEnumerable <dynamic> -Objekt.
Travis Heeter
@TravisHeeter könnte ja tun reader.Cast<IDataRecord>().ToList(). Ich glaube, Sie könnten dort ein dynamicSchlüsselwort verwenden, IDataRecordaber ohne Nutzen. DataTablewurde entwickelt, um das einmalige Laden zu vereinfachen, sodass Sie dies auch verwenden können, aber den Vorteil des Ladens bei Bedarf verlieren (mit dem Datenleser können Sie das Laden jederzeit beenden), wie z var dt = new DataTable(); dt.Load(reader); return dt.AsEnumerable().ToList();. Es gibt viele Bibliotheken, die dies für Sie automatisieren können. Sie finden sie hier stackoverflow.com/questions/11988441 und hier stackoverflow.com/questions/1464883
nawfal
Ich habe es versucht reader.Cast<IEnumerable<dynamic>>und .Cast<dynamic>, aber es heißt, Cannot convert method group 'Cast' to non-delegate type 'dynamic'. Did you intend to invoke the method?was habe ich dort falsch gemacht? (Ich habe mir Ihre Quellen angesehen, aber Sie mussten den Spaltennamen kennen, was ich nicht weiß.)
Travis Heeter
6

Wenn Sie nur die Spaltennamen möchten, können Sie Folgendes tun:

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

Wenn Sie jedoch nur eine Zeile benötigen, gefällt mir mein AdoHelper-Zusatz. Dieser Zusatz ist ideal, wenn Sie eine einzeilige Abfrage haben und sich nicht mit der Datentabelle in Ihrem Code befassen möchten. Es wird ein Wörterbuch mit Spaltennamen und -werten zurückgegeben, bei dem die Groß- und Kleinschreibung nicht berücksichtigt wird.

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;
}
Yakir Manor
quelle
1
throw ex;ist eine schlechteste Praxis.
Asawyer
2
Es ist nur ein Beispiel
Yakir Manor
5
Asawyer, du solltest wenigstens sagen warum. Ich nehme an, Sie werden sagen, Sie sollten "werfen" verwenden. Stattdessen, damit Sie nicht die ursprünglichen Details der Strack-Spur verlieren.
Brent Rittenhouse
3

Verwenden Sie eine Erweiterungsmethode:

    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;
    }
Rob Sedgwick
quelle
2

Sie können sicher.


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

}

Dies ist ursprünglich von: http://www.dotnetjunkies.ddj.com/Article/B82A22D1-8437-4C7A-B6AA-C6C9BE9DB8A6.dcik

Jeremiah Peschka
quelle
1

In SQL ist dies einfacher zu erreichen

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();
Almett
quelle