2010-11-03 177 views
3

我想使用DataReader填充DataTable。如何使用DataReader填充DataTable

我创建对象这样

SqlDataReader dr = cmd.ExecuteReader(); 

if(dr.HasRows) 
{ 

} 
+0

相关:http://stackoverflow.com/questions/18961938/populate-data-table-from-data-reader – vapcguy 2016-11-17 19:31:12

回答

0

来一补DataSet,您可以使用类似:

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

我知道这一点,我想使用datareader – NoviceToDotNet 2010-11-03 17:00:19

9

如果你想要的是一个只读数据表用于报告或网页,试试这个:

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); 
1

你可以从你SqlDataReader dr获取架构表得到的列名,名称保存到List<string>并将其添加为列上了一个新DataTable,然后填写,使用索引上dr从名字DataTable名单:

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)并没有太大的改进,因为当我试图抓取一列97列和80行左右的SELECT * FROM MyTable时,它失败了。只有上面的代码才能在所有场景下工作,对我来说。

最初发布在Populate data table from data reader由sarathkumar。我提供了摘要,精简了它,添加了空检查并分配它是否为空值,并将该表添加到DataSet并在最后添加了DataSet条件。

注意:对于那些使用OracleDataReader,我发现如果您正在阅读的表/结果集中有一个空值为NCLOBCLOB的字段,则会发生错误。我发现如果我通过查看索引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);似乎都无法正确适应空值。