Me he pasado el finde descansando y vagueando, que ya tocaba! (13/10/12)
Pero hoy es lunes, así que volvemos a la carga con el blog. Además empezamos la parte de programación.
En esta entrada ampliaremos el juego, usando ADO.net.
ADO.net
ADO.net es un objeto que el ".net" provee, con la función de conectar a las bases de datos sin demasiadas dificultades.
Por así decirlo, crea una capa extra entre el motor de la base de datos y la aplicación .net (así como hicimos con Java hace tiempo, pero de manera nativa).
Hay una serie de objetos que segregan de la utilización de ADO, que son:
- OleDbConnection: provee la conexión
- OleDbCommand: contiene sentencias SQL, sirve para lanzarlas
- OleDbDataReader: se usa para obtener los datos de las sentencias.
Una visualización de ejemplo: supongamos que al iniciar el juego de VB.net, éste conecta con la base de datos y ejecuta un SQL. El esquema sería algo así como indica la img1
img1 |
El evento onLoad tiene su recorrido en naranja: así, se puede ver cómo, usando los objetos de ADO.net accedemos a la base de datos, y extraemos datos, los cuales serán tratados con OleDbDataReader.
Haciendo un símil con PHP, el OleDbCommand equivaldría al mysq_query(), mientras que el OleDbDataReader equivaldría al mysq_fetch_array().
Diseño de consultas
El siguiente paso es diseñar todas las consultas que nos pudieran hacer falta. Aquí enumeraré unas cuantas imprescindibles:
- Comprobar si existe un usuario
- Crear un nuevo usuario
- Insertar un registro
Tal como quedó el modelo relacional, definiríamos las sentencias así:
- select count(*) from usuario where nick='';
- insert into email(email) values(''); insert into usuario(nick, nombre, apellido1, apellido2, idE, password) values('', '', '', '', select max(idE) from email, '');
- insert into estadistica(gana, tiempo, dificultad, opcion, autenticacion, minas, clicks) values('', '', '', '', '', '', '', ''); insert into juego(nick, id_estadistica, fecha) values('', select max(id_estadistica) from estadistica, '');
Desde luego estas consultas son las realmente básicas. No he puesto ningún dato porque de momento aún tenemos que ver cómo rellenaremos estas sentencias.
NOTA: cometí un error (como no...) cuando describía las tablas: la columna "minas" sirve para almacenar el número de minas que el usuario tenía marcadas cuando el juego terminó.
Hacer que funcione
El último paso antes de finalizar esta entrada es conectar todo; tenemos el MSAccess, el VB.net y el ADO.net. Es el momento de conectarlo todo!
Para ello, el objeto OleDbConnection necesita lo que se denomina "cadena de conexión". Ésta es un String que contiene información parametrizada sobre cómo y con qué conectará el objeto.
La cadena de conexión de ADO.net para MSAccess es la siguiente:
Provider=Microsoft.ACE.OLEDB.12.0;Data Source=SRC;Persist Security Info=False;
Las partes en negrita son variables. SRC indica la ruta física donde está la base de datos, y False indica si la conexión ha de ser persistente (por defecto siempre a false con MSAccess).
Ahora abrimos nuestro proyecto de VB.net, y añadimos las siguientes líneas en BX_module:
Public con As OleDbConnection
Public cn As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + Application.StartupPath + "\BuscaminaX.accdb;Persist Security Info=False;"
Public cmd As OleDbCommand
Public cn As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + Application.StartupPath + "\BuscaminaX.accdb;Persist Security Info=False;"
Public cmd As OleDbCommand
Aquí definimos los dos objetos fijos que usaremos para tratar nuestra base de datos. Dos anotaciones: seguramente tendréis que importar el dominio System.Data.OleDb. Para ello escribid al comienzo del módulo:
"Imports System.Data.OleDb"
Por otra parte, tenéis que copiar la base de datos "BuscaminaX" a la carpeta de la aplicación ("/bin/debug").
El siguiente paso es definir tres funciones globales para nuestra aplicación:
- Una función de conexión
- Una función de ejecución de SQL (insert, update, delete)
- Una función de consulta SQL (select)
Las podemos definir así:
#Region "SQL FUNCTIONS"
Public Sub Conectar()
BX_module.con = New OleDbConnection(cn)
End Sub
Public Sub Lanzar(ByVal sql As String, ByRef r As OleDbDataReader)
BX_module.con.Open()
cmd = New OleDbCommand(sql, BX_module.con)
r = cmd.ExecuteReader()
End Sub
Public Sub Ejecutar(ByVal sql As String)
Dim command As New OleDbCommand(sql, con)
Try
command.Connection.Open()
Catch ex As Exception
End Try
Catch ex As Exception
End Try
command.ExecuteNonQuery()
command.Connection.Close()
command.Dispose()
command = Nothing
con.Close()
End Sub
#End Region
Vamos a analizar un poco el código:
- Conectar() instancia un nuevo OleDbConnection usando la cadena de conexión "cn".
- Lanzar(sql, r) abre la conexión, instancia un nuevo OleDbCommand con "sql" y "con", y rellena "r". Nótese que para que los cambios en "r" sean persistentes, pasamos la variable por referencia ("ByRef") y no por valor ("ByVal")
- Ejecutar(sql) crea un nuevo OleDbCommand (ya que luego será destruído), y ejecuta la sentencia SQL pasada.
Para leer los datos que devuelve lanzar debemos hacer algo similar a PHP (por ejemplo). Concretamente:
Lanzar(ret, r)
Do While r.Read
'cosas. Se accede por "r(n)", donde n es un entero mayor o igual que 0
Loop
con.Close()
Do While r.Read
'cosas. Se accede por "r(n)", donde n es un entero mayor o igual que 0
Loop
con.Close()
Y así es cómo accedemos a los datos desde VB.net.
El siguiente paso es hacer un sistema de registro para cuando empieza el juego. También (después) crearemos una pantalla con estadísticas.
Para la pantalla de inicio de sesión, crearemos una nueva "SplashScreen". La llamaremos "LogIn.vb". De nuevo la preparamos borrando todo el contenido, y colocamos varios campos rellenables; tal que así:
img2 |
SI nick NO vacío
recoges datos de DB
SINO
error
FIN
SI datos(pass) NO vacío
SI pass vacío
error
SINO
SI datos(pass) = pass
ok!
SINO
error
FIN
SINO
ok!
FIN
recoges datos de DB
SINO
error
FIN
SI datos(pass) NO vacío
SI pass vacío
error
SINO
SI datos(pass) = pass
ok!
SINO
error
FIN
SINO
ok!
FIN
Se puede ver una gran cantidad de "IF". Ahora os explicaré lo que yo llamo "filtrar por return". Esta técnica quizás no sirva para acortar demasiado el código, pero sirve para evitar tantas identaciones.
El sistema es el siguiente: se supone el "peor" caso. Si se cumple salimos, sin más (terminamos el sub, retornamos un valor de control...).
En la siguiente línea, ya tenemos controlado el caso, por tanto no hace falta un "ELSE".
Aplicando este concepto, podemos hacer:
SI nick vacío
error(SALIR)
FIN
SI datos(pass) NO vacío
SI pass vacío
error(SALIR)
FIN
SINO
SI datos(pass) NO = pass
error
FIN
FIN
sigue
error(SALIR)
FIN
SI datos(pass) NO vacío
SI pass vacío
error(SALIR)
FIN
SINO
SI datos(pass) NO = pass
error
FIN
FIN
sigue
El siguiente caso a contemplar es el de crear un nuevo usuario. Para ello los pasos a seguir son:
- Comprobar si todos los datos están introducidos
- En caso que lo estén, comprobar si existe el usuario registrado
- En caso que no exista, introducimos los datos.
Crearemos dos funciones principales para sendas tareas. Podrían ser algo así:
#Region "LogIn"
Public Function nextStep() As Boolean
Dim r As OleDbDataReader
Dim pass As String
If LogIn.TextBox1.Text.Length = 0 Then
Return False
End If
BX_module.Conectar()
Lanzar("select nick, password from usuario where nick ='" + LogIn.TextBox1.Text.ToString + "'", r)
r.Read()
Try
pass = r(1)
Catch ex As Exception
pass = ""
End Try
BX_module.con.Close()
If pass <> "" Then
If LogIn.TextBox2.Text.ToString = "" Then
Return False
ElseIf LogIn.TextBox2.Text.ToString <> pass Then
Return False
End If
Else
If pass <> LogIn.TextBox2.Text.ToString Then
Return False
End If
End If
Return True
End Function
Public Function newUser() As Boolean
Dim r As OleDbDataReader
Dim cont As Integer
Dim idE As Integer
If LogIn.TextBox3.Text = "" Or _
LogIn.TextBox4.Text = "" Or _
LogIn.TextBox5.Text = "" Or _
LogIn.TextBox6.Text = "" Or _
LogIn.TextBox7.Text = "" Then
Return False
End If
BX_module.Conectar()
Lanzar("select count(*) from usuario where nick ='" + LogIn.TextBox4.Text.ToString + "' and idE = (select idE from email where email = '" + LogIn.TextBox5.Text.ToString + "')", r)
r.Read()
Try
cont = r(0)
Catch ex As Exception
cont = 0
End Try
BX_module.con.Close()
If cont <> 0 Then
Return False
End If
BX_module.Conectar()
Lanzar("select max(idE) from email", r)
r.Read()
Try
idE = r(0) + 1
Catch ex As Exception
idE = 1
End Try
BX_module.con.Close()
Ejecutar("insert into email(idE, email) values(" + idE.ToString + ", '" + LogIn.TextBox5.Text.ToString + "')")
BX_module.Conectar()
Lanzar("select idE from email where email = '" + LogIn.TextBox5.Text.ToString + "'", r)
r.Read()
Ejecutar("insert into usuario([nick], [nombre], [apellido1], [apellido2], [idE], [password]) values('" + LogIn.TextBox4.Text.ToString + "', '" + LogIn.TextBox6.Text.ToString + "', '" + LogIn.TextBox7.Text.ToString + "', '" + LogIn.TextBox8.Text.ToString + "', " + r(0).ToString + ", '" + LogIn.TextBox3.Text.ToString + "')")
BX_module.con.Close()
Return True
End Function
#End Region
Public Function nextStep() As Boolean
Dim r As OleDbDataReader
Dim pass As String
If LogIn.TextBox1.Text.Length = 0 Then
Return False
End If
BX_module.Conectar()
Lanzar("select nick, password from usuario where nick ='" + LogIn.TextBox1.Text.ToString + "'", r)
r.Read()
Try
pass = r(1)
Catch ex As Exception
pass = ""
End Try
BX_module.con.Close()
If pass <> "" Then
If LogIn.TextBox2.Text.ToString = "" Then
Return False
ElseIf LogIn.TextBox2.Text.ToString <> pass Then
Return False
End If
Else
If pass <> LogIn.TextBox2.Text.ToString Then
Return False
End If
End If
Return True
End Function
Public Function newUser() As Boolean
Dim r As OleDbDataReader
Dim cont As Integer
Dim idE As Integer
If LogIn.TextBox3.Text = "" Or _
LogIn.TextBox4.Text = "" Or _
LogIn.TextBox5.Text = "" Or _
LogIn.TextBox6.Text = "" Or _
LogIn.TextBox7.Text = "" Then
Return False
End If
BX_module.Conectar()
Lanzar("select count(*) from usuario where nick ='" + LogIn.TextBox4.Text.ToString + "' and idE = (select idE from email where email = '" + LogIn.TextBox5.Text.ToString + "')", r)
r.Read()
Try
cont = r(0)
Catch ex As Exception
cont = 0
End Try
BX_module.con.Close()
If cont <> 0 Then
Return False
End If
BX_module.Conectar()
Lanzar("select max(idE) from email", r)
r.Read()
Try
idE = r(0) + 1
Catch ex As Exception
idE = 1
End Try
BX_module.con.Close()
Ejecutar("insert into email(idE, email) values(" + idE.ToString + ", '" + LogIn.TextBox5.Text.ToString + "')")
BX_module.Conectar()
Lanzar("select idE from email where email = '" + LogIn.TextBox5.Text.ToString + "'", r)
r.Read()
Ejecutar("insert into usuario([nick], [nombre], [apellido1], [apellido2], [idE], [password]) values('" + LogIn.TextBox4.Text.ToString + "', '" + LogIn.TextBox6.Text.ToString + "', '" + LogIn.TextBox7.Text.ToString + "', '" + LogIn.TextBox8.Text.ToString + "', " + r(0).ToString + ", '" + LogIn.TextBox3.Text.ToString + "')")
BX_module.con.Close()
Return True
End Function
#End Region
Ahora viene enlazar los valores de retorno al módulo principal. Esto lo haremos en dos partes, de manera que:
- Crearemos una variable pública en LogIn.vb, de manera que el resultado de la función se guardará ahí.
- Mientras la variable anterior sea "false", mostraremos la pantalla principal.
Esto lo hacemos así:
a) LogIn.vb
Public hand As Boolean = False
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Me.hand = BX_module.nextStep()
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Me.hand = BX_module.newUser()
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Me.hand = BX_module.nextStep()
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Me.hand = BX_module.newUser()
End Sub
b) BuscaminaX.vb -> BuscaminaX_onLoad
Do
LogIn.ShowDialog()
Loop Until LogIn.hand
LogIn.ShowDialog()
Loop Until LogIn.hand
Con esto damos por terminada la parte de Programación en VB.net
Así, en la próxima entrada trataremos la gestión de consultas desde MSAccess.
Pido disculpas por la tardanza; repito que estuve MUY liado.
Espero poder seguir escribiendo más a menudo!
Saludos y,
¡Hasta la próxima!
No hay comentarios:
Publicar un comentario