你能从 SqlDataReader 获取列名吗?

问题描述 投票:0回答:12

连接到数据库后,我可以获取我的

SqlDataReader
中返回的所有列的名称吗?

c# ado.net sqldatareader
12个回答
533
投票
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();

88
投票

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

相反,有一个

GetOrdinal
接受列名并返回列索引。


61
投票

您可以从 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
  }

20
投票

已经提到过。只是一个 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
,查询也会非常慢。


7
投票

如果您只想要列名称,您可以这样做:

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

5
投票

使用扩展方法:

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

5
投票

对我来说,我会编写这样的扩展方法:

public static string[] GetFieldNames(this SqlDataReader reader)
{
     return Enumerable.Range(0, reader.FieldCount).Select(x => reader.GetName(x)).ToArray();
}

3
投票

我使用 GetSchemaTable 方法,该方法通过 IDataReader 接口公开。


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


2
投票

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

0
投票

奇怪的是,对于这样一个老问题,没有人建议使用 DbDataReaderExtensions.GetColumnSchema(DbDataReader) 方法

var colNames = reader.GetColumnSchema().Select((dbCol) => dbCol.ColumnName);

其异步等效物

var colNames = (await reader.GetColumnSchemaAsync()).Select((col) => col.ColumnName);

0
投票

这是对更流行的答案的调整,可以说有一些小的改进:

var columnNames = new HashSet<string>(
    Enumerable.Range(0, reader.FieldCount).Select(reader.GetName),
    StringComparer.OrdinalIgnoreCase);

要检查

TaskId
(或
taskid
taskID
TaskID
等 - 适用于所有这些):

if (columnNames.Contains("TaskId")) {
    // yes, the reader has this column name...
}

与其他答案对比:

  • 列检查不区分大小写。
  • 列检查语法的可读性丝毫不减。
  • 使用
    HashSet
    速度更快,至少在纸面上:
    O(log n)
    相对于
    O(n)
    。如果只有少数列,这可能并不重要。
© www.soinside.com 2019 - 2024. All rights reserved.