Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extract from DataRow or DataReader with one function

I'm looking for a solution for how to be able to extract data from a database when using either a DataRow and a DataReader with only one function (or one base function).

My problem stems from the fact that sometimes I need a DataReader and sometimes I need a DataTable/DataRow but then in order to extract the data from those objects I need two seperate Data access methods because they do not share an interface.

Basically when my database structure changes, I don't want to have to go in and write the following data retrieval code in multiple functions:

someValue = dr["someValue"]

It's the same syntax and does the same thing so I want a function that shares that functionality regardless of whether I'm using a DataReader or DataTable/DataRow to extract the data from the database.

like image 761
Nate32 Avatar asked Jun 09 '11 13:06

Nate32


People also ask

How do I get data from ExecuteReader?

To retrieve data using a DataReader, create an instance of the Command object, and then create a DataReader by calling Command. ExecuteReader to retrieve rows from a data source.

Which is better DataReader or DataAdapter?

Using a DataReader produces faster results than using a DataAdapter to return the same data. Because the DataAdapter actually uses a DataReader to retrieve data, this should not surprise us.

Which is faster DataSet or DataReader?

DataReader provides faster performance, but has read-only and forward-only access. DataSet, on the other hand, is high resource-consuming, but offers more control and a disconnected nature.

What are the differences between using SqlDataAdapter vs SqlDataReader for getting data from a DB?

A SqlDataAdapter is typically used to fill a DataSet or DataTable and so you will have access to the data after your connection has been closed (disconnected access). The SqlDataReader is a fast forward-only and connected cursor which tends to be generally quicker than filling a DataSet/DataTable.


2 Answers

You can use CreateDataReader method in DataTable class to access data through DbDataReader base class. Hence you can change the implementation but keep the mapping.

public List<MyType> GetMyTypeCollection(DbDataReader reader)
{
//mapping code here
}

It would be better if you can move to an ORM where you do not have to map manually.

Take a look at this micro ORM Dapper

like image 181
Eranga Avatar answered Oct 06 '22 12:10

Eranga


Use this article to convert the datareader to a datatable and then you can interface both as a datatable

So you would basically add this function that get's called from your dataLayer:

public DataTable ConvertDataReader(SqlDataReader dr)
{
  SqlDataReader dr = cmd.ExecuteReader(CommandBehavior.CloseConnection); 
  DataTable dtSchema = dr.GetSchemaTable();
  DataTable dt = new DataTable();

  // You can also use an ArrayList instead of List<>
  List<DataColumn> listCols = 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"]));
        column.Unique = (bool)drow["IsUnique"];
        column.AllowDBNull = (bool)drow["AllowDBNull"];
        column.AutoIncrement = (bool)drow["IsAutoIncrement"];
        listCols.Add(column);
        dt.Columns.Add(column);
     }
  }

  // Read rows from DataReader and populate the DataTable 
  while (dr.Read())
  {
    DataRow dataRow = dt.NewRow();
    for(int i = 0; i < listCols.Count; i++)
    {
      dataRow[((DataColumn)listCols[i])] = dr[i];
    }
    dt.Rows.Add(dataRow);
  }
}

And then in your function where you get the datatable, you would then do an if it's a dataReader, pass the reader to the function to return a datatable:

DataTable dtFromReader = ConvertDataReader(dr);
like image 26
TBohnen.jnr Avatar answered Oct 06 '22 13:10

TBohnen.jnr