Konverze SqlDataReaderu na DataSet

Ač to není příliš šťastná situace, může se nám někdy přihodit, že potřebujeme konvertovat SqlDataReader na DataSet.
V .NET Frameworku 1.1 jsou v podstatě dvě základní cesty – buď to udělat ručně, prvek po prvku, nebo si uvědomit, že DataAdapter dělá v podstatě totéž, a už by to tedy mohlo být někde řešeno (v .NET Frameworku 2.0 již je tato funkčnost exponováno prostřednictvím metody DataTable.Load(), viz níže).
Ručně to vypadá např. takto (kód není můj, tak to berte s rezervou):

public static DataSet DataReaderToDataSet( SqlDataReader rd )
{
    DataSet ds = new DataSet();
    do
    {
       DataTable st = rd.GetSchemaTable();
       DataTable Dt = new DataTable();
 
       if (st != null)
       {
          for (int i = 0 ; i < st.Rows.Count ; i++)
          {
             DataRow dr = st.Rows[i];
             string columnName = (string)dr["ColumnName"];
             DataColumn column = new DataColumn(columnName, (Type)dr["DataType"]);
             dt.Columns.Add(column);
          }
 
          ds.Tables.Add(dt);
 
          while (rd.Read())
          {
             DataRow dr = dt.NewRow();
 
             for (int i = 0; i < rd.FieldCount; i++)
                dr[i] = rd.GetValue(i);
 
             dt.Rows.Add(dr);
          }
       }
       else
       {
          DataColumn column = new DataColumn("RowsAffected");
          dt.Columns.Add(column);
          ds.Tables.Add(dt);
          DataRow dr = dt.NewRow();
          dr[0] = rd.RecordsAffected;
          dt.Rows.Add(dr);
       }
    }
    while (rd.NextResult());
 
    return ds;
}

Mnohem lepší fígl přes DataAdapter spočívá ve zjištění, že třída DbDataAdapter, z které jsou odvozeny všechny specifické DataAdaptery obsahuje metodu protected Fill(DataTable, IDataReader).

Můžeme tedy vytvořit vlastní DataAdapter odvozený od DbDataAdapteru, který tuto metodu použije ke zbudování příslušné tabulky:

public class DataReaderAdapter : DbDataAdapter 
{ 
   public int FillFromReader(DataTable dataTable, IDataReader dataReader) 
   { 
      return this.Fill(dataTable, dataReader); 
   } 
   protected override RowUpdatedEventArgs CreateRowUpdatedEvent( 
      DataRow dataRow, 
      IDbCommand command, 
      StatementType statementType, 
      DataTableMapping tableMapping)
   {
      return null;
   } 
   protected override RowUpdatingEventArgs CreateRowUpdatingEvent( 
      DataRow dataRow, 
      IDbCommand command, 
      StatementType statementType, 
      DataTableMapping tableMapping)
   {
      return null;
   } 
   protected override void OnRowUpdated( 
      RowUpdatedEventArgs value)
   {
   } 
   protected override void OnRowUpdating( 
      RowUpdatingEventArgs value)
   {
   } 
}

…a dát DataTable do DataSetu už není problém, případně escalovat SqlDataReader na další rowset a vytáhnout další tabulku. Ostatně DbDataAdapter obsahuje i mnoho další overloadů metody Fill() a můžeme si tak udělat mnohem chytřejší DataReaderAdapter.

Update pro .NET Framework 2.0

.NET Framework 2.0 již tuto problematiku řeší metodou DataTable.Load();

Napsat komentář

Vyplňte detaily níže nebo klikněte na ikonu pro přihlášení:

WordPress.com Logo

Komentujete pomocí vašeho WordPress.com účtu. Log Out / Změnit )

Twitter picture

Komentujete pomocí vašeho Twitter účtu. Log Out / Změnit )

Facebook photo

Komentujete pomocí vašeho Facebook účtu. Log Out / Změnit )

Google+ photo

Komentujete pomocí vašeho Google+ účtu. Log Out / Změnit )

Připojování k %s