【问题标题】:How do I fill a DataTable using DataReader如何使用 DataReader 填充 DataTable
【发布时间】:2010-11-03 16:52:25
【问题描述】:

我想使用 DataReader 填充 DataTable。

我已经创建了这样的对象

SqlDataReader dr = cmd.ExecuteReader();

if(dr.HasRows)
{

}

【问题讨论】:

标签: asp.net ado.net sqldatareader


【解决方案1】:

如果您只需要一个用于报告或网络的只读数据表,请尝试以下操作:

  conn = new SqlConnection(connString);
  string query = "SELECT * FROM Customers";
  SqlCommand cmd = new SqlCommand(query, conn);
  conn.Open();
  SqlDataReader dr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
  DataTable dt = new DataTable();
  dt.Load(dr);

信用到期:http://www.dotnetcurry.com/showarticle.aspx?ID=143

【讨论】:

    【解决方案2】:

    DataTable.load() 可用于通用方法。

    do {
        var table = new DataTable();
        table.Load(reader);
        dataset.Tables.Add(table);
    } while(!reader.IsClosed);
    

    【讨论】:

      【解决方案3】:

      您可以从 SqlDataReader dr 获取架构表以获取列名,将名称保存到 List<string> 并将它们作为列添加到新的 DataTable,然后使用 @ 上的索引填充 DataTable 987654327@ 与列表中的名称:

      DataSet ds = new DataSet();
      DataTable dtSchema = dr.GetSchemaTable();
      DataTable dt = new DataTable();
      List<DataColumn> listCols = new List<DataColumn>();
      List<DataColumn> listTypes = new List<DataColumn>();
      
      if (dtSchema != null)
      {
         foreach (DataRow drow in dtSchema.Rows)
         {
              string columnName = System.Convert.ToString(drow["ColumnName"]);
              DataColumn column = new DataColumn(columnName, (Type)(drow["DataType"]));
              listCols.Add(column);
              listTypes.Add(drow["DataType"].ToString()); // necessary in order to record nulls
              dt.Columns.Add(column);
          }
      }
      
      // Read rows from DataReader and populate the DataTable
      if (dr.HasRows)
      {
          while (dr.Read())
          {            
              DataRow dataRow = dt.NewRow();
              for (int i = 0; i < listCols.Count; i++)
              {
                  if (!dr.IsDBNull[i])
                  {
                      // If your query will go against a table with null CLOB fields 
                      // and that column is the 5th column...
                      if (strSQL == "SELECT * FROM TableWithNullCLOBField" && i == 4)
                          dataRow[((DataColumn)listCols[i])] = dr.GetOracleClob(i).Value;
                      // If you might have decimal values of null... 
                      // I found dr.GetOracleDecimal(i) and dr.GetDecimal(i) do not work
                      else if (listTypes[i] == System.Decimal)
                          dataRow[((DataColumn)listCols[i])] = dr.GetFloat(i);                
                      else 
                          dataRow[((DataColumn)listCols[i])] = dr[i];  // <-- gets index on dr
                  }
                  else  // value was null
                  {
                      byte[] nullArray = new byte[0];
                      switch (listTypes[i])
                      {
                          case "System.String":
                              dataRow[((DataColumn)listCols[i])] = String.Empty;
                          break;
                          case "System.Decimal":
                          case "System.Int16":  // Boolean
                          case "System.Int32":  // Number
                              dataRow[((DataColumn)listCols[i])] = 0;
                          break;
                          case "System.DateTime":
                              dataRow[((DataColumn)listCols[i])] = DBNull.Value;
                          break;
                          case "System.Byte[]":  // Blob
                              dataRow[((DataColumn)listCols[i])] = nullArray;
                          break;
                          default:
                              dataRow[((DataColumn)listCols[i])] = String.Empty;
                          break;
                      }
                  }
              }
              dt.Rows.Add(dataRow);
          }
          ds.Tables.Add(dt);
      }
      
      // Put this after everything is closed
      if (ds.Tables.Count > 0)
          return ds.Tables[0]; // there should only be one table if we got results
      else
          return null;
      

      显然你需要你的try...catch...finally 块来处理异常和处理你的连接,并使用finally 之后的最后一个条件。我发现这有助于了解我何时有结果,并避免了dt.Load(dr) 在没有结果时失败的问题。 ds.Fill(adapter) 也好不了多少,因为当我尝试用SELECT * FROM MyTable 抓取一个包含 97 列和大约 80 行的表时它失败了。对我来说,只有上面的代码能够在所有场景中工作。

      最初由 sarathkumar 在Populate data table from data reader 上发布。我提供了摘要,对其进行了压缩,添加了空检查并分配它是否为空值,并将表添加到 DataSet 并在末尾添加了 DataSet 条件。

      注意:对于那些使用OracleDataReader 的人,我发现如果您正在阅读的表/结果集中有一个为空的NCLOB 或CLOB 字段,您可能会遇到错误。我发现如果我通过查看索引i 来检查该列并且做了dr.GetOracleClob(i) 而不是dr[i],我就停止了异常。请参阅EF + ODP.NET + CLOB = Value Cannot be Null - Parameter name: byteArray? 的答案,当if (!dr.IsDBNull[i]) 时,我在上面的代码中添加了这个条件。同样,如果您有一个空的 Decimal 字段,我必须使用 dr.GetFloat(i); 检查它,因为 dr.GetOracleDecimal(i); 和 dr.GetDecimal(i); 似乎都不能正确地适应空值。

      【讨论】:

        【解决方案4】:

        要填写DataSet,您可以使用以下内容:

        var da = new SqlDataAdapter();
        da.SelectCommand = cmd; // your SqlCommand object
        var ds = new DataSet();
        da.Fill(ds);
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-08-13
          • 1970-01-01
          • 1970-01-01
          • 2015-08-19
          • 1970-01-01
          • 2014-10-12
          • 2014-08-22
          相关资源
          最近更新 更多