DataReader desacoplado con ADO.NET, Framework 4, LINQ. Programación por capas, velocidad de lectura máxima.

 

Desacoplar DataReader

Desacoplar DataReader

El acceso con DataReader a las bases de datos SQL Server es un técnica óptima para las consultas sobre páginas webs con listados casi infinito. Hoy en día el paginado esta infravalorado y comienza a estar en desuso, ya que nos gusta tener mucho contenido accesible para que los buscadores nos valoren bien, sobre todo Google.

El objetivo es aprovechar el modo conectado y su gran velocidad que nos ofrecen los DataReader sin renunciar a una arquitectura por capas.

DataReader Clásico

Aquí se puede ver un ejemplo de acceso de lectura en modo conectado con ADO.NET Y DataReader.

 Using connection as new sqlConnection
        Dim command As SqlCommand = New SqlCommand( _
          "SELECT id, nombre FROM personas;", _
          connection)
        connection.Open()
        Dim reader As SqlDataReader = command.ExecuteReader()
        If reader.HasRows Then
            Do While reader.Read()
                Console.WriteLine(reader.GetInt32(0) _
                  & vbTab & reader.GetString(1))
            Loop
        Else
            Console.WriteLine("No rows found.")
        End If

         reader.Close()
    End Using

Yield

Para lograr el desacople, lo primero que hacemos es quitar dependencias del acceso a datos, esto se puede conseguir con la instrucción Yield.

Esta instrucción es nativa de C# desde la versión del Framework 2.0, aparece en Visual Basic  Framework 4.5, o bien con el paquete Async CTP.

Yield permite guardar la posición exacta en memoria que ocupa está instrucción.
El código fuente también ocupa un trocito de memoria y cada línea de ejecución tiene su dirección. Yield se guarda está dirección para operar sobre el DataReader más adelante.

 Public Iterator Function getIDataReader(sql As String)  As IEnumerable(Of IDataReader)
        Using conn As New SqlConnection("cadena de conexion")
            Using da As New SqlCommand(sql, conn)
                conn.Open()
                Using dr As SqlDataReader = da.ExecuteReader
                    If dr.HasRows Then
                        While dr.Read
                            Yield dr 
                        End While
                    End If
                <a href="http://www.wholesaleprojerseys.com">wholesale mlb jerseys</a>   End Using
                conn.Close()
            End Using
    <a href="http://itomahoroba.com/archives/447">宣材写真撮ります</a>       End Using
    End Function

Arquitectura de capas

Llegados a este punto, es conveniente plantear una sencilla perspectiva de cómo podría estar montada nuestra aplicación por capas:

  • Modelo: Base de datos. SQL Server preferiblemente -> ADO -> Clase persona.
  • Vista: Presentación en WebForms. Una lista <ul><li> o unos cuantos <div>.
  • Controlador: Lógica que unirá ambas partes.
    • Aquí es donde un DataReader es más dificil de desacoplar.
    • Esta capa debería de trabajar meta-información con la Clase Persona y no con las clases de conexión.
    • Para conseguirlo utilizaremos LINQ en el modelo. (No “Linq to Sql“, sino la característica “Consulta en Memoria“)

Supongamos que mi clase persona tiene un constructor como este:

Class persona
    Public ID As String
    Public Nombre As String
    Public Sub New(_id As Integer, _Nombre As String)
        ID = _id
        Nombre = _Nombre
    End Sub
End Class

En un principio con una lectura sobre Data.DataTable podría obtener en la capa de datos el objeto persona y usarlo completamente desacoplado en el controlador, pero con DataReader no es tan sencillo, ya que se trabaja en modo conectado y hay que obtener la información de cada fila antes de que itere sobre la siguiente. También recordar que en el acceso de un DataReader sólo se puede ir hacia delante en la wholesale nfl jerseys colección.
Por ejemplo:

Dim lista As New List(Of persona)
        Using conn As New SqlConnection("cadena de conexion")
            Using da As New SqlCommand(Sql, conn)
                conn.Open()
                Using dr As SqlDataReader = da.ExecuteReader
                    If dr.HasRows Then
                      While dr.Read
                    <a href="http://www.cheapjerseyspro.com">cheap nba jerseys</a>           lista.Add(New persona(dr("id"), dr("nombre")))
                        End While
                    End If
                End Using
                conn.Close()
  <a href="https://www.adolfogarcialopez.net/renderizar-un-control-en-asp-net-y-guardar-en-un-string/">HTML</a>             End Using
        End Using

 

LINQ, Consulta en memoria

Esto es precisamente lo que se pretende evitar, usar este código en la parte del controlador. Como solución vamos a construir el método que dará la cara en la capa de datos para obtener las personas introducidas en una lista genérica con DataReader cuando queramos y donde queramos.

 Public Function getLista(Optional ByVal sWhere As String = "", Optional ByVal sOrder As String = "") As List(Of persona)

        Dim sql As String = "select * from personas"
        Return (From reg As IDataReader In getIDataReade(sql) Select New persona(reg("id"), reg("nombre"))).ToList

    End Function

La razón por la que podemos desacoplar es que en lugar de iterar el DataReader cuando invocamos la función getLista, se itera cuando accedemos a los elementos de la lista.

Esto es posible gracias a LINQ y su forma de operar “Consulta en memoria“.

Aquí dejo el código completo de una posible clase persona.

Class persona
    Public ID As String
    Public Nombre As String

    Public Sub New(_id As Integer, _Nombre As String)
        ID = _id
        Nombre = _Nombre
    End Sub

    Public Function getLista(Optional ByVal sWhere As String = "", Optional ByVal sOrder As String = "") As List(Of persona)

        Dim sql As String = "select * from personas"
        Return (From reg As IDataReader In getIDataReader(sql) Select New persona(reg("id"), reg("nombre"))).ToList

    End Function

    Public Iterator Function getIDataReader(sql As String) As IEnumerable(Of IDataReader)

        Using conn As New SqlConnection("cadena de conexion")
            Using da As New SqlCommand(sql, conn)
                conn.Open()
                Using dr As SqlDataReader = da.ExecuteReader
                    If dr.HasRows Then
                While dr.Read
                            Yield dr
                        End While
                    End If
                End Using
                conn.Close()
            End Using
        End Using
    End Function
End Class

 

Esta entrada fue publicada en ADO.NET, ASP .NET Webforms, DataReader, LINQ y etiquetada , , . Guarda el enlace permanente.

2 Respuestas a DataReader desacoplado con ADO.NET, Framework 4, LINQ. Programación por capas, velocidad de lectura máxima.

  1. Dante dijo:

    Adolfo, muy buen articulo. Es lo que estaba buscando

    Gracias

    Dante

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.