Bisakah Anda mendapatkan nama kolom dari SqlDataReader?

276

Setelah terhubung ke database, bisakah saya mendapatkan nama semua kolom yang dikembalikan di saya SqlDataReader?

Blankman
sumber

Jawaban:

460
var reader = cmd.ExecuteReader();

var columns = new List<string>();

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

atau

var columns = Enumerable.Range(0, reader.FieldCount).Select(reader.GetName).ToList();
Rob Stevenson-Leggett
sumber
71
Ini gila bahwa tidak ada antarmuka enumerable yang memungkinkan Anda beralih melalui kolom.
JohnFx
61
Sedikit lebih pendek:columns = Enumerable.Range(0, reader.FieldCount) .Select(reader.GetName).ToList();
Alex
2
Ini sangat bagus. Saya juga mengetahui bahwa nama kolom saya semuanya huruf besar kecuali saya menggunakan tanda kutip di sekitar nama kolom. SELECT id AS "MyId" FROM table;
styfle
Pak, mengembalikan semua nama kolom dalam huruf kecil. Nama kolom dalam tabel semuanya huruf besar seperti OBJECTID dan pembaca mengembalikan huruf kecil seperti objectid
Muneem Habib
2
kolom Dimnya () Sebagai String = Enumerable.Range (0, cTab.FieldCount). Pilih (Fungsi (n) cTab.GetName (n)). ToArray
swe
77

Ada GetNamefungsi SqlDataReaderyang menerima indeks kolom dan mengembalikan nama kolom.

Sebaliknya, ada GetOrdinalyang mengambil nama kolom dan mengembalikan indeks kolom.

Stephen Wrighton
sumber
3
Dua alasan: pertama, poster asli belum memilih jawaban, dan kedua, ada jawaban lain yang memberikan deskripsi yang lebih rinci tentang 'solusi' masalah kemudian hanya keberadaan fungsi. Secara pribadi, saya suka jawaban Steven Lyons yang terbaik karena tidak hanya berbicara tentang GetName tetapi juga masuk ke FieldType dan DataType.
Stephen Wrighton
1
GetOrdinalsempurna. Saya mencari GetName, tetapi solusi yang jauh lebih bersih untuk masalah saya GetOrdinal.
selamat tinggal
43

Anda bisa mendapatkan nama kolom dari DataReader.

Inilah bagian penting:

  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
sumber
15

Sudah disebutkan. Hanya jawaban 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();

Yang kedua lebih bersih dan lebih cepat. Bahkan jika Anda melakukan cache GetSchemaTabledalam pendekatan pertama, permintaan akan menjadi sangat lambat.

nawfal
sumber
Apakah ada cara untuk melakukan ini dengan Nilai-nilai?
Travis Heeter
@ TravisHeeter, saya tidak mengerti. Cari nama kolom dari nilai apa?
nawfal
Maksud saya hanya cara timur untuk mendapatkan nilai-nilai dalam hasil yang ditetapkan ke daftar, atau mungkin semuanya ke objek <dynamic> IEnumerable.
Travis Heeter
@ TravisHeeter ya bisa dilakukan reader.Cast<IDataRecord>().ToList(). Saya yakin Anda bisa menggunakan dynamickata kunci di sanaIDataRecord tetapi tanpa manfaat. DataTabledirancang untuk memudahkan pemuatan sekali pakai, jadi Anda bisa menggunakannya juga tetapi Anda kehilangan manfaat pemuatan saat diminta (dengan pembaca data Anda bisa berhenti memuat kapan saja), seperti var dt = new DataTable(); dt.Load(reader); return dt.AsEnumerable().ToList();. Ada banyak perpustakaan yang dapat mengotomatisasi ini untuk Anda, temukan di sini stackoverflow.com/questions/11988441 dan di sini stackoverflow.com/questions/1464883
nawfal
Saya mencoba reader.Cast<IEnumerable<dynamic>>dan .Cast<dynamic>, tetapi dikatakan, Cannot convert method group 'Cast' to non-delegate type 'dynamic'. Did you intend to invoke the method?apa yang saya lakukan salah di sana? (Saya melihat sumber Anda, tetapi mereka meminta Anda untuk mengetahui nama kolom, yang saya tidak tahu)
Travis Heeter
6

Jika Anda hanya menginginkan nama kolom, Anda dapat melakukan:

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

Tetapi jika Anda hanya perlu satu baris, saya suka penambahan AdoHelper saya. Penambahan ini bagus jika Anda memiliki permintaan satu baris dan Anda tidak ingin berurusan dengan tabel data dalam kode Anda. Ini mengembalikan kamus kasus nama dan nilai kolom tidak sensitif.

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
sumber
1
throw ex;adalah praktik terburuk.
asawyer
2
ini hanya sebuah contoh
Yakir Manor
5
Asawyer, kamu setidaknya harus mengatakan mengapa. Saya berasumsi Anda akan mengatakan Anda harus menggunakan "lemparan;" alih-alih agar Anda tidak kehilangan detail jejak strack asli.
Brent Rittenhouse
3

Gunakan metode ekstensi:

    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
sumber
2

Kamu yakin bisa.


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

}

Ini berasal dari: http://www.dotnetjunkies.ddj.com/Article/B82A22D1-8437-4C7A-B6AA-C6C9BE9DB8A6.dcik

Jeremiah Peschka
sumber
1

Lebih mudah untuk mencapainya dalam 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();
Almett
sumber