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

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

【问题讨论】:

    标签: c# ado.net 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();。有许多库可以为您自动执行此操作,请在此处找到它们 stackoverflow.com/questions/11988441 和此处 stackoverflow.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 接口公开。

          【讨论】:

          【解决方案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();
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2011-03-07
              • 1970-01-01
              • 2010-10-12
              • 2022-10-13
              • 2013-10-02
              • 1970-01-01
              • 2010-11-28
              相关资源
              最近更新 更多