Programacion en Capas

20
1. PROGRAMACION EN CAPAS. La programación por capas es un estilo de programación en el que el objetivo primordial es la separación de la lógica de negocios de la lógica de diseño; un ejemplo básico de esto consisten separar la capa de datos de la capa de presentación al usuario Puede haber tantas capas como creas necesarias en tu proyecto, aunque para mi, lo ideal es que en un proyecto solo haya 3 capas: Acceso a datos, Negocio y Presentación. 1. Capa de Datos. Esta capa es la que accede directamente a la base de datos. 2. Capa de Negocio. Esta capa es la que sostiene todo el negocio de la aplicación, es decir, todos los cálculos necesarios para que nuestra aplicación haga lo que se espera de ella. 3. Capa de Presentación Esta capa comprende todo lo que se muestra hacia el usuario final, es decir, el diseño de los formularios o plantillas con las que va a trabajar el usuario final. Es importante separar bien estas capas, ya que por ejemplo el Negocio no podría tener acceso directamente sin pasar primero por la capa Acceso a Datos, al igual que la capa presentación no puede hacer ningún tipo de cálculo importante de la aplicación o acceder directamente a Base de Datos. 1.1. Creando una Solucion Una vez que hemos entendido como funciona la programación en capas, vamos a llevarlo a cabo. Abrimos nuestro Visual Studio 2008 y creamos una solución. Para ello: Archivo->Nuevo Proyecto En Tipos de Proyecto seleccionamos "Soluciones de Visual Studio", ponemos un nombre a la solución y elegimos una ubicación donde queremos guardar la solución.

description

Programación

Transcript of Programacion en Capas

1. PROGRAMACION EN CAPAS.La programacin por capas es un estilo de programacin en el que el objetivo primordial es la separacin de la lgica de negocios de la lgica de diseo; un ejemplo bsico de estoconsistenseparar la capa de datos de la capa de presentacin al usuarioPuede haber tantas capas como creas necesarias en tu proyecto, aunque para mi, lo ideal es que en un proyecto solo haya 3 capas: Acceso a datos, Negocio yPresentacin.1. Capa de Datos. Esta capa es la que accede directamente a la base de datos.2. Capa de Negocio. Esta capa es la que sostiene todo el negocio de laaplicacin, es decir, todos losclculosnecesarios para que nuestraaplicacinhaga lo que se espera de ella.3. Capa dePresentacin Esta capa comprende todo lo que se muestra hacia el usuario final, es decir, el diseo de los formularios o plantillas con las que va a trabajar el usuario final.Es importante separar bien estas capas, ya que por ejemplo el Negocio nopodratener acceso directamente sin pasar primero por la capa Acceso a Datos, al igual que la capapresentacinno puede hacerningntipo de clculo importante de laaplicacino acceder directamente a Base de Datos.

1.1. Creando una SolucionUna vez que hemos entendido como funciona laprogramacinen capas, vamos a llevarlo a cabo.Abrimos nuestro Visual Studio 2008 y creamos unasolucin. Para ello:Archivo->Nuevo Proyecto

En Tipos de Proyecto seleccionamos "Soluciones de Visual Studio", ponemos un nombre a lasoluciny elegimos unaubicacindonde queremos guardar lasolucin.Ahora en el explorador de soluciones pinchamos con elbotnderecho sobre lasoluciny aadimos un nuevo proyecto.

En tipos de proyecto elegimos un proyecto de tipo Visual Basic - Windows - Biblioteca de clases y le ponemos el nombre AccesoDatos. Este proyectocorrespondera la Capa de Datos que hemos explicado anteriormente.Nos ospreocupissi solo os aparece en el explorador de proyectos el proyecto AccesoDatos, esto es normal. Vamos aadir ahora un segundo proyecto del mismo tipo que el anterior llamado Negocio, para ello nos vamos alMen"Archivo-Agregar-Nuevo Proyecto".Si todo ha ido bien, el explorador de soluciones os debe de quedar de la siguiente manera:

Comopodisver ha vuelto a aparecer "SolucionCapas" englobando a los dos proyectos. Este segundo proyecto es el que englobara toda lalgicadel negocio de nuestraaplicacin.Por ultimo vamos a crear un tercer proyecto que secorrespondercon la capa depresentacin Para ello, realizamos los mismos pasos anteriores para aadir un proyecto nuevo a lasolucin.

En este caso elegimos un tipo de proyecto VisualStudio - Windows - Aplicacion de Windows Form y le damos el nombre "Presentacion".

Si todo ha ido bien, el explorador de soluciones debe quedar de la misma forma que la imagen anterior.Aqu podemos ver como exactamente como queda separadas cada capa.

1.2. Referencias y dependencias entre proyectosUna vez que tenemos claro la estructura de nuestra solucion debemos crear las dependencias de cada proyecto y ver cul es nuestro proyecto de inicio.Para ello debemos entender que el proyecto de presentacion "depende" directamente del proyecto de negocio y este a su vez depende del proyecto de Acceso a Datos. Para decirle esto a Visual Studio pinchamos con el boton derecho sobre el proyecto de presentacion y en el menu resultante pinchamos sobre "Dependencias del proyecto", la ventana resultante

Como podemos ver tenemos que marcar solamente el proyecto "Negocio" de nuestrasolucin Acceso a Datos no lo marcamos pues el flujo de datos debe de pasar antes por el proyecto Negocio. Esto nos ayudara luego a importar los proyectos entre ellos.Hacemos la mismaoperacincon el proyecto Negocio aadiendo la dependencia del proyecto "AccesoDatos".As mismo hay que aadir directamente las referencias de cada proyecto.Si nos vamos al "My Project" del proyecto Presentacion y seleccionamos la pestaa Referencias se nos mostrara una ventana con todas las referencias asociadas al proyecto, como podeis ver, aunque hemos asignado la dependencia del proyecto Negocio no tenemos asignada la referencia.

Para ello pulsamos sobre elbotnAgregar y seleccionamos en la ventana emergente la pestaa "Proyectos". Seleccionamos la referencia del proyecto Negocio y pulsamos Aceptar. La referencia se ha aadido.Hacemos la mismaoperacincon el MY PROJECT de Negocio y le aadimos la referencia del proyecto AccesoDatos.De esta forma ya tendremos aadidas las referencias y dependencias entre proyectos de la solucion.

Nota:Mas adelante os enseare otra forma de meter referencias entre proyectos. Veremos que podemos crear una dll de un proyecto de una solucion en otra solucion como referencia.

2. Proyecto AccesoDatosVamos a empezar primero con el proyecto de Acceso a Datos, puesto que es el proyecto del que dependen los dems proyectos y sobre el cual va a caer la responsabilidad de conectar y comunicarse directamente con la Base de Datos de nuestra aplicacin.

Si nuestra aplicacin no comunicara con una base de datos este proyecto no tendra ningn sentido.La idea de este proyecto es que sea capaz de conectar con cualquier tipo de base de datos, independientemente de la cadena de conexin o a travs de un ODBC, por qu? la respuesta es sencilla, este proyecto debe ser comn para cualquier tipo de aplicacin que creemos en el futuro.

Para ello crearemos dos clases en nuestro proyecto:

BaseDatos. Donde recaera todo el peso del proyecto. BaseDatosException. Encargada de transmitir mensajes de errores a los dems proyectos.En los siguientes captulos explicaremos que propiedades tendrn cada una de estas clases.

2.1. Clase BaseDatos.ConstructoresEn primer lugar vamos a crear la clase BaseDatos, que es quien va ha llevar todo el peso de las comunicaciones con la base de datos a la que conectaremos. Creamos una clase llamada BaseDatos y escribimos el siguiente cdigo:?123456789101112131415161718Option Explicit OnImports System.Data.CommonPublic Class BaseDatosPublic Enum BBDDSQL = 1ODBC = 2OLEDB = 3End EnumPrivate Conexion As IDbConnection = NothingPrivate Commando As IDbCommand = NothingPrivate Transaccion As IDbTransaction = NothingPrivate sCadenaConexion As StringPrivate _Factory As DbProviderFactory = NothingPrivate tipoBBDD As BBDDPrivate pParametros() As IDbDataParameterEnd Class

Notas: Option Explicit ONhay que meterlo al principio de cualquier clase que creemos. Esto es para que no nos permita crear variables sin definir el tipo, pues puede crear errores de compilacion. El tipo Enumerado nos servira para identificar el tipo de conexion a la Base de Datos.El segundo paso es crear los distintosconstructoresde la clase:1. Constructor parametrizado, donde le pasamos el tipo de conexion (SQL,ODCB,OLEDB), el nombre de la base de datos, el usuario y la contrasea

?23456789101112131415161718192021222324Public Sub New(ByVal tipoConexion As BaseDatos.BBDD, _ByVal sBaseDatos As String, _ByVal sUsuario As String, _ByVal sPass As String)TryDim proveedor As String = ""InicializarVariables()Me.tipoBBDD = tipoConexionSelect Case Me.tipoBBDDCase BBDD.SQL : proveedor = "System.Data.SqlClient"Case BBDD.ODBC : proveedor = "System.Data.Odbc"Case BBDD.OLEDB : proveedor = "System.Data.OleDb"End SelectMe.sCadenaConexion = "DSN=" & sBaseDatos & ";UID=" & sUsuario & ";PWD=" & sPassMe._Factory = DbProviderFactories.GetFactory(proveedor)pParametros = NothingCatch ex As ExceptionThrow New BaseDatosException("ERROR :" & ex.Message & " BASEDATOS.New(Parametros) ", ex)End TryEnd Sub

2. Constructor con parametros establecidos en el app.config del programa, el pasamos la key del proveedor y la key de la Base de Datos.?12345678910111213141516171819Public Sub New(ByVal ProveedorBBDD As String, ByVal sKeyConfig As String)TryDim proveedor As String = ConfigurationManager.AppSettings.Get(ProveedorBBDD)Select Case Trim(proveedor)Case "System.Data.SqlClient" : tipoBBDD = BBDD.SQLCase "System.Data.Odbc" : tipoBBDD = BBDD.ODBCCase "System.Data.OleDb" : tipoBBDD = BBDD.OLEDBEnd SelectMe.sCadenaConexion = ConfigurationManager.AppSettings.Get(sKeyConfig)Me._Factory = DbProviderFactories.GetFactory(proveedor)pParametros = NothingCatch ex As ExceptionThrow New BaseDatosException("ERROR :" & ex.Message & " BASEDATOS.New(sKeyConfig) ", ex)End TryEnd Sub

NOTA: el app.config es un fichero de configuracion que contiene parametros totalmente configurables y que se pueden utilizar en toda la solucion. Es como un equivalente a las constantes por asi decirlo. En este caso, el app.config tendria configurado el parametro Proveedor y la key de la base de datos es donde se identifica la cadena de conexion. Para acceder al app.config llamaremos a la funcion "ConfigurationManager", y para poder utilizarla debemos aadir la referencia "System.Configuration" en las referencias del proyecto.

3. Constructor con parametros, le pasamos el tipo de conexion y la cadena de conexion.?2345678910111213141516171819Public Sub New(ByVal tipoConexion As BaseDatos.BBDD, _ByVal sCadenaConexion As String)TryDim proveedor As String = ""tipoBBDD = tipoConexionSelect Case tipoBBDDCase BBDD.SQL : proveedor = "System.Data.SqlClient"Case BBDD.ODBC : proveedor = "System.Data.Odbc"Case BBDD.OLEDB : proveedor = "System.Data.OleDb"End SelectMe.sCadenaConexion = sCadenaConexionMe._Factory = DbProviderFactories.GetFactory(proveedor)pParametros = NothingCatch ex As ConfigurationErrorsExceptionThrow New BaseDatosException("ERROR :" & ex.Message & " BASEDATOS.New(tipoConexion,CadenaConexion) ", ex)End TryEnd Sub

2.2.Clase Base Datos. Conexion y DesconexionUna vez que hemos construidos los constructores de nuestra clase, necesitamos dos funciones o mtodos que puedan crear una conexin con la base de datos, en funcin de los parmetros pasados en nuestros constructores.Esta es la funcin encargada de conectar:?23456789101112131415161718192021222324252627282930Public Sub Conectar()TryIf Not Me.Conexion Is Nothing ThenIf Me.Conexion.State.Equals(ConnectionState.Closed) ThenThrow New BaseDatosException("La conexion ya se encuentra abierta")Exit SubEnd IfEnd IfIf Me.Conexion Is Nothing ThenSelect Case tipoBBDDCase BBDD.SQL : Me.Conexion = New SqlConnectionCase BBDD.ODBC : Me.Conexion = New OdbcConnectionCase BBDD.OLEDB : Me.Conexion = New OleDbConnectionEnd SelectMe.Conexion = _Factory.CreateConnection()Me.Conexion.ConnectionString = Me.sCadenaConexionEnd IfMe.Conexion.Open()If Me.Conexion.State ConnectionState.Open ThenMsgBox("ERROR AL CONECTAR CON LA BASE DE DATOS " & Me.Conexion.Database)End IfCatch ex As ExceptionThrow New BaseDatosException("ERROR :" & ex.Message & " - Cadena conexion : " & Me.sCadenaConexion & " BASEDATOS.Conectar ", ex)End TryEnd Sub

En esta funcin se ve claramente el flujo de los datos, primero preguntamos si la conexin esta ya abierta, si no es asi y es una nueva conexin entonces creamos la conexin en funcin del proveedor y cadena de conexin del constructor elegido.

Una vez que hayamos terminado con las operaciones contra la base de datos, debemos de utilizar una funcin que nos desconecte de la sesin, porque si no esta conexin puede penalizar con el tiempo el rendimiento de la Base de Datos.

?123456789101112131415Public Sub Desconectar()TryIf Me.Conexion.State.Equals(ConnectionState.Open) ThenMe.Conexion.Close()Me.Conexion = NothingEnd IfCatch ex As DataExceptionMe.Conexion = NothingThrow New BaseDatosException("ERROR :" & ex.Message & " BASEDATOS.DESCONECTAR ", ex)Catch ex As InvalidOperationExceptionMe.Conexion = NothingThrow New BaseDatosException("ERROR :" & ex.Message & " BASEDATOS.DESCONECTAR ", ex)End TryEnd Sub

El funcionamiento es sencillo, preguntamos si la conexion esta abierta, la cerramos y controlamos los errores.

Nota: El control de errores los veremos en siguientescaptulos.

2.3.Clase Base Datos. Transacciones9:50| |0 comentariosComo sabeis en base de datos las transacciones tiene muy buen uso, pues te permite hacer todo tipo de pruebas a las base de datos y poder "retroceder" si algo ha salido mal. Hay 3 tipos de transacciones:1. BeginTrans. Es cuando empieza la transaccion. Todo lo que este despues de aqui se ejecutara en modo de prueba.2. Commit. Si todo lo que hemos programado ha salido correcto y no ha habido errores debemos de lanzar este comando a la Base de Datos, que hara que los cambios tengan efecto.3. RollBack. Si se produce un error durante la ejecucion debemos de lanzar este comando a la Base de Datos, de tal forma que todos los cambios producidos en base de datos desde el BeginTrans no tengan efecto.En la clase Base de Datos que estamos creando lo haremos de esta manera:

?1234567891011121314151617Public Sub ComenzarTransaccion()If Me.Transaccion Is Nothing ThenMe.Transaccion = Me.Conexion.BeginTransaction()End IfEnd SubPublic Sub CancelarTransaccion()If Not Me.Transaccion Is Nothing ThenMe.Transaccion.Rollback()End IfEnd SubPublic Sub ConfirmarTransaccion()If Not Me.Transaccion Is Nothing ThenMe.Transaccion.Commit()End IfEnd Sub

2.4. Clase BaseDatos. Consultas.23:59| |0 comentariosAhora vamos a ver como podemos hacer consultas a la base de datos (inserciones, modificaciones, eliminaciones o consultas para traernos datos).

Primero vamos a ver como ejecutar consultas para inserciones, modificaciones o eliminaciones:?12345678910Public Function EjecutarConsulta(ByVal CadenaSql As String) As BooleanTryMe.CrearComando(CadenaSql, "S")Me.EjecutarComando()EjecutarConsulta = TrueCatch ex As ExceptionEjecutarConsulta = FalseThrow New BaseDatosException("ERROR :" & ex.Message & " BASEDATOS.EjecutarConsulta ", ex)End TryEnd Function

Esta funcion crea un comando que ejecutara la consulta en la Base de Datos.Para utilizar esta funcion necesitamos dos funciones mas :?1234567891011121314151617181920212223242526272829303132333435Private Sub CrearComando(ByVal CadenaSql As String, _ByVal TipoConsulta As String)TrySelect Case tipoBBDDCase BBDD.SQL : Me.Commando = New SqlCommandCase BBDD.ODBC : Me.Commando = New OdbcCommandCase BBDD.OLEDB : Me.Commando = New OleDbCommandEnd SelectMe.Commando = _Factory.CreateCommand()Me.Commando.Connection = Me.ConexionMe.Commando.CommandTimeout = 99999999Select Case TipoConsultaCase "P" 'Procedimiento almacenadoMe.Commando.CommandType = CommandType.StoredProcedureCase "T"Me.Commando.CommandType = CommandType.TableDirectCase Else 'Sentencia SQLMe.Commando.CommandType = CommandType.TextEnd SelectMe.Commando.CommandText = CadenaSqlIf Not Me.Transaccion Is Nothing ThenMe.Commando.Transaction = Me.TransaccionEnd IfCatch ex As ExceptionThrow New BaseDatosException("ERROR :" & ex.Message & " BASEDATOS.CrearComando ", ex)End TryEnd Sub

?12345678Private Sub EjecutarComando()TryMe.Commando.ExecuteNonQuery()Catch ex As ExceptionThrow New BaseDatosException("ERROR :" & ex.Message & " BASEDATOS.EjecutarComando ", ex)End TryEnd Sub

Si lo que queremos es hacer consultas para recuperar datos de la base de datos y tratarlos luego en nuestro programa tenemos varias opciones, podemos traernos en un DATAREADER, DATATABLE o en un DATASET. A mi me gusta mas recuperarlo en un DATATABLE pues a mi parecer es mas fcil tratar despues los datos.

Para poder utilizar las siguientes funciones debemos primero crear esta funcion, que dependiendo del tipo de Base de Datos que tengamos ejecutara la consulta de una manera o de otra.?1234567891011121314Private Function EjecutarConsultaDataAdapter() As IDataAdapterTrySelect Case tipoBBDDCase BBDD.SQL : EjecutarConsultaDataAdapter = New SqlDataAdapter(Me.Commando)Case BBDD.ODBC : EjecutarConsultaDataAdapter = New OdbcDataAdapter(Me.Commando)Case BBDD.OLEDB : EjecutarConsultaDataAdapter = New OleDbDataAdapter(Me.Commando)Case Else : Return NothingEnd SelectCatch ex As ExceptionReturn NothingThrow New BaseDatosException("ERROR :" & ex.Message & " BASEDATOS.EjecutarConsultaDataAdapter ", ex)End TryEnd Function

La siguiente funcion ejecuta una consulta (CadenaSQL) y devuelve el resultado en un DATATABLE (Tabla) que luego podemos tratar en la capa de NEGOCIO. TipoConsulta nos dice si se trata de una consulta o de un procedimiento Almacenado y con "HayParametros" le decimos si le pasamos parametros (solo en el caso de que estemos tratando con un procedimiento almacenado.?123456789101112131415161718192021222324252627282930313233343536373839404142Public Function Dame_Datos_DT(ByVal CadenaSQL As String, _ByVal HayParametros As Boolean, _ByRef Tabla As DataTable, _ByVal TipoConsulta As String) As BooleanDim arsDatos As IDataAdapterDim datos As New DataSetDim i As Integer = 0TrySelect Case tipoBBDDCase BBDD.SQL : arsDatos = New SqlDataAdapterCase BBDD.ODBC : arsDatos = New OdbcDataAdapterCase BBDD.OLEDB : arsDatos = New OleDbDataAdapterEnd SelectCrearComando(CadenaSQL, TipoConsulta)If HayParametros ThenWhile i 0 ThenDame_Datos_DT = TrueElseDame_Datos_DT = FalseEnd IfCatch ex As ExceptionDame_Datos_DT = FalseThrow New BaseDatosException("ERROR :" & ex.Message & " BASEDATOS.DameDatosDT ", ex)End TryEnd Function

La siguiente funcion Ejecuta una consulta (CadenaSQL) y devuelve los datos en un DATAADAPTER que luego podremos utilizar en la capa NEGOCIO.?12345678910111213141516171819202122Public Function Dame_Datos_DA(ByVal CadenaSQL As String, _ByVal HayParametros As Boolean, _ByVal TipoConsulta As String) As IDataAdapterTryDim i As Integer = 0CrearComando(CadenaSQL, TipoConsulta)If HayParametros ThenWhile i