如何使用 DataReader 填充 DataTable

发布于 2024-09-30 03:46:58 字数 141 浏览 0 评论 0原文

我想使用 DataReader 填充 DataTable。

我创建了这样的对象

SqlDataReader dr = cmd.ExecuteReader();

if(dr.HasRows)
{

}

I want to fill DataTable using DataReader.

I have created object like this

SqlDataReader dr = cmd.ExecuteReader();

if(dr.HasRows)
{

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

盗琴音 2024-10-07 03:46:58

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

  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

If all you want is a ReadOnly DataTable for reporting or web, try this:

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

Credit where it's due: http://www.dotnetcurry.com/showarticle.aspx?ID=143

请恋爱 2024-10-07 03:46:58

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

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

DataTable.load() can be used for a generic approach.

do {
    var table = new DataTable();
    table.Load(reader);
    dataset.Tables.Add(table);
} while(!reader.IsClosed);
贱贱哒 2024-10-07 03:46:58

您可以从 SqlDataReader dr 获取架构表以获取列名称,将名称保存到 List 并将它们添加为新 上的列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) 也好不了多少,因为当我尝试使用 SELECT * FROM MyTable 获取包含 97 列和大约 80 行的表格时,它失败了。对我来说,只有上面的代码能够在所有场景中工作。

最初发布于 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); 似乎正确地适应了空值。

You can get the Schema Table from your SqlDataReader dr to get the column names, save the names to a List<string> and add them as columns on a new DataTable, then fill that DataTable using indexing on dr with the names from the list:

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;

Obviously you'd need your try...catch...finally block around it all to handle exceptions and disposing your connection, and use the last condition after the finally. I found this helpful in order to handle finding out when I had results or not, and avoided issues with dt.Load(dr) that was failing when there were no results. ds.Fill(adapter) wasn't much better, as it failed when I tried to grab a table of 97 columns and about 80 rows with SELECT * FROM MyTable. Only the code above managed to work in all scenarios, for me.

Originally posted on Populate data table from data reader by sarathkumar. I provided the summary, condensed it, added the null checks and assigning if it's a null value, and added the table to a DataSet and added the DataSet condition at the end.

NOTE: For those using OracleDataReader, I found out that you can experience an error if you have an NCLOB or CLOB field that is null in the table/results set that you are reading. I found if I checked for that column by looking at the index i and did dr.GetOracleClob(i) instead of dr[i], I stopped getting the exception. See answer at EF + ODP.NET + CLOB = Value Cannot be Null - Parameter name: byteArray? and I added this condition in the code above when if (!dr.IsDBNull[i]). Similarly, if you have a null Decimal field, I had to check it with dr.GetFloat(i);, since neither dr.GetOracleDecimal(i); and dr.GetDecimal(i); seemed to correctly accommodate for a null value.

瘫痪情歌 2024-10-07 03:46:58

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

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

To fill a DataSet, you can use something like:

var da = new SqlDataAdapter();
da.SelectCommand = cmd; // your SqlCommand object
var ds = new DataSet();
da.Fill(ds);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文