24
Obtener valores tipados de IDataReader
La documentación oficial de microsoft lo define como:
Provides a means of reading one or more forward-only streams of result sets obtained by executing a command at a data source, and is implemented by .NET data providers that access relational databases.
En Resumen, se trata de una interface que nos permite leer un conjunto de datos de manera secuencial hacia adelante, se implementa mediante proveedores de datos que tienen acceso a bases de datos relacionales.
Al tratarse de una interfaz, esta puede tener diferentes implementaciones las cuales dependerán del proveedor de datos algunas de las mas populares son:
- SqlDataReader
- MySqlDataReader
- SqliteDataReader
La interfaz expone diversos métodos para para acceder a los valores de los registros, sin embargo la manera de acceder es mediante la posición del campo, por ejemplo:
using var connection = new SqlConnection();
using var command = connection.CreateCommand();
command.CommandText = "StoredProcedureName";
command.CommandType = CommandType.StoredProcedure;
using IDataReader rd = command.ExecuteReader();
var person = new Person
{
Name = rd.GetString(0),
LastName = rd.GetString(1),
DateOfBirth = rd.GetDateTime(2)
};
Podemos crear nuestro propio método que nos permita acceder a los valores mediante su nombre y asignando el tipo, como se ve en este ejemplo
using var connection = new SqlConnection();
using var command = connection.CreateCommand();
command.CommandText = "StoredProcedureName";
command.CommandType = CommandType.StoredProcedure;
using IDataReader rd = command.ExecuteReader();
var person = new Person
{
Name = rd.GetField<string>("Name"),
LastName = rd.GetField<string>("LastName"),
DateOfBirth = rd.GetField<DateTime>("DateOfBirth")
};
Haciendo uso de los métodos de extensión debemos crear la siguiente clase estática
public static class Extensions
{
public static T GetField<T>(this IDataReader reader, string name)
{
var value = reader[name];
// En caso que el valor sea nulo retornara el valor default del tipo
if (value == null || value == DBNull.Value)
{ return default(T); }
// En caso que se trate convertir a un Enum, el metodo de coversion es diferente
if (typeof(T).IsEnum)
{ return (T)Enum.Parse(typeof(T), value.ToString()); }
// En caso que se trate convertir a un Nullable<>, el metodo de coversion es diferente
if (Nullable.GetUnderlyingType(typeof(T)) != null)
{ return (T)value; }
// Metodo de conversión default
return (T)Convert.ChangeType(value, typeof(T));
}
}
Es correcto, la clase SqlDataReader ya cuenta con el método de extensión GetFieldValue sin embargo al utilizar esta clase perdemos la modularidad que obtenemos al usar IDataReader ya que al utilizar solo las interfaces podríamos por ejemplo cambiar de SQL Server a MySQL de una manera sencilla
24