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 2016 년

61
조금 더 짧은 :columns = Enumerable.Range(0, reader.FieldCount) .Select(reader.GetName).ToList();
Alex

2
이것은 잘 작동합니다. 또한 열 이름 주위에 따옴표를 사용하지 않으면 열 이름이 모두 대문자라는 것을 알았습니다. SELECT id AS "MyId" FROM table;
styfle

모든 열 이름을 소문자로 반환합니다. 테이블의 열 이름은 모두 OBJECTID와 같은 대문자이며 독자는 objectid와 같은 소문자를 반환합니다
Muneem Habib

2
그것의 Dim columns () As String = Enumerable.Range (0, cTab.FieldCount) .Select (Function (n) cTab.GetName (n)). ToArray
swe

77

GetName기능이 있습니다SqlDataReader 열 인덱스를 허용하고 열 이름을 반환 .

반대로 GetOrdinal열 이름을 가져와 열 인덱스를 반환하는가 있습니다.


3
두 가지 이유 : 첫째, 원래 포스터가 아직 답을 선택하지 않았으며 둘째, 문제의 '해결책'에 대한 자세한 설명을 제공 한 다음 기능의 존재 여부에 대한 다른 답변이 있습니다. 개인적으로, 나는 Steven Lyons의 대답이 GetName에 대해 이야기 할뿐만 아니라 FieldType 및 DataType으로도 들어가는 것이 가장 좋습니다.
Stephen Wrighton

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첫 번째 접근 방식으로 캐시하더라도 쿼리 속도가 매우 느려집니다.


Values로 이것을 수행하는 방법이 있습니까?
트래비스 Heeter

@TravisHeeter 나는 당신을 얻을 수 없습니다. 무엇의 값에서 열 이름을 찾으십니까?
nawfal

결과 집합의 값을 목록으로 가져 오거나 IEnumerable <dynamic> 객체로 전체를 가져 오는 동적 인 방법을 의미합니다.
트래비스 Heeter

@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
nawfal

나는 시도 reader.Cast<IEnumerable<dynamic>>하고 .Cast<dynamic>있지만,라고 Cannot convert method group 'Cast' to non-delegate type 'dynamic'. Did you intend to invoke the method?내가 잘못이 무슨 짓을? (나는 당신의 출처를 보았지만 열 이름을 알아야합니다.)
Travis Heeter

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
단지 예
Yakir Manor

5
Asawyer, 최소한 이유를 말해야합니다. 나는 당신이 "throw;"를 사용해야한다고 말할 것이라고 가정합니다. 대신 원본 트랙 추적 세부 사항을 잃지 않도록하십시오.
브렌트 리튼 하우스


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();
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.