Как заполнить DataTable с помощью DataReader - PullRequest
4 голосов
/ 03 ноября 2010

Я хочу заполнить DataTable с помощью DataReader.

Я создал такой объект

SqlDataReader dr = cmd.ExecuteReader();

if(dr.HasRows)
{

}

Ответы [ 4 ]

13 голосов
/ 14 февраля 2014

Если все, что вам нужно, это DataOnly 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);

Кредит, где он должен: http://www.dotnetcurry.com/showarticle.aspx?ID=143

3 голосов
/ 02 марта 2015

DataTable.load () может использоваться для общего подхода.

do {
    var table = new DataTable();
    table.Load(reader);
    dataset.Tables.Add(table);
} while(!reader.IsClosed);
2 голосов
/ 17 ноября 2016

Вы можете получить таблицу схем из вашего SqlDataReader dr, чтобы получить имена столбцов, сохранить имена в List<string> и добавить их в виде столбцов на новый DataTable, а затем заполнить это 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 строк с помощью SELECT * FROM MyTable. Только код выше смог работать во всех сценариях, для меня.

Первоначально опубликовано Заполнить таблицу данных из устройства чтения данных от sarathkumar. Я предоставил сводку, сжал ее, добавил нулевые проверки и присвоение, если это нулевое значение, и добавил таблицу в DataSet и добавил условие DataSet в конце.

ПРИМЕЧАНИЕ. Для тех, кто использует OracleDataReader, я обнаружил, что вы можете столкнуться с ошибкой, если у вас есть поле NCLOB или CLOB, которое является пустым в таблице / наборе результатов, которые вы читаете. Я обнаружил, что если я проверил этот столбец, посмотрев на индекс i и выполнив dr.GetOracleClob(i) вместо dr[i], я перестал получать исключение. См. Ответ в EF + ODP.NET + CLOB = Значение не может быть пустым - Имя параметра: byteArray? , и я добавил это условие в коде выше, когда if (!dr.IsDBNull[i]). Точно так же, если у вас есть нулевое поле Decimal, я должен был проверить его с помощью dr.GetFloat(i);, так как ни dr.GetOracleDecimal(i);, ни dr.GetDecimal(i);, казалось, не могли корректно принять нулевое значение.

0 голосов
/ 03 ноября 2010

Чтобы заполнить DataSet, вы можете использовать что-то вроде:

var da = new SqlDataAdapter();
da.SelectCommand = cmd; // your SqlCommand object
var ds = new DataSet();
da.Fill(ds);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...