我想使用DataReader填充DataTable。
我创建了像这样的对象
SqlDataReader dr = cmd.ExecuteReader();
if(dr.HasRows)
{
}
答案 0 :(得分:13)
如果你想要的只是一个用于报告或网络的ReadOnly DataTable,请试试这个:
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);
答案 1 :(得分:3)
DataTable.load()可用于通用方法。
do {
var table = new DataTable();
table.Load(reader);
dataset.Tables.Add(table);
} while(!reader.IsClosed);
答案 2 :(得分:2)
您可以从SqlDataReader dr
获取架构表以获取列名,将名称保存到List<string>
并将其添加为新DataTable
上的列,然后填写{ {1}}在DataTable
上使用列表中的名称进行索引:
dr
显然,您需要围绕这一切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行的表时失败了。对我来说,只有上面的代码可以在所有场景中使用。
最初由sarathkumar发布在Populate data table from data reader上。我提供了摘要,压缩了它,添加了空检查并分配了它是否为空值,并将表添加到SELECT * FROM MyTable
并在最后添加了DataSet
条件。
注意:对于使用DataSet
的用户,我发现如果您在表/结果集中有OracleDataReader
或NCLOB
字段为空,则可能会遇到错误正在读书。我发现如果通过查看索引CLOB
检查了该列并且i
而不是dr.GetOracleClob(i)
,我就停止了获取异常。请参阅EF + ODP.NET + CLOB = Value Cannot be Null - Parameter name: byteArray?上的回答,并在dr[i]
时在上面的代码中添加了此条件。同样,如果您有一个空if (!dr.IsDBNull[i])
字段,我必须使用Decimal
进行检查,因为dr.GetFloat(i);
和dr.GetOracleDecimal(i);
似乎都没有正确容纳空值。
答案 3 :(得分:0)
要填写DataSet
,您可以使用以下内容:
var da = new SqlDataAdapter();
da.SelectCommand = cmd; // your SqlCommand object
var ds = new DataSet();
da.Fill(ds);