【发布时间】:2010-11-03 16:52:25
【问题描述】:
我想使用 DataReader 填充 DataTable。
我已经创建了这样的对象
SqlDataReader dr = cmd.ExecuteReader();
if(dr.HasRows)
{
}
【问题讨论】:
标签: asp.net ado.net sqldatareader
我想使用 DataReader 填充 DataTable。
我已经创建了这样的对象
SqlDataReader dr = cmd.ExecuteReader();
if(dr.HasRows)
{
}
【问题讨论】:
标签: asp.net ado.net sqldatareader
如果您只需要一个用于报告或网络的只读数据表,请尝试以下操作:
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);
【讨论】:
DataTable.load() 可用于通用方法。
do {
var table = new DataTable();
table.Load(reader);
dataset.Tables.Add(table);
} while(!reader.IsClosed);
【讨论】:
您可以从 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); 似乎都不能正确地适应空值。
【讨论】:
要填写DataSet,您可以使用以下内容:
var da = new SqlDataAdapter();
da.SelectCommand = cmd; // your SqlCommand object
var ds = new DataSet();
da.Fill(ds);
【讨论】: