Miguel Angel Morán

Machines take me by surprise with great frecuency...

April 2007 - Artículos

LINQ y Visual Basic 9.0 con Windows Presentation Foundation

Introducción

Una de las principales pugnas que existen entre los programadores de Visual Basic. Net y C#  es la de saber cuál de los dos lenguajes es mejor. Esta pregunta comenzó desde que se lanzó la primera versión de .Net y continúa hasta nuestros días. Desafortunadamente la misma pregunta  en la mayoría de los casos es estéril toda vez que ambos lenguajes son capaces de hacer lo mismo salvo contadas excepciones. Sin embargo, particularmente tengo una extraña debilidad hacía Visual Basic. Net y quizás se deba a  que aprendí a programar con Pascal y me gustan mucho los lenguajes verbosos porque se me hacen más auto documentados.

Prefiero mil veces

Public Class MiClase

    Inherits MiClaseBase

    Implements IMiInterfaz

End Class

 

Que

    public class MiClase:MiClaseBase,IMiInterfaz {}

 

Cualquier otro argumento que no sea el anteriormente descrito podrá ser rebatido fácilmente por cualquier programador en C#, y desde luego podrán existir personas que no encuentren de acuerdo conmigo lo cual es totalmente válido.

Afortunadamente y para darnos gusto a todos, Microsoft ha continuado con un soporte completo a ambos lenguajes y todas las tecnologías nuevas son soportadas tanto por VB como por C#. Esto ha propiciado que los lenguajes continúen evolucionando tal es el caso de lo que sucederá en las versiones 3.0 y 9.0 de C# y VB.Net a respectivamente, que ahora traen mejoras enfocadas a la productividad el programador y soporte a la nueva tecnología de manejo de colecciones de datos de Microsoft que se denomina LINQ .

En este artículo veremos el soporte que tiene Visual Basic. Net a LINQ y algunas de las mejoras incorporadas dentro de lenguaje. Cabe señalar que todas estas funcionalidades han sido también implementadas desde luego con sintaxis diferente en C#.

 

LINQ es el acrónimo de Language Integrated Query .

Como explicamos en el artículo anterior de ORM, la mayoría de las aplicaciones hacen uso extensivo de entidades para generar persistencia dentro de una base de datos, de un archivo o de cualquier otro medio. Con LINQ ahora es posible manejar estas entidades con una sintaxis similar a la que utilizamos dentro de un manejador de base de datos como es el caso de sql server.

Sabemos nosotros que las bases de datos relacionales guardan su información en tablas que se encargarán de persistir las entidades del modelo orientado a objetos y para obtener o modificar información específica de la base de datos es necesario utilizar de DML (Data Manipulation Language). Los comandos de DML por excelencia son

SELECT

UPDATE

DELETE

Estos comandos son muy utiles y sencillos de utilizar y nos dan un gran poder para extraer adecuadamente la información que se requiere. Imagínense ahora que nosotros podamos utilizar sentencias como SELECT directamente dentro del lenguaje de programación. Pues ya no se lo imaginen porque eso será posible con LINQ.

Las ventajas son realmente infinitas debido a que la construcción de cueris será más fácil de realizar toda vez que ahora hay un soporte completo a Intellisense,  existen providers para manipular datos en forma de xml o bien con conexiones directas a bases de datos relacionales, es decir los jueces de sql dejarán de ser cadenas de texto y se convertían en parte integral del lenguaje de programación.

Manos a la obra

1) Para ejecutar este ejercicio es necesario bajar el ctp de Marzo de visual studio, el poder se encuentra de la siguiente dirección, http://www.microsoft.com/downloads/details.aspx?FamilyID=281fcb3d-5e79-4126-b4c0-8db6332de26e&DisplayLang=en

Viene en un conveniente formato de máquinas virtuales, por lo que ya no necesario echar a perder nuestra instalación de producción de visual studio 2005.

2) Una vez que está instalado vamos a seleccionar una nueva aplicación de Windows Presentation Foundation (aunque si quieren también desde luego pueden hacerlo con Windows forms o hasta con ASP.NET) y vamos hacer algunas payasaditas con la presentación de la ventana de WPF

<Window x:Class="Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Prueba LINQ" Height="300" Width="300">
<
Grid>
<
Grid.Background>
<
RadialGradientBrush>
<
GradientStop Color="Blue" Offset=".1" />
<
GradientStop Color="White" Offset=".8" />
</
RadialGradientBrush>
</
Grid.Background>
<Canvas Margin="50,69,55,91" Name="Canvas1" />
<
Button Background="Red" Margin="107,125.723333333333,110,121" Name="Button1" >Invocar</Button>
</
Grid>
</
Window>

 Este código producirá una ventanita como la siguiente

3) Vayamos ahora al codebehind de la ventana y añadamos dos nuevas clases una que se llamará cliente y otra que se llamará clientes que tendrá una lista genérica de cliente.

El código es el siguiente

 

Public Class Cliente
            Public Id As Integer
            Public
Nombre As String

            Public Telefono As String
' NOTESE QUE AQUI DEBERIAMOS PONER UN CONSTRUCTOR PARA INICIALIZAR LOS CAMPOS
' PERO CON VB 9.0 YA NO ES NECESARIO :) PORQUE PODEMOS ASIGNAR VALORES
' AL MOMENTO DE INSTANCIAR COMO SE VERÁ MÁS ADELANTE

End Class

 


Public Class Clientes
            Public Clientes As New Generic.List(Of Cliente)
End Class

 

3) Agreguemos ahora un manejador de eventos para el botón button1 dentro de la clase Window1 (que representa la ventana de WPF) y escribamos la invocación de dos funciones que programaremos posteriormente. Además declararemos de inicializaremos dos campos con los tipos de datos definidos en el paso anterior.

 

Class Window1

            Private UnCliente As Cliente
            Private ListaClientes As New Clientes


Private Sub Button1_Click(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Button1.Click
            AgregarClientes()
            SeleccionarClientes()
End Sub

End Class

 

 

4) La function AgregarClientes se encarga de agregar nuevos clientes a la lista genérica ListaClientes. Hay que notar la sintaxis en la cual automáticamente al momento de instanciar de la clase cliente que añadiremos a la lista, podemos utilizar la vieja palabra reservada With y corchetes para asignar los valores que tendrá la clase sin necesidad de escribir un constructor que se encargue de hacer esto.

 

 

Public Function AgregarClientes() As Boolean
 
ListaClientes.Clientes.Add(New Cliente With {.Id = 1, .Nombre = "Juanito", .Telefono = "12345"})
ListaClientes.Clientes.Add(
New Cliente With {.Id = 2, .Nombre = "Gilberto", .Telefono = "12345"})
ListaClientes.Clientes.Add(
New Cliente With {.Id = 3, .Nombre = "Susana", .Telefono = "12345"})
ListaClientes.Clientes.Add(
New Cliente With {.Id = 4, .Nombre = "Norberto", .Telefono = "12345"})
ListaClientes.Clientes.Add(
New Cliente With {.Id = 5, .Nombre = "Alberto", .Telefono = "12345"})
ListaClientes.Clientes.Add(
New Cliente With {.Id = 6, .Nombre = "Erika", .Telefono = "12345"})

MsgBox(ListaClientes.Clientes.Count)


End Function

 

5)  en la función seleccionarclientes haremos uso de LINQ para seleccionar aquellos clientes cuyo nombre termine en berto. El código es el siguiente.

 

 

Public Function SeleccionarClientes() As String
            Dim
Query = From SeleccionCliente In ListaClientes.Clientes _
            Where SeleccionCliente.Nombre Like "*berto" _
            Order By SeleccionCliente.Nombre _
            Select SeleccionCliente.Nombre, SeleccionCliente.Telefono
            Dim CadenaSalida As String = ""

            For Each SeleccionCliente In Query
                       With SeleccionCliente
                                   CadenaSalida += .Nombre &
" " & .Telefono & Chr(13)
                       End With
Next
            MsgBox(CadenaSalida)
 
 
            Return True
End
Function

 

Como podemos ver las variable Query y SeleccionCliente no tienen definido un tipo de datos, y por sorprendente que parezca no se está utilizando el tipo de datos Object ni se asigna mediante LateBinding. A estos tipos de datos en se les conoce como tipos anónimos y lo que has el compilador de visual basic es inferir a los tipos de datos dinámicamente de acuerdo al contexto en el cual se les encuentra.

Al momento de ejecutar este código deberíamos ver un msgbox con los clientes que cumplen con la condición del nombre que termina en Berto.

 

 

Conclusión

Esto es una pequeñísima parte de lo que estaremos viendo en la siguiente entrega de nuestro querido visual studio. Esperen próximos artículos para un ahondar un poco más sobre el asunto, mientras tanto les recomiendo que se vayan metiendo más al tema...

 

Si alguno de ustedes le interesa este o cualquier otro artículo de los que platicamos aquí en DevelopersDotNet los invito a que escriban en el foro o nos manden un correo para ahondar en sus inquietudes o para que ustedes tengan una participación más activa dentro de este sitio.

 

Tal es el caso de César Muñoz a quien le interesó bastante el artículo de ORM  y terminó algunas partes de la implementación que no estaban en el artículo. Posteriormente estaremos mostrando más detalles sobre el particular.

 

 

Sin más que decir reciban un abrazo y

¡Feliz codificación!

 

Su Compa:

Miguel Angel Morán

Microsoft MVP Visual Developer

 

Posted: 04-15-2007 3:46 PM por Bichi | con no comments |
Persistencia automática de datos sin SQL usando ORM

Introducción

¿Recuerdan aquel día en su vida en el cual decidieron estudiar en informática?

Yo la verdad aún me acuerdo y muy claramente mi objetivo era conocer a profundidad todo lo relacionado a estos maravillosos entes digitales llamados computadoras.

Quería conocer sobre compiladores, escuchaba términos raros como  algoritmos genéticos, redes neuronales  y quería saber el significado de los mismos y  ¿Por qué no? Hasta quería programar mi propio videojuego (Bueno… hoy ya es más o menos posible con XNA, pero eso… es otra historia, como diría la ruquita cajeta del comercial) jeje.

Sin embargo cuando uno llega al mercado laboral generalmente este tipo de aspiraciones, aunque permanecen enclavadas en la memoria, se convierten exclusivamente en recuerdo y añoranza, toda vez que en el campo de trabajo real pasamos la inmensa mayoría de nuestro tiempo haciendo programas de altas bajas y cambios, muy complejos o muy sencillos, grandes y pequeños, pero al fin de cuentas son altas bajas y cambios

Aunque esta realidad parezca un poco dramática, realmente podemos hacer muchas cosas para facilitarnos la vida porque el hacer sistemas de altas bajas y cambios también puede tener un enorme grado de reto y nos puede llenar de satisfacción de la misma manera que sea programáramos un compilador o si hiciéramos un videojuego.

En éste artículo les mostraré una manera muy entretenida y excitante de manipular nuestros accesos a base de datos mediante el uso de un concepto llamado “ORM” o lo que es lo mismo, Object Relational Mapping.

Escenario por todos conocido

Como ustedes saben, se nos dice que en la arquitectura de sistemas en . NET, debemos de promover la arquitectura en capas y cada una de esas capas deberá estar especializada en hacer algo exclusivo (patrón de responsabilidad)

El ejemplo más usado para esta separación es el famoso modelo de tres capas donde encontramos las siguientes

Capa de Usuario:  Contiene las clases boundary (que son la frontera entre el usuario y nuestra aplicación) En .NET, éstas clases pueden ser una Windows Form, una ventana de Windows Presentation Foundation, una página ASP.NET  etc. Esta capa se responsabiliza de recibir la información del usuario.

Regla de Negocio: Contiene clases controller que se encargan de orquestar los flujos de trabajo y reglas de negocio de nuestra aplicación; además, ésta capa también tiene las clases entity. Esta capa se responsabiliza de ordenar el flujo de nuestro sistema, realizar la regla de negocio y exponer a las entidades que nos permiten guardar los datos.

Acceso a base de datos: Contiene la implementación específica de nuestra base de datos. Esta capa tiene la responsabilidad de persistir las entidades dentro de la base de datos. Esta capa es la que debería contener las llamadas SQL a la base de datos, así como toda la lógica para conexiones, comandos y transacciones

 

Generalmente estas tres capas conviven de la siguiente manera


En este modelo, muchas veces hay una relación de 1:1 entre una entidad y una capa acceso a base de datos, o bien la misma entidad se puede responsabilizar de generar SQL. En el escenario más básico supongamos que tenemos una entidad Cliente que tiene tres métodos, uno que Inserta, otro que Actualiza y otro que Elimina, donde su declaración sería la siguiente

Public Class Cliente

    Public Id As Integer

    Public Nombre As String

    Public APaterno As String

    Public AMaterno As String

    Private CapaDatos As Abd

 

    Public Sub New()

        CapaDatos = New Abd

    End Sub

 

    Public Function Insertar() As Boolean

        CapaDatos.Insertar(Me)

 

    End Function

 

    Public Function Eliminar() As Boolean

        'Aqui va el código de implementación para eliminar

    End Function

 

    Public Function Actualizar() As Boolean

        'Aqui va el código de implementación para actualizar

 

    End Function

 

 

End Class

La capa de base de datos (Abd) correspondiente a la entidad antes mencionada debería ser, cosas más, cosas menos algo como esto:

Public Class Abd

    Public Function Insertar(ByVal pobjCliente As Cliente) As Boolean

        'Aqui va el código para declarar una SQLConnection, un SQLCommand etc.

 

        Dim lstrSQL = "INSERT INTO Cliente VALUES (" & pobjCliente.Nombre '... y asi sucesivamente....

 

        'Aqui ira un SQLCommand.ExecuteNonQuery o algo parecido, y un cerrado de la conexión

 

    End Function

End Class

Con sus variantes, muchos de nosotros utilizamos en esencia ésta técnica para persistir información, la cual es muy buena porque separamos la implementación del SQL de la entidad, promoviendo la escalabilidad de nuestra aplicación y haciéndola adaptable al cambio, sin embargo pues ésta técnica requiere estar codificando muchas entidades y capas de datos. Si nos ponemos a analizar un poco más resulta más que evidente que generalmente a una propiedad o campo de la entidad dentro de nuestro programa corresponde un campo de la base de datos, por lo que no hace falta pensar mucho para suponer que éste escenario se puede automatizar.

Al proceso de mapeo automatizado entre una entidad del paradigma orientado a objetos a una tabla de una base de datos relacional se le conoce como ORM o lo que es lo mismo Object Relational Mapping

Escenario ORM

El chiste del ORM es hacer que nuestro programa sea lo suficientemente inteligente para generar dinámicamente el SQL requerido para manipular las entidades persistidas en el manejador de base de datos y que cuando creemos una nueva entidad nosotros ya no tengamos que escribir manualmente el SQL, es decir hacer Entidades inteligentes que automáticamente generen su código SQL y que nos ahorremos esa fea chamba de escribir cueris. En otras palabras, entidades instantáneas… Suena chido ¿No? El concepto no es nuevo, ya tiene sus ayeres y ya existen en el mercado bastantes soluciones pero son caras y lerdas. Nosotros podemos implementar una funcionalidad bastante respetable utilizando las herramientas que el .NET Framework nos da: El poder de System.Reflection y el sistema de metadatos de .NET: Los atributos.

Lo que obtendremos es un código que generará automáticamente el SQL

A continuación implementaremos ORM de la manera más sencilla posible.

1) Lo primero que deberemos hacer es crear un par de atributos personalizados (clases que hereden de Attribute) que contengan como tal la información del mapeo de entidad a la tabla. El primero guardará a qué tabla vamos a mapear la entidad y el segundo mapeará cada uno de los campos de la entidad hacia la tabla, además aquí le podremos especificar si el campo es numérico o no para que se genere correctamente el SQL. El código a continuación…

'Atributo 1 para marcar a qué tabla queremos mapear la entidad

<AttributeUsage(AttributeTargets.Class)> _

Public Class BDTabla

    Inherits Attribute

    Public Tabla As String

 

'Constructor para que decoremos directamente las entidades   

 

    Public Sub New(ByVal BDTabla As String)

        Tabla = BDTabla

    End Sub

End Class

 

'Atributo 2 para marcar a cada uno de los campos o propiedades que conforman la entidad

'para mapearlos a los campos de las tablas en la BD

<AttributeUsage(AttributeTargets.Field Or AttributeTargets.Property)> _

Public Class BDCampo

    Inherits Attribute

    Public Campo As String

    Public EsNumerico As Boolean

    Public EsLlavePrimaria As Boolean = False

 

'Constructor para que decoremos directamente las entidades   

Public Sub New(ByVal pstrBDCampo As String, ByVal pbolEsNumerico As Boolean)

        Campo = pstrBDCampo

        EsNumerico = pbolEsNumerico

    End Sub

 

End Class

 

 

2) Posteriormente debemos implementar una clase abstracta que será la base de todas las entidades que tenga nuestro programa, y que como tal hará la chamba de descubrir dinámicamente el tipo de entidad y recorrer uno a uno, los atributos con los que está decorada la clase y la extracción de los valores de los campos de la entidad, y de esta forma ir generando dinámicamente el SQL. El ejemplo de la clase, con el método de Insertar ya implementado se presenta a  continuación:

 

'Clase base entidad

Public MustInherit Class Entidad

 

    Private Capadatos As New Abd

 

    Public Sub New()

    End Sub

 

    Public Function Insertar() As Boolean

 

        Dim lobjsBuilderNombresCampos As New StringBuilder("INSERT INTO ")

        Dim lobjsBuilderValoresCampos As New StringBuilder("")

 

        Dim lstrNombresCampos As String

        Dim lstrValoresCampos As String

 

 

        Dim lobjEntidad As Type = Me.GetType()

        Dim lobjAtributo As Attribute

 

        Dim latrBDTabla As BDTabla = _

        Attribute.GetCustomAttribute(lobjEntidad, GetType(Ent.BDTabla))

 

        Dim latrBDCampo As BDCampo

        Dim lobjInfoCampos() As FieldInfo

 

        lobjInfoCampos = lobjEntidad.GetFields( _

                      BindingFlags.Instance Or BindingFlags.Public)

 

        lobjsBuilderNombresCampos.Append(latrBDTabla.Tabla)

        lobjsBuilderNombresCampos.Append(" (")

 

        Dim i As Integer

 

        For i = 0 To lobjInfoCampos.Length - 1

 

            For Each lobjAtributo In Attribute.GetCustomAttributes(lobjInfoCampos(i))

                If TypeOf lobjAtributo Is BDCampo Then

                    latrBDCampo = CType(lobjAtributo, BDCampo)

 

                    lobjsBuilderNombresCampos.Append(latrBDCampo.Campo)

                    lobjsBuilderNombresCampos.Append(",")

                    lobjsBuilderValoresCampos.Append(IIf(latrBDCampo.EsNumerico = True, " ", "'"))

                    lobjsBuilderValoresCampos.Append(lobjEntidad.GetField(lobjInfoCampos(i).Name).GetValue(Me))

                    lobjsBuilderValoresCampos.Append(IIf(latrBDCampo.EsNumerico = True, " ", "'"))

                    lobjsBuilderValoresCampos.Append(",")

 

                End If

 

            Next

 

        Next

 

        lobjsBuilderNombresCampos.Remove(lobjsBuilderNombresCampos.Length - 1, 1)

        lobjsBuilderNombresCampos.Append(") VALUES (")

 

        lobjsBuilderValoresCampos.Insert(0, "(", 1)

        lobjsBuilderValoresCampos.Remove(lobjsBuilderValoresCampos.Length - 1, 1)

        lobjsBuilderValoresCampos.Append(")")

 

 

        lstrValoresCampos = lobjsBuilderValoresCampos.ToString()

        lstrNombresCampos = lobjsBuilderNombresCampos.ToString().Substring(0, lobjsBuilderNombresCampos.Length - 1)

 

        lobjAbd.EjecutarComando(lstrNombresCampos + lstrValoresCampos)

  

        Return True

 

    End Function

 

    Public Function Eliminar() As Boolean

Return True

 

'Aquí debe ir el código ORM que elimina

    End Function

 

 

 

    Public Function Actualizar() As Boolean

Return True

 

'Aquí debe ir el código ORM que actualiza

 

    End Function

 

 

End Class

3) Como podemos comprobar el código anterior genera dinámicamente el SQL requerido para insertar en una tabla la entidad.  En esta clase podemos ver la declaración una variable llamada CapaDatos del tipo Abd, cuyo trabajo es conectarse a la base de datos. Suponiendo que en la aplicación existe un archivo de configuración con el connection string correspondiente a donde se encuentra la base de datos con las tablas que persistirán las entidades, esta clase Abd deberá parecerse a la siguiente:

 

Public Class Abd

 

    Private lobjConexion As New SqlClient.SqlConnection

    Private lobjComando As New SqlClient.SqlCommand

    Private lbolConexionInicializada As Boolean = False

 

    Public Function IniciarConexion() As Boolean

        Try

            If Not lbolConexionInicializada Then

                Dim connections As ConnectionStringSettingsCollection = _

                ConfigurationManager.ConnectionStrings

                lobjConexion.ConnectionString = connections(1).ToString()

                lbolConexionInicializada = True

 

            End If

 

        Catch ex As Exception

            MsgBox("Ocurrió el siguiente error al conectar con la base de datos " & ex.InnerException.ToString())

 

        End Try

        Return True

 

    End Function

 

    Public Function EjecutarComando(ByVal lstrSQL As String) As Boolean

        Try

            IniciarConexion()

            lobjConexion.Open()

            lobjComando.Connection = lobjConexion

            lobjComando.CommandText = lstrSQL

            lobjComando.ExecuteNonQuery()

            lobjConexion.Close()

        Catch ex As Exception

            MsgBox("Ocurrió el siguiente error al ejecutar el comando en la base de datos " & ex.InnerException.ToString())

 

 

        End Try

 

        Return True

 

    End Function

 

End Class

 

4) Y Voilà… Eso es todo lo que debemos hacer para implementar ORM, ahora todas las clases que hereden de la clase entidad que definimos en el fragmento de código anterior, serán autopersistentes por default. Nuestra entidad ya una vez implementada se verá del siguiente modo:

 

<BDTabla("TablaCliente")> _

Public Class Cliente

    Inherits Entidad

    <BDCampo("Id", True)> Public IdCliente As Integer

    <BDCampo("APaterno", False)> Public Nombre As String

    <BDCampo("AMaterno", False)> Public sexo As String

    <BDCampo("Nombre", False)> Public edad As String

 

End Class

Al asignar los valores en los campos correspondientes  e invocar el método Insertar() de nuestra clase Cliente, se insertará automáticamente en la base de datos, en el ejemplo anterior se insertaría en la tabla TablaCliente, y ya cualquier entidad que hagamos y que siga estas reglas estará lista para insertarse. ¿No es maravilloso?

Pros y contras

Como podrán ver esto es una maravilla, en el mejor de los casos nos elimina la necesidad de escribir SQL y además se fomenta el estilo de programación en objetos.

Seguramente se preguntarán, si parece tan bonito porque no existe algo ya hecho listo para usarse, bueno, pues como todo en esta vida, ésta tecnología también tiene su darkside...

Una de las desventajas de este modelo de programación es que de alguna manera estamos reduciendo algo de performance en nuestra aplicación, toda vez que estamos utilizando reflexión para descubrir dinámicamente la información que viene contenida dentro de nuestra entidad, por lo que hay que poner sobre la balanza las cosas: Aunque estamos ganando productividad en el desarrollo estamos sacrificando un poco el desempeño de nuestra aplicación.

Nosotros como arquitectos de software debemos de elegir que esto que estamos buscando y seleccionar la mejor opción.

Tendencias

Existen muchas tendencias y tecnologías que implementan métodos similares a los presentados en este artículo. Microsoft intentó hacer algo parecido a lo visto en este capítulo llamado “Object Spaces”, que por razones no muy claras desapareció, ahora Microsoft decidió apostar a su nueva tecnología llamada LINQ incluida en la versión 3.5 del .NET Framework donde existirán versiones actualizadas de los lenguajes Visual Basic y C# (versiones 9.0 y 3.0 respectivamente) que añaden soporte al concepto LINQ, que no es más que la inclusión de la sintaxis de SQL dentro del mismo lenguaje de programación de propósito general para manipular entidades y objetos de datos con sintaxis de cueri. (Próximamente un artículo de LINQ para que vean esta nueva tecnología, alterna a lo que expusimos en éste post)

Conclusiones

 

Al final de cuentas, la idea de todo esto es promover la programación en objetos y  aumentar la productividad de los programadores y del equipo de desarrollo en General.

ORM es una técnica disponible que nos permite automatizar el proceso de generación de tipos de datos especializados en persistir datos llamados entidades. Como sucede con cualquier otro tecnología ORM no es la solución a todos los problemas existentes hay que analizar si verdaderamente esa tecnología puede ayudarnos y verificar si los beneficios son mayores a los problemas que nos pueda llegar a acarrear.

Los invito muy cordialmente a que implementen de los métodos actualizar y eliminar que como se pueden dar cuenta en el código no están implementados porque con el método insertar tienen la base para programar los demás métodos, de esta manera ustedes pueden proponer mejoras o tropicalizar el proyecto para que cumpla con las necesidades de su empresa o negocio.

Espero que estas líneas hayan sido de su agrado. No se pierdan porque como pueden ver DevelopersDotNet está creciendo como nunca antes. Me dará muchísimo gusto que alguien comente sobre este artículo en los foros correspondientes. Un saludo y abrazo a tod@s.

Sin más que decir

¡Feliz codificación!