您可以从 SqlDataReader 获取列名吗?

Posted

技术标签:

【中文标题】您可以从 SqlDataReader 获取列名吗?【英文标题】:Can you get the column names from a SqlDataReader? 【发布时间】:2009-03-25 13:43:31 【问题描述】:

连接数据库后,能否获取我的SqlDataReader中返回的所有列的名称?

【问题讨论】:

【参考方案1】:
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();

【讨论】:

没有可枚举的接口让您遍历列真是太疯狂了。 短一点:columns = Enumerable.Range(0, reader.FieldCount) .Select(reader.GetName).ToList(); 这很好用。我还发现我的列名都是大写的,除非我在列名周围使用引号。 SELECT id AS "MyId" FROM table; 先生,它以小写形式返回所有列名。表中的列名都是大写的,比如 OBJECTID,而 reader 返回的是小写,比如 objectid its Dim columns() As String = Enumerable.Range(0, cTab.FieldCount).Select(Function(n) cTab.GetName(n)).ToArray【参考方案2】:

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

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

【讨论】:

两个原因:首先,原始发布者尚未选择答案,其次,还有其他答案可以更详细地描述问题的“解决方案”,然后只是功能的存在。就个人而言,我最喜欢 Steven Lyons 的回答,因为它不仅涉及 GetName,还涉及 FieldType 和 DataType。 GetOrdinal 非常完美。我一直在寻找GetName,但对于GetOrdinal 的问题,我的解决方案要干净得多。【参考方案3】:

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

【讨论】:

【参考方案4】:

已经提到了。只是一个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 做到这一点? @TravisHeeter 我不明白你。从什么值中查找列名? 我的意思只是一种将结果集中的值放入列表的东方方式,或者可能将整个事物放入 IEnumerable 对象中。 @TravisHeeter 是的,可以做到reader.Cast&lt;IDataRecord&gt;().ToList()。我相信您可以在那里使用 dynamic 关键字而不是 IDataRecord 但没有任何好处。 DataTable 旨在简化一次性加载,因此您也可以使用它,但您失去了按需加载的好处(使用数据阅读器,您可以随时停止加载),例如 var dt = new DataTable(); dt.Load(reader); return dt.AsEnumerable().ToList();。有许多库可以为您自动执行此操作,请在此处找到它们 ***.com/questions/11988441 和此处 ***.com/questions/1464883 我试过reader.Cast&lt;IEnumerable&lt;dynamic&gt;&gt;.Cast&lt;dynamic&gt;,但它说,Cannot convert method group 'Cast' to non-delegate type 'dynamic'. Did you intend to invoke the method? 我在那里做错了什么? (我查看了您的来源,但他们要求您知道列名,而我不知道)【参考方案5】:

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

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;

【讨论】:

throw ex; 是最糟糕的做法。 只是一个例子 Asawyer,你至少应该说出原因。我假设你会说你应该使用“throw;”。而是这样您就不会丢失原始的轨迹详细信息。【参考方案6】:

使用扩展方法:

    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;
    

【讨论】:

【参考方案7】:

对于我来说,我会写一个这样的扩展方法:

public static string[] GetFieldNames(this SqlDataReader reader)

     return Enumerable.Range(0, reader.FieldCount).Select(x => reader.GetName(x)).ToArray();

【讨论】:

【参考方案8】:

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

【讨论】:

是的,这里有一篇关于它的文章:Getting schema info from the datareader msdn.microsoft.com/en-us/library/haa3afyz(v=vs.110).aspx【参考方案9】:

你当然可以。


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

【讨论】:

【参考方案10】:

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

【讨论】:

以上是关于您可以从 SqlDataReader 获取列名吗?的主要内容,如果未能解决你的问题,请参考以下文章

获取SqlDataReader的列名

如何从 SqlDataReader 获取列的表名

使用 SqlDataReader.IsDBNull 时使用列名

我们可以从 HBase 表中获取所有列名吗?

您可以从大查询 SDK 中的 Select 语句中获取列名而不运行它吗

我们可以从 Google BigQuery 中的特定表中获取列名吗?