您可以从SqlDataReader获取列名吗?


Answers:


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 2011年

61
短一点:columns = Enumerable.Range(0, reader.FieldCount) .Select(reader.GetName).ToList();
Alex

2
这很好。我还发现,除非我在列名周围使用引号,否则我的列名都是大写的。SELECT id AS "MyId" FROM table;
styfle

先生,它以小写形式返回所有列名。表中的列名都像OB​​JECTID一样都是大写字母,而读者则像objectid一样返回小写字母
Muneem Habib 2015年

2
。其暗淡列()作为字符串= Enumerable.Range(0,cTab.FieldCount)。选择(功能(n)的cTab.GetName(N))的ToArray
SWE

77

上有一个GetName函数,该函数SqlDataReader接受列索引并返回列的名称。

相反,有一个GetOrdinal接受列名并返回列索引。


3
有两个原因:首先,原始发布者尚未选择答案,其次,还有其他答案为问题的“解决方案”提供了更详细的描述,然后仅是功能的存在。就个人而言,我最喜欢Steven Lyons的回答,因为它不仅涉及GetName,而且涉及FieldType和DataType。
斯蒂芬·赖顿2013年

1
GetOrdinal太完美了 我一直在寻找GetName,但是解决我的问题的方法更干净GetOrdinal
眼神

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中
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 2015年

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
Asawyer,您至少应该说出原因。我假设您要说的是应该使用“投掷”;相反,这样您就不会丢失原始的跟踪跟踪详细信息。
布伦特·里滕豪斯


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();
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.