DEV Community

Iulio Cesar
Iulio Cesar

Posted on • Edited on

2 2

Obtener valores tipados de IDataReader

¿Qué es un 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.

Link: https://docs.microsoft.com/en-us/dotnet/api/system.data.idatareader?view=net-5.0

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.

Implementaciones

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

¿Cuál es el problema?

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)
};
Enter fullscreen mode Exit fullscreen mode

¿Cómo solucionarlo?

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")
};
Enter fullscreen mode Exit fullscreen mode

¿Cómo funciona?

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));
    }
}
Enter fullscreen mode Exit fullscreen mode

Pero la clase SqlDataReader ya cuenta con un método similar

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

Hostinger image

Get n8n VPS hosting 3x cheaper than a cloud solution

Get fast, easy, secure n8n VPS hosting from $4.99/mo at Hostinger. Automate any workflow using a pre-installed n8n application and no-code customization.

Start now

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay