Thursday, January 19, 2006
DataReaders, Dispose and doing things properly!
Anyone who has attempted to follow the confusion around close() and dispose() on objects, particluarly data objects would have been even more confused when using things such as datareaders when it wasn't always entirely clear when they closed or the best time to close them. Datareaders are fast and optimied and the using statement made our lives easier, but the problem when returning a datareader is that the underlying connection is closed and so we can't access it. If we really wanted to return it we'd have to do some work to return somethnig other than a datareader (or expect the consumer to manage the closing etc....!!) and then the using statement would do wat we wanted.
It basically was a pain. Until .Net 2.0.
Now the DataTable can load a datareader directly and hence we can get an optimized cache of our data , still have the underlying connections closed and disposed by the using statement and get our data back!! What's more (and this was REALLY cool for me) - the DataTable now has a CreateDataReader() method which returns a DataTableReader object which is derived from DbDataReader which itself implements the IDataReader interface and so our DataTableReader can be cast to an IDataReader allowing our public methods to remain fairly generic (basically if we have performance issues, we can change the datalayer to do something with a datareader without changing all our interfaces).
So to end with some code, we can write a data method something like...
public static IDataReader GetData(string filter)
{
try
{
using (SqlConnection conn = new SqlConnection(connstr))
{
conn.Open();
using (SqlCommand command = new SqlCommand(mysp, conn))
{
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add("@Something", SqlDbType.NVarchar, 100).Value = filter;
DataTable dt = new DataTable();
using (SqlDataReader rdr = command.ExecuteReader())
{
dt.Load(rdr);
}
return dt.CreateDataReader();
}
}
}
}
read 0 comments |
It basically was a pain. Until .Net 2.0.
Now the DataTable can load a datareader directly and hence we can get an optimized cache of our data , still have the underlying connections closed and disposed by the using statement and get our data back!! What's more (and this was REALLY cool for me) - the DataTable now has a CreateDataReader() method which returns a DataTableReader object which is derived from DbDataReader which itself implements the IDataReader interface and so our DataTableReader can be cast to an IDataReader allowing our public methods to remain fairly generic (basically if we have performance issues, we can change the datalayer to do something with a datareader without changing all our interfaces).
So to end with some code, we can write a data method something like...
public static IDataReader GetData(string filter)
{
try
{
using (SqlConnection conn = new SqlConnection(connstr))
{
conn.Open();
using (SqlCommand command = new SqlCommand(mysp, conn))
{
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add("@Something", SqlDbType.NVarchar, 100).Value = filter;
DataTable dt = new DataTable();
using (SqlDataReader rdr = command.ExecuteReader())
{
dt.Load(rdr);
}
return dt.CreateDataReader();
}
}
}
}
read 0 comments |