Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
0:21 | | 8 comentarios
Resumiendo .... 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 Presentacin.
2. Capa de Negocio. Esta capa es la que sostiene todo el negocio de la aplicacin, es decir,
todos los clculos necesarios para que nuestra aplicacin haga lo que se espera de ella.
3. Capa de Presentacin 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.
Una vez que hemos entendido como funciona la programacin en capas, vamos a llevarlo a cabo.
Abrimos nuestro Visual Studio 2008 y creamos una solucin. Para ello:
Archivo->Nuevo Proyecto
En Tipos de Proyecto seleccionamos "Soluciones de Visual Studio", ponemos un nombre a
la solucin y elegimos una ubicacin donde queremos guardar la solucin.
Por ultimo vamos a crear un tercer proyecto que se corresponder con la capa de presentacin
Para ello, realizamos los mismos pasos anteriores para aadir un proyecto nuevo a la solucin.
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 imagenanterior.
Una vez que tenemos claro la estructura de nuestra solucion debemos crear las dependencias de
cada proyecto y ver cual 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
nuestra solucin 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 misma operacin con 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 el botn Agregar 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 misma operacin con 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 AccesoDatos
23:53 | | 0 comentarios
Vamos 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 que? la respuesta es
sencilla, este proyecto debe ser comn para cualquier tipo de aplicacin que creemos en
el futuro.
En los siguientes captulos explicaremos que propiedades tendrn cada una de estas clases.
En 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:
?
1 Option Explicit On
2
Imports System.Data.Common
3
4
5
6 Public Class BaseDatos
7
8 Public Enum BBDD
9 SQL = 1
ODBC = 2
10 OLEDB = 3
11 End Enum
12
13 Private Conexion As IDbConnection = Nothing
14 Private Commando As IDbCommand = Nothing
Private Transaccion As IDbTransaction = Nothing
15 Private sCadenaConexion As String
16 Private _Factory As DbProviderFactory = Nothing
17 Private tipoBBDD As BBDD
18 Private pParametros() As IDbDataParameter
19
20 End Class
21
Notas:
Option Explicit ON hay 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.
?
1 Public Sub New(ByVal tipoConexion As BaseDatos.BBDD, _
ByVal sBaseDatos As String, _
2 ByVal sUsuario As String, _
3 ByVal sPass As String)
4 Try
5
6 Dim proveedor As String = ""
7 InicializarVariables()
8
Me.tipoBBDD = tipoConexion
9 Select Case Me.tipoBBDD
10 Case BBDD.SQL : proveedor = "System.Data.SqlClient"
11 Case BBDD.ODBC : proveedor = "System.Data.Odbc"
12 Case BBDD.OLEDB : proveedor = "System.Data.OleDb"
13 End Select
14
15
Me.sCadenaConexion = "DSN=" & sBaseDatos & ";UID=" & sUsuario & ";PWD=" &
16 sPass
17 Me._Factory = DbProviderFactories.GetFactory(proveedor)
18 pParametros = Nothing
19
20 Catch ex As Exception
21 Throw New BaseDatosException("ERROR :" & ex.Message & "
BASEDATOS.New(Parametros) ", ex)
22 End Try
23 End Sub
24
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.
?
1 Public Sub New(ByVal ProveedorBBDD As String, ByVal sKeyConfig As String)
2
3 Try
4
5 Dim proveedor As String =
6 ConfigurationManager.AppSettings.Get(ProveedorBBDD)
7
Select Case Trim(proveedor)
8 Case "System.Data.SqlClient" : tipoBBDD = BBDD.SQL
9 Case "System.Data.Odbc" : tipoBBDD = BBDD.ODBC
10 Case "System.Data.OleDb" : tipoBBDD = BBDD.OLEDB
11 End Select
12
13 Me.sCadenaConexion = ConfigurationManager.AppSettings.Get(sKeyConfig)
Me._Factory = DbProviderFactories.GetFactory(proveedor)
14 pParametros = Nothing
15
16 Catch ex As Exception
17 Throw New BaseDatosException("ERROR :" & ex.Message & "
18 BASEDATOS.New(sKeyConfig) ", ex)
End Try
19
End Sub
20
?
1
2 Public Sub New(ByVal tipoConexion As BaseDatos.BBDD, _
3 ByVal sCadenaConexion As String)
Try
4 Dim proveedor As String = ""
5
6 tipoBBDD = tipoConexion
7 Select Case tipoBBDD
8 Case BBDD.SQL : proveedor = "System.Data.SqlClient"
9 Case BBDD.ODBC : proveedor = "System.Data.Odbc"
Case BBDD.OLEDB : proveedor = "System.Data.OleDb"
10 End Select
11
12 Me.sCadenaConexion = sCadenaConexion
13 Me._Factory = DbProviderFactories.GetFactory(proveedor)
14 pParametros = Nothing
Catch ex As ConfigurationErrorsException
15 Throw New BaseDatosException("ERROR :" & ex.Message & "
16 BASEDATOS.New(tipoConexion,CadenaConexion) ", ex)
17 End Try
18 End Sub
19
Una 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:
?
1 Public Sub Conectar()
2 Try
3
If Not Me.Conexion Is Nothing Then
4
If Me.Conexion.State.Equals(ConnectionState.Closed) Then
5
Throw New BaseDatosException("La conexion ya se encuentra abierta
6 Exit Sub
7 End If
8 End If
9
10 If Me.Conexion Is Nothing Then
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.
?
1 Public Sub Desconectar()
2
3 Try
If Me.Conexion.State.Equals(ConnectionState.Open) Then
4
Me.Conexion.Close()
5
Me.Conexion = Nothing
6
End If
7
Catch ex As DataException
8
Me.Conexion = Nothing
9
Throw New BaseDatosException("ERROR :" & ex.Message & "
10 BASEDATOS.DESCONECTAR ", ex)
11 Catch ex As InvalidOperationException
Me.Conexion = Nothing
12
Throw New BaseDatosException("ERROR :" & ex.Message & "
13 BASEDATOS.DESCONECTAR ", ex)
14 End Try
15 End Sub
Como 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
2 Public Sub ComenzarTransaccion()
3 If Me.Transaccion Is Nothing Then
4 Me.Transaccion = Me.Conexion.BeginTransaction()
End If
5 End Sub
6
7 Public Sub CancelarTransaccion()
8 If Not Me.Transaccion Is Nothing Then
9 Me.Transaccion.Rollback()
10 End If
End Sub
11
12 Public Sub ConfirmarTransaccion()
13 If Not Me.Transaccion Is Nothing Then
14 Me.Transaccion.Commit()
15 End If
End Sub
16
17
Ahora 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:
?
1 Public Function EjecutarConsulta(ByVal CadenaSql As String) As Boolean
2 Try
3 Me.CrearComando(CadenaSql, "S")
Me.EjecutarComando()
4
5 EjecutarConsulta = True
Catch ex As Exception
6
EjecutarConsulta = False
7
Throw New BaseDatosException("ERROR :" & ex.Message & "
8 BASEDATOS.EjecutarConsulta ", ex)
9 End Try
10 End Function
?
1 Private Sub CrearComando(ByVal CadenaSql As String, _
3
4 Try
18 Me.Commando.CommandType = CommandType.TableDirect
19
20 Case Else 'Sentencia SQL
21
Me.Commando.CommandType = CommandType.Text
22
End Select
23
24
Me.Commando.CommandText = CadenaSql
25
26
If Not Me.Transaccion Is Nothing Then
27 Me.Commando.Transaction = Me.Transaccion
28 End If
29
30 Catch ex As Exception
2 Try
Me.Commando.ExecuteNonQuery()
3
Catch ex As Exception
4
Throw New BaseDatosException("ERROR :" & ex.Message & "
5 BASEDATOS.EjecutarComando ", ex)
6 End Try
7
8 End 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.
?
Private Function EjecutarConsultaDataAdapter() As IDataAdapter
1
Try
2
Select Case tipoBBDD
3
Case BBDD.SQL : EjecutarConsultaDataAdapter = New SqlDataAdapter(Me.C
4
Case BBDD.ODBC : EjecutarConsultaDataAdapter = New OdbcDataAdapter(Me
5
Case BBDD.OLEDB : EjecutarConsultaDataAdapter = New
6 OleDbDataAdapter(Me.Commando)
8 End Select
9 Catch ex As Exception
10 Return Nothing
?
1 Public Function Dame_Datos_DT(ByVal CadenaSQL As String, _
10
11 Select Case tipoBBDD
27 arsDatos.Fill(datos)
28 Tabla = datos.Tables(0)
29
30 If Tabla.Rows.Count > 0 Then
Dame_Datos_DT = True
31
Else
32
Dame_Datos_DT = False
33
End If
34
35
Catch ex As Exception
36
Dame_Datos_DT = False
37
Throw New BaseDatosException("ERROR :" & ex.Message & "
38
39 BASEDATOS.DameDatosDT ", ex)
40 End Try
41 End Function
42
?
1 Public Function Dame_Datos_DA(ByVal CadenaSQL As String, _
Try
4
Dim i As Integer = 0
5
6
CrearComando(CadenaSQL, TipoConsulta)
7
8
If HayParametros Then
9
While i <= UBound(pParametros)
10
Me.Commando.Parameters.Add(pParametros(i))
11
i = i + 1
12
End While
13 End If
14
15 Return Me.EjecutarConsultaDataAdapter()
16
17 Catch ex As Exception
18 Dame_Datos_DA = Nothing
La siguiente funcion ejecuta una consulta (CadenaSQL) y devuelve los datos en un DATAREADER
que luego podremos utilizar en la capa de NEGOCIO.
5 Dim i As Integer = 0
6 CrearComando(CadenaSQL, TipoConsulta)
7 If HayParametros Then
Me.Commando.Parameters.Add(pParametros(i))
9
i = i + 1
10
End While
11
End If
12
13
Return Me.Commando.ExecuteReader()
14
15
Catch ex As Exception
16
Return Nothing
17
Throw New BaseDatosException("ERROR :" & ex.Message & "
18 BASEDATOS.DameDatosDR ", ex)
End Try
19
End Function
20
5 Try
6
7 ReDim Preserve pParametros(Indice)
20 pParametros(Indice).DbType = DbType.Int64
22 pParametros(Indice).DbType = DbType.Double
pParametros(Indice).DbType = DbType.Boolean
24
Case "DC" 'Decimal
25
pParametros(Indice).DbType = DbType.Decimal
26
Case "DT" 'Datetime
27
pParametros(Indice).DbType = DbType.DateTime
28
Case "S" 'String
29
pParametros(Indice).DbType = DbType.String
30 Case "I" 'Integer
31 pParametros(Indice).DbType = DbType.Int32
32 Case "SM" 'Smallint
33 pParametros(Indice).DbType = DbType.Int16
34
35 End Select
36
37 pParametros(Indice).Value = Valor
Aadir_Parametro = True
38
Catch ex As Exception
39
Aadir_Parametro = False
40
Throw New BaseDatosException("ERROR :" & ex.Message & "
41 BASEDATOS.Aadir_Parametro ", ex)
42 End Try
43
44 End Function
45
Esta funcion debemos de llamarla antes que la funcion para devolver los datos de Base de Datos.
Ejemplo:
Para los que no sepais que es un procedimiento almacenado o PA, segun la definicion encontrada
en la wikipedia:
Es decir, sirver para hacer que las consultas a base de datos sean mas rapidas que
una consulta normal, ya que esta directamente conectado con la base de datos.
Asi que nuestra clase tambien debe de tener una funcion que sea capaz de ejecutar un PA
alojado en la base de datos que estamos conectada.
Para ello utilizamos la siguiente funcion:
?
1 Public Function Ejecutar_PA(ByVal NombreProcedimiento As String, _
10 Me.Commando.Parameters.Add(pParametros(i))
11 i = i + 1
12 End While
End If
13
14
If Me.Commando.ExecuteNonQuery() = 0 Then
15
Ejecutar_PA = False
16
Else
17
Ejecutar_PA = True
18
End If
19
20
Catch ex As Exception
21
Ejecutar_PA = False
22 Throw New BaseDatosException("ERROR :" & ex.Message & "
BASEDATOS.EjecutarPA ", ex)
23
End Try
24
25
End Function
26
Como habeis podido observar mientras hemos ido construyendo la clase BaseDatos el
compilador habr reconocido errores en la parte del catch ya que no reconocia la clase que
vamos a implementar a continuacin. Se trata de la clase BaseDatosException, la cual, como su
nombre indica va ha controlar las excepciones producidas durante el uso de la clase. Esto nos
permitira controlar las excepciones y traspasar el mensaje de error entre las capas de
nuestra aplicacin, es decir, que podremos saber que error se ha producido en la capa de
AccesoDatos desde la capa Negocio y luego en Presentacion, y asi mostrarla al usuario final.
Para ello nos vamos al Proyecto AccesoDatos y aadimos una nueva clase llamada:
BaseDatosException e implementamos el siguiente codigo:
?
1 Option Explicit On
2
3 Public Class BaseDatosException
4 Inherits ApplicationException
5
Public Sub New(ByVal mensaje As String , ByVal original As
6
Exception)
7 MyBase.New(mensaje, original)
8 End Sub
9
10 Public Sub New(ByVal mensaje As String)
11 MyBase.New(mensaje)
12 End Sub
13
14 End Class