Proyecto web: 111121PuenteASPNETyPHP
Código del Default:
<%@ Page Language="VB" AutoEventWireup="false" CodeFile="Default.aspx.vb" Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title></title>
<script type="text/javascript">
// Se abre una zona de javascript (nada que ver con Java. Es C (C++)
function OpenTag() {
window.open("http://www.as.com");
return false;
}
function OpenWin() {
var w = window.open()
w.opener = null;
w.document.location = "http://www.marca.com";
// w.close; -> si quisiesemos cerrar la ventana
return false;
}
// Ejemplo de funcion de comunicacion. Es una funcion que recibe dos parametros
// y los manda como argumentos a una pagina php.
function puentePHP(producto,articulo) {
var enlace = "http://www.chorradas.com/datos.php?idproducto=" + producto +
"&articulo=" + articulo;
window.open(enlace, "miventana","scrollbars=no,resizable=no,width=400,height=200");
return false;
}
function retroceder() {
// Retrocede una página
history.go(-1);
return false;
}
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Button ID="Button1" runat="server" Text="Button" OnClientClick="javascript:return OpenTag()" />
<asp:Button ID="Button2" runat="server" Text="Button" />
<asp:Button ID="Button3" runat="server" Text="Button" />
<asp:LinkButton ID="LinkButton1" runat="server">LinkButton</asp:LinkButton>
<asp:Button ID="Button4" runat="server" Text="Button"
onclientclick="javascript:return OpenWin()" />
</div>
<a href="http://www.as.com" target="_newTab" rel ="noreferrer"> Voy al As </a>
<br />
<br />
<asp:Button ID="Button5" runat="server" Text="Button" />
<asp:Button ID="Button6" runat="server" Text="Button" />
</form>
</body>
</html>
En la propia página:
Partial Class _Default
Inherits System.Web.UI.Page
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
' Metodo que se ejecuta al cargar la pagina.
' Le añadimos secuencias de javascript a Button2
Me.Button2.Attributes.Add("onclick", "javascript:return OpenWin();")
Me.Button3.Attributes.Add("onclick", "javascript:return puentePHP(10,20);")
Me.Button6.Attributes.Add("onclick", "javascript:return retroceder();")
End Sub
Protected Sub Button5_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button5.Click
'Genera html desde ASP.NET
Response.Write("<a href='http://www.as.com' target ='_blank'> Ir al As </a>")
' History.go() 'Retrocede a la página anterior.
' History.go(-2) 'Retrocede 2 páginas.
End Sub
End Class
Como adaptar totalmente el sistema a las necesidades de nuestro cliente. Hoy hay muchas notas que iremos completando.
Creamos un uevo sitio web (no vacío) con framework 4.0: 111118AdaptarSistema
Tendremos 2 tablas: una que gestionamos nosotros…
Para alojar el sitio web, la cadena de conexión está aquí (en WEB CONFIG).
<?xml version="1.0" encoding="utf-8"?>
<!--
Para obtener más información sobre cómo configurar la aplicación de ASP.NET, visite
http://go.microsoft.com/fwlink/?LinkId=169433
-->
<configuration>
<connectionStrings>
<add name="ApplicationServices"
connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\aspnetdb.mdf;User Instance=true"
providerName="System.Data.SqlClient" />
</connectionStrings>
Está al principio de todo. Al modificar esto ya se cambia el alojamiento (para pasarlo al 1and1).
Para acceder a esas tablas.
Si la cadena no aparece en el webcong del 3.5, se copian todos los perfiles, se modifican y se pegan.
Hoy hemos creado las páginas de Alta de Clientes y Alta de Proveedores. Lo hicimos a través de una tabla donde introducimos un FormView (podría servir cualquier otro).
Se desea buscar un Cliente por NIF (por ejemplo). Como otras veces, en el el DataSource, en el WHERE señalamos el NIF, LIKE, CONTROL (en un textbox que añadimos en la fila de abajo) y el %.
Para evitar que recargue la página al darle al BOTÓN (un botón, por defecto, activa el POSTBACK) [ver más datos aquí].
También el programa debe detectar si la página es un reenvío. Lo recordamos de otras veces:
Partial Class Altas_Clientes
Inherits System.Web.UI.Page
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
'Código que se ejecuta si la página no es reenvío.
'Esto se puede hacer en cualquier lugar.
End If
End Sub
End Class
Pueden aparecer otros errores no controlados. Para ello debemos realizar una modificaciones en Webconfig. Habilitamos la siguiente parte que está en comentarios:
Lo habilitamos.
<customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm">
<error statusCode="403" redirect="NoAccess.htm" />
<error statusCode="404" redirect="FileNotFound.htm" />
<error statusCode="" redirect="FileNotFound.htm" />
</customErrors>
Debemos crear ErrorDatos.aspx. Después modificamos lo siguiente Global.axa:
Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs)
' Código que se ejecuta al producirse un error no controlado
Response.Redirect("~/Altas/ErrorDatos.aspx")
End Sub
A partir de entonces debería ser cuando se atacan los eventos en la introducción de datos que vimos en el post anterior y en su posterior documento. Más datos de este post, aquí.
Pondremos en esta sección distintas aplicaciones útiles que hemos aprendido en la creación de una página web a través de ASP.NET.
El programa está bastante avanzado. Iremos introduciendo temas sueltos.
Hemos insertado en nuestra página aspx un FormView. Tiene varios eventos asociados a la introducción de datos. Se trata de UPDATED, INSERTING y UPDATING. Los eventos terminados en -ED hacen referencia a una vez que se han actualizado los datos. Por ese motivo disponen de los datos antiguos (OldValues) y los nuevos (NewValues). Los terminados en –ING sólo disponen de los OldValues.
En este doc detallamos algunos comentarios sobre las distintas pruebas que hicimos.
Importante: Para el caso de la introducción correcta de los correos electrónicos hicimos uso del “método científico” (siempre se debería hacer de este modo). Pueden verse los códigos en: http://msdn.microsoft.com/es-es/library/bb932288.aspx
If Regex.IsMatch(e.NewValues.Item(8).ToString.Trim, "^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$") = False Then
Me.Label3.Text = "EMAIL incorrecto".Length
e.Cancel = True
End If
End Sub
Convierte un valor en la representación de cadena equivalente.
int mensaje1 = 123;
label1.Text = mensaje1.ToString();
Convierte un valor en la representación de cadena equivalente.
int mensaje1 = 123;
label1.Text = mensaje1.ToString();
Para poder conectar remotamente con sql debemos abrir estos puertos,
se abre la consola de comando y ejecutamos estas dos ordenes
Primer comando
netsh firewall set portopening protocol = TCP port = 1433 name = SQLPort m
ode = ENABLE scope = SUBNET profile = CURRENT
Segundo comando
netsh advfirewall firewall add rule name = SQLPort dir = in protocol = tcp
action = allow localport = 1433 remoteip = localsubnet profile = DOMAIN
Convierte el valor de un carácter Unicode en un carácter equivalente, pero en minúsculas.
string mensaje1 = "Pasa a Minúsculas";
label1.Text = mensaje1.ToLower();
Transfiere el control del programa directamente a una instrucción identificada por una etiqueta.
goto Finish; // Goto
Finish: // Etiqueta
Console.WriteLine("Se acaba el programa.");
Declara una enumeración. Se declara fuera del espacio de nombres. De forma predeterminada, el primer enume-rador tiene el valor 0 y los sucesivos se van incrementando en 1. Así…
enum Dias { Lunes, Martes, Miércoles, Jueves, Viernes, Sábado, Domingo };
… lunes vale 0; Martes, 1; Miércoles, 2… Sin embargo, podemos cambiar el valor inicial y los sucesivos:
enum Dias : byte { Lunes = 2, Martes, Miércoles, Jueves, Viernes, Sábado, Domingo };
Los tipos admitidos para una enumeración son byte, sbyte, short, ushort, int, uint, long o ulong. El tipo predeter-minado es int.
Especifica que el valor del campo o de la variable local es constante, o sea, que no se puede modificar.
const double Pi = 3.1416;
label1.Text = Pi.ToString();
const double x = 1.0, y = 2.0, z = 3.0;
Para introducir comentarios en el código hay dos métodos:
// De esta forma se introduce una línea de comentarios.
/* Esta forma permite introducir varías líneas.
*
* Se cierra con: */
En las últimas semanas estamos trabajando en un programa de gestión nuevo. Uno de los puntos más destacados donde incidimos en estas clases son los INFORMES. La temática sería:
1. Informe normal (REPASO).
2. Informe parametrizado (REPASO).
3. Informe agrupado (NUEVO).
4. Informe ASP.NET (NUEVO).
a. Parámetros.
b. Agrupado.
c. Asíncrono.
Las siguientes notas nos pueden ayudar a recordar los pasos más importantes.
Hemos tenido unas nociones de C#. mostramos algunos temas tratados este mes.
Una cadena es un objeto de tipo String cuyo valor es texto. La propiedad Length de una cadena representa el número de objetos Char que contiene. En C#, la palabra clave string es un alias de String. Por lo tanto, String y string son equivalentes y se puede utilizar indistintamente.
1. DECLARACIÓN:
string Cadena;
String Cadena2;
2. DECLARACIÓN E INICIACIÓN COMO NULL
String Cadena = null;
3. CONCATENACIÓN
string mensaje1 = "Hola";
string mensaje2 = "Amigo";
mensaje1 = mensaje1 + mensaje2;
19 de agosto de 2011
Recordamos que Corsair está en línea con nuestro anfitrión. Cada uno de los pasos están señalados en este documento.
Siguiendo este documento se nos detalla CÓMO MONTAR UN SERVIDOR FTP.
Importante: Si se está empleando internet se producen muchos problemas con el FTP. Por lo tanto, vamos a emplear los comandos básicos de FTP. Señalamos algunos:
ls muestra el listado del directorio remoto (los archivos que están en el directorio remoto)
cd se mueve por las carpetas remotas
lcd se mueve por las carpetas locales
put archivo sube el archivo
get archivo baja el archivo
mput archivo sube múltiples archivos
mget archivo baja múltiples archivos
disconnect cierra la conexión
connet conecta
mkdir carpeta crea una carpeta remota
rmdir carpeta borra una carpeta remota
rm archivo borra un archivo
remove archivo borra un archivo
pwd nos dice la carpeta remota
Adrián preparó este documento donde aparecen más comandos FTP con sus explicaciones.
Otro detalle relevante que nos consiguió superar las dificultades: tuvimos que desactivar el Firewall en el ordenador central y en el servidor.
Hemos tenido que instalar FileZilla: os ayudará a convertir nuestro ordenador en un servidor de FTP.
El siguiente documento en una continuación del anterior. Hemos explicado cómo se crea un ALOJAMIENTO WEB CON CABECERA. Después seguimos creando UN ALOJAMIENTO WEB CON ACCESO FTP. Ver AQUÍ.
1 y 2 de septiembre de 2011
José Carlos Alcántara ha diseñado el siguiente documento sobre la clase de hoy. Fue una sesión muy práctica que al día siguiente repetimos en parte.
También trabajamos con las conexiones con cable de teléfono. Dos cosas:
- Los cables tienen 4 hilos. Sólo tienen conexión los del medio. Los de los extremos tienen una función de soporte cuando las distancias del cable se alargan. Se pueden enlazar en los casquillos de enlace para 6 hilos: simplemente debemos colocar los 4 en los huecos centrales.
- Las empresas como Telefónica, R, etc. suelen darnos un switch. Javier se extendió sobre cómo se hacen esas conexiones a la red telefónica. A ese aparato sí llega un cable telefónico y es imposible que enrute. En los router (generalmente) sólo se conectan cables de red.
La semana pasada estuvimos varios días trabajando la herencia de clases. Ahora vamos a estudiar las interfaces de objetos.
En VISUAL, una clase sólo puede heredar de una clase a la vez. Puede implementar varias interfaces a la vez.
Importante: no se pueden crear objetos de las interfaces.
Una interfaz se usa para que las clases que la implementen ( ≠ hereden) tengan unos tipos o métodos comunes. Así se garantiza que las clases implementadoras usan esos tipos.
NOTA: Se trata de un caso muy distinto al conceto de “herencia múltiple”.
Las interfaces se dice que pertenecen a los polimorfismos.
Debemos tener en cuenta que una interfaz puede heredar de otra. Y son las únicas que pueden heredar de más de una interfaz a la vez pero no puede implementar ninguna interfaz.
Ejemplo:
Class Arraylist
Implements IList
Class List
Implements IList
De esta manera, las 2 clases implementan IList.
Hemos empezado con este proyecto de interfaces: Proyecto 220811Interfaces1.
El siguiente proyecto fue éste: Proyecto 220811ClaseGenerica.
Otro proyecto: Proyecto 220811Interfaces2.
Se puede ver en el siguiente diagrama lo analizado.
La siguiente tabla nos muestra las conclusiones de estos ejercicios para distinguir implementación de herencia:
| INTERFACE | CLASE | |
Hereda de una clase | NO | SÍ | INHERITS |
Hereda de varias clases | NO | NO |
Hereda de interfaces | SÍ | NO |
Hereda de más de una interface | SÍ | NO |
Implementa interface | NO | SÍ | IMPLEMENTS |
Implementa más de una interface | NO | SÍ |
29 de agosto de 2011
Seguimos con la clase de archivos. Hemos realizado proyecto 290811Carpetas4. De forma sencilla se entiende el procedimiento.
También hemos realziado este otro proyecto: aparecen 2 métodos de cómo hacerlo. Puede parecer algo más confuso: importando IO o utilizando otra alternativa. Otro archivo de ejercicio con la IO es éste: vemos que hay algunas limitaciones a causa de los permisos concedidos a los rodenadores de clase.
Ya hemos visto las relaciones entre clases. Las sesiones siguientes de POO serán para realizar un Estudio a fondo de la herencia. Sea el siguiente proyecto 190811HerenciaAFondo1. Vemos lo que representa una directiva. El siguiente proyecto 190811HerenciaAFondo2 pretendíamos seguir profundizando con las directivas: tuvimos que desistir ya que el llamado directo en VISUAL STUDIO 2010 no aparece.
Finalmente hemos aprovechado el proyecto 190811HerenciaAFondo3 para estudiar los alcances. Se cumplen según esta tabla que recordamos:
| PUBLIC | PRIVATE | PROTECTED |
¿Pueden acceder los objetos de la clase? | Sí | No | No |
¿Lo heredan las clases derivadas? | Sí | No | Sí |
¿Y cómo son los alcances en los espacios de nombres?
Se cumplen las indicaciones del siguiente recuadro:
| ACCESIBILIDAD |
PUBLIC | PRIVATE | FRIED |
Por otras clases | SÍ | NO | SÍ |
Por otros módulos | SÍ | NO | SÍ |
Por otros espacios de nombres | SÍ | NO | NO |
Por otros ensamblados | SÍ | NO | NO |
Nota: Protected sólo se emplea dentro de clases. Sólo para herencia de clases. Tiene que estar dentro de CLASS y de END CLASS. Fuera de ahí carece de existencia.
Probamos esto en el proyecto 190811HerenciaAFondo4_Ensamblado2. El ensamblado es todo el conjunto del programa.
A esto se llama ensamblado (propiedades del proyecto): ver aquí cómo se ven en el VISUAL..
Jimmy está redactando un documento más profundo sobre las clases y estructuras que se puede ver aquí. También ha redactado otros documentos más elaborados y específicos sobre el tema. Son los siguientes:
- ACCESIBILIDAD 1: Explica conceptos básicos: Tipos de ficheros o módulos que se pueden usar en VB.NET y Cómo... saber cuándo usar Protected, Private, etc.
- ACCESIBILIDAD 2: Se tratan temas como declarar Propiedades y Métodos en las clases.
- ACCESIBILIDAD 3: Cómo usar otros modificadores de Métodos (Shared, Overridable, etc.).
19 de agosto de 2011
Vamos a empezar creando 2 dominios en una de nuestras máquinas virtuales para cada miembro de la clase (todos distintos entre sí). En nuestro caso, por ejemplo:
www.dominio3.com
www.dominio4.com
Adrián elaboró el siguiente documento donde se detalla cada uno de los pasos para crear lo que Javier denomina el “DOMINIO DEL POBRE”. Es un sistema muy eficaz (con una apariencia algo chusca).
También Adrián redactó en otro documento las indicaciones que Javier nos dio en clase para crear ALOJAMIENTOS WEB CON CABECERA. Con esto ya tenemos hemos completado la creación de los dominios.
Para avanzar en la programación orientada a objetos debemos conocer un poco más los eventos. En concreto, vamos a estudiar los eventos que se producen cuando un control está activo y deja de estarlo. En este orden:
1. Enter.
2. GotFocus.
3. Leave (abandonamos el control).
4. Validating (se validan los datos del control). Hay que activarlo.
5. Validated (el control ha sido validado). Hay que activarlo.
6. LostFocus (el control pierde el foco).
Asi tengo un control Button1. En el caso de emplear button1.Focus() con código se ejecutan con un orden diferente. Al dar focus, sigue este orden (siempre será así cuando damos la orden con código):
1. Enter.
2. GotFocus.
3. LostFocus (el control pierde el foco).
4. Leave (abandonamos el control).
5. Validating (se validan los datos del control). Hay que activarlo.
6. Validated (el control ha sido validado). Hay que activarlo.
CausesValidation tiene que estar a True para que se ejecute el orden de eventos.
Vamos a suponer que el primer control (textbox) tiene que tener una longitud mínima de 4.
En el proyecto 180811Validar experimentamos como se opera.
17 de agosto de 2011
Hoy hemos trabajado con IIS = INTERNET INFORMATION SERVER. Es el sistema de los protocolos HTTP, FTP y SMTP. Es decir: publicar páginas web, transferencia de archivos y correo electrónico. También en la HTTPS (la aplicación web segura).
En los entornos corporativos de alto rendimiento se emplea el IIS.
Vamos a instalarlo en Corsair. Quitamos al función DNS. Intentamos que aquí se pueda publicar nuestros proyectos de ASP.NET. La instalación de IIS se hace en funciones. Le metemos los servicios de aplicaciones, FTP y HTTP.
Adrián ha redactado el siguiente documento sobre la instalación de la IIS. Al final conseguimos publicar este proyecto 170811AspNet01. También probamos a meter un proyecto de ASP.
16 de agosto de 2011
Adrián ha elaborado el siguiente documento tomando información de diversas web sobre los protocolos TCP/IP. De forma muy descritiva señalamos algunas notas de clase:
En cada host (cada ordenador) existen diversos niveles o capas. Cada capa tiene comunicación (a través de interfaces) con las CAPAS más próximas. La comunicación a través de máquinas diferentes al mismo nivel se realiza a travñes de PROTOCOLOS (conjunto de reglas que regulan la transferencia de información de los mismos niveles en distintas máquinas). En el siguiente gráfico se puede ver con claridad.
· NIVEL FÍSICO. Son los cables, la circuitería… Se comunican bytes entre los distintos host.
· NIVEL DE ENLACE. Se trabaja con nº MAC. Se comunican tramas entre los distintos host.
A este nivel funciona el protocolo IEE802. Las más famosas de esta capa son: 802.3 (Ethernet), 802.4 (token bus), 802.5 (token ring), 802.11 (wifi) y 802.16 (wimax).
También funciona el protocolo PPP (punto a punto) y el HOLC (protocolo de enlace a alto nivel).
IMPORTANTE: Esta capa se divede en 2 subnivels:
a) Subnivel MAC.
b) Subnivel LLC. El empleo de LLC es proporcionar servicios a nivel de enlace para que se vea lo mismo con independencia de la red física.
· NIVEL DE RED. Se comunican paquetes entre los distintos host. Su función es encaminar los paquetes a destino. Se trabaja a través de las IP.
· NIVEL DE TRANSPORTE. Se comunican paquetes o datagramas entre los distintos sockets. Las tarjetas de red vienen con una capa de red implementada (se comporta como wifi, Ethernet…). El ordenador debe encargarse de la LLC. La transmisión es confiable. Existen 2 importantes protocolos:
§ TCP: orientado a la conexión. Seguimos hablando de paquetes.
§ UDP: no orientado a la conexión. Hablamos de datagramas.
· NIVEL DE APLICACIÓN. Aparecen importantes protocolos que se ven aquí.
Para entender mejor esto, Javier nos propone el siguiente ejercicio: tenemos un concentrador Ethernet è Tiene un subnivel MAC común. Si tenemos un enlace 802.3 (ethernet) y 802.11 (wifi) tendremos lo siguiente (ver aquí).
En realidad, la transmisión entre hosts se produce así (ver gráfico). Con él entenderemos que un ordenador es un router que sólo llega al nivel 3 o de RED:
- La información del host A en la capa de aplicación pasa (baja) del nivel de transporte y se divide en paquetes.
- Baja al nivel de red y se le añaden nuevos paquetes.
- Ahí se subdivide entramas y baja al nivel de enlace.
- El nivel físico añade su cabecera (vamos teniendo más información redundante).
- La trama física va al router. Éste elimina la cabecera y cola físicas y las sube al nivel de enlace.
- El nivel de enlace suprime su cabecera/cola correspondiente y la sube al nivel de red.
- La red examina el paquete y decide por dónde enviarlo a su destino. Una vez que reconoce el destino, bala al nivel de enlace: éste le añade su cabecera/cola.
- Baja al nivel físico y le añade la cabecera/cola nueva correspondiente.
- Va al ordenador host B a nivel físico. Le quita la cabecera/cola físicas y la sube al nivel de enlace.
- Mismo proceso en la capa de enlace.
- Al llegar a la capa de red ya es un ordenador y toma decisiones. Si decide que la infromación es para él, elimina la cabecera/cola correspondiente y lo eleva al nivel de transporte.
- El nivel de transporte lo eleva a la de aplicación (eliminando su parte).
- La capa de aplicación facilita la indormación a su usuario.
NOTA: los ordenadores siempre escuchan todos los paquetes y los elevan a su nivel de red.
En su nivel de red deciden:
1. Si es para él, lo eleva a la capa de trasnporte.
2. Si es no para él, lo vuelve a bajar de capa.
A nivel de red, el protocolo que se emplea es el RIP.
16 y 17 de agosto de 2011
Vamos a estudiar las relaciones entre clases. Le dedicaremos varios días.
Hoy nos hemos dedicado a los 3 primeros tipos de relaciones:
- 1ª relación: asociación (1 a varios).
- 2ª relación: muchos a muchos. El diagrama de clases se ve incapaz de soportar esto. Hay que meter una clase intermediadora (el problema es similar a las relaciones M:N).
Se puede ver aquí el proyecto 160811CPO3 con las explicaciones de los dos primeros tipos de relación.
- 3ª relación: agregación y composición. En este proyecto vemos cómo se agrega una clase con otra. En la composición se dice que los objetos de una clase contienen físicamente los objetos de otra clase (usando Arrays o Colecciones).
NOTA: Javier prefiere colecciones.
En este ejemplo, los objetos de la case Polígono van a tener una colección que contendrá objetos del tipo Vértice. Cuando los objetos están dentro de los objetos del otro se denomina Composición. Se señala con un rombo negro.
Para distinguir la Composición de la Agregación, hacemos el siguiente proyecto. La diferencia básica de la Agregación es que si desaparece la clase Almacen se sigue manteniendo la clase agregada (Cliente). En la composición, al desaparecer la de Almacen también desaparecería la clase compuesta (Pasillo).
Nota: la agregación se señala con un rombo vacío.
¿Cómo implementar una agregación? Hay 2 formas:
a) Se pone la clave foránea en Clientes.
b) En Almacen ponemos una colección con los NIF de los clientes. En el ejercicio optaremos por esta opción (si la clase Clientes tiene más relaciones con otras clases, parace más elegante).
Para implementar la composición, las opciones son las mismas:
a) Se pone la clave foránea en Clientes.
b) En Almacen ponemos una colección con los Pasillos (directamente). Es la que empleamos en este proyecto.
c) En Almacen ponemos una colección con los números de los Pasillos.
- 4ª relación: la dependencia. Una clase depende de otra.
12 de agosto de 2011
Pasos empezar a programar en red. Dice Javier que ahora vamos a afrontar retos de calado. Hemos realizado distintos ejercicios para probar cada uno de los pasos.
1º. Comprobar al disponibilidad de la red. Ponemos un botón para ello. Proyecto 120811Red1. Atención: tuvimos que programar en ApplicationEvents.vb.
2º. Conocer todos los adaptadores: wifi, bluetooth… Proyecto 120811Red2.
3º. Intentar conectarnos. Proyecto 120811Red4. Para entender este ejercicio Javier tuvo que enseñarnos el manejo de With: se peude ver aquí.
4º. Escaneo de puertos. Proyecto 120811Red5_Puertos.
MUY IMPORTANTE: Un puerto es una dirección de memoria asociada a un servicio hardware, software o de red. A través de esas direcciones de memoria se transfieren páginas web, correo, etc.
Comentario: un ordenador es placa base, memoria, CPU y puertos (periféricos). El ordenador está leyendo esos puertos de forma contínua. Disco duro es un periférico: va conectado a un puerto (por ejemplo).
Nos centraremos en este curso en los puertos de red.
El protocolo de las páginas web es el http. Tiene asociado el puerto 80.
Si se desea acceder a la web de terra sucede que un paquete hace lo siguiente:
Destino | Puerto |
www.terra.es 213.4.130.210 | 80 |
La dirección 80 está en la RAM del ordenador. Por el empleo de ese puerto se conoce que se está requiriendo el acceso a esa web.
Listado de puertos de un ordenador. Ver aquí. Se ve cada puerto con su protocolo. Cda protocolo va en azul: lo demás son programas.
Si cambio el puerto de destino (al 21), pido una trasnferencia de archivos vía ftp.
Si cambio el puerto de destino (al 25), pido que envíe un mail.
Así el servidor sabe lo que tiene que hacer (al conocer el puerto que se le reclama). El servidor debe estar siempre atendiendo peticiones.
Una vez establecida la conexión con el servidor, se crean una serie de puertos adicionales (según el protocolo) en el servidor y en el cliente entre los que se realziará la transferencia de información.
Una forma de estudiar si están atacando nuestro ordenador ver qué puertos tenemos activos.
En internet existen 2 protocolos básicos para todos los puertos:
- TCP: orientado a conexión y se dice que trabaja con nosotros.
- UDP: no orientado a conexión.
A un par dirección IP + puerto se denomina SOCKET. Son los extremos de las conexiones. Javier nos hizo el siguiente ejercicio para que entendamos qué es un socket y para qué sirve. Adrián lo muestra este gráfico. Al abrirse el puerto 80 el servidor al que le reclaman el acceso a su dirección web conoce qué se le está reclamando esa información. Ese socket (ip + puerto) será único en el mundo. Vemos que el socket local (el de nuestro rodenador) se relaciona con el socket remoto (el servidor de la web de terra.es, en este caso). Esto puertos los abre el protocolo http que estudiaremos en la siguiente sesión.
11.08.11
Con el avance de la clase de ayer, ya podemos enfrentarnos a nuestro proyecto 110811ClasePOO1 (será la 1ª clase de programación orientada a objetos). Antes de empezar vamos al Designer y vemos los Javier nos explica lo siguiente:
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _ 'Directiva generada por Visual. Es modificable.
Form è es una clase que contiene los atributos y métodos de los formulario. En principio és inmodificable.
Al crear formulario se crean 2 archivos:
· Partial Class From1 'Lo gestiona Visual.
· Class From1 'Lo programamos nosotros
Ambos archivos forman la clase Form1 (y son derivados – o heredados – de Form1.
Por tanto Form1 no se puede usar. visual crea en cada formulario un objeto del mismo (Me) y se ejecuta el formulario a través de Me. è En algún sitio debe existir esta declaración:
Dim Me as new form1
Las explicaciones del proyecto son muy clarificadoras. De forma gráfica nos lo muestra Adrián aquí las indicaciones de Javier.
Para entender mejor las herencias de clases, el proyecto 110811ClasePOO2 dirigido por Javier relata una herencia de una clase en otra. Muy gráfico.
Además, Javier explicó el diagrama de clases de este mismo proyecto. Adrián lo recogió aquí. El mismo Javier nos recuerda que la herencia múltiple no está permitida en Visual Basic (en C++ sí). En este caso, veríamos un ejemplo de herencia múltiple si pretendiéramos crear una clase que heredara de la clase Persona y de la clase Trabajador al mismo tiempo: no es posible.
10.08.11
Volvemos a VISUAL BASIC. La idea de Javier es empezar en serio a estudiar los componenetes de Visual: con ello iniciaremos la PROGRAMACIÓN ORIENTADA A OBJETOS. Antes debemos entender el control de los eventos. Hemos realizado 3 proyectos sencillos.
En el primero de ellos vimos cómo un sencillo evento como el Click de un botón:
Private Sub Button1_Click(ByVal sender As System.Object,ByVal e As System.EventArgs) Handles Button1.Click
Si añadimos un label y unos botones, añadiendo esto…
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click, Button2.Click, Button3.Click, Label1.MouseHover
… todos ejecutarán lo mismo.
En el 2º proyecto nos dedicamos a generar un evento propio. De inicio nos metimos en el Designer de cada proyecto. Vamos a explicar esto:
Private WithEvents cl As Persona
Esto significa: cl es un objeto del tipo Persona. Además, escuchará e interceptará los eventos generados por la clase Persona.
Imaginemos que la clase Persona genera 2 eventos: Uno() y Dos(). Por lo tanto esto significa que podemos tener en elgún sitio:
Private Sub cl_Uno (ByVal sender As Object, ByVal e As EventArgs) Handles cl.Uno
En el caso del ejercicio vemos que:
Friend WithEvents Button1 As System.Windows.Forms.Button
Es decir: Button1 tiene todos los eventos de la clase Button.
Imaginamos que disponemos de la clase botón.
'PASO 1.
Class Boton
'...
Public Event Click()
Public Event MouseLeave()
Public Event MouseHover()
'...
End Class
'PASO 2. En otro módulo hacemos lo siguiente:
Private WithEvents boton1 As Boton
Private WithEvents boton2 As Boton
Private WithEvents boton3 As Boton
'PASO 3. A partir de ahora boton1, boton2 y boton3 pueden interceptar (manejar) esos eventos.
Private Sub boton1.click() handles boton1.click()
'...
End Sub
End Class
En el ejercicio lo vemos en detalle.
En éste último proyecto hemos modificado los eventos según aparecía el evento predeterminado. Comprobamos que todos los componentes son iguales: tienen los mismos eventos (en su mayoría). Podemos hacer cosas como, por ejemplo, ejecutar el evento click al darle al formulario.
El 9 de agosto hemos estado estudiando este protocolo DHCP. Se trata de un protocolo que asigna de forma dinámica direcciones IP, máscaras de subred y DNS a ordenadores cliente. Si un ordenador configurado para el DHCP no obtiene esas direcciones, obtendrá una APIPA /16 (ej.: 169.254. … . … ). De forma gráfica lo recoge aquí Adrián.
Para ello vamos a crear una nueva máquina virtual y a posteriori la replicaremos. Los pasos de cómo los hemos realizado en Virtual PC se pueden ver en el documento de Adrián: Replicando máquinas virtuales. Gracias a estas máquinas podemos comprobar cómo se obtiene una dirección APIPA en una de las máquinas al seleccionar “obtener la IP automáticamente”.
Este ejercicio nos sirvió para comprender la importancia del protocolo APIPA. En el esquema realizado por Adrián de una red local (con una impresora conectada a uno de ellos) el protocolo APIPA puede hacer que todos los ordenadores se conecten a una red local sin que la persona que realice la conexión tenga conocimientos de redes: APIPA soluciona el problema. Advertimos que esto sólo es posible si los ordenadores tienen Windows.
En el caso (también señalado en el gráfico) que el concentrador esté conectado a un servidor DHCP (un router, un Windows Server o Linux), ningún Host puede tener una dirección APIPA. Si aparece es que hay un problema con el cableado o la conexión DHCP está interrumpida.
Nuestra idea es que una de las máquinas virtuales haga de servidor de la otra. IMPORTANTE: un servidor siempre debe disponer de una IP estática.
¿Cómo crear un servidor? En la máquina escogida hacemos lo siguiente:
Herramientas administrativas --- administrador servidor --- funciones (agregar) --- servidor DHCP.
Ponemos el DNS de nuestro ISP (Telefónica, R o quien corresponda: así tendremos conexión a internet).
Al reiniciar estuvimos haciendo ejercicios creando ámbitos en IPV4. Así:
Herramientas administrativas --- DHCP --- Crear ámbito (en IPV4) --- nos concedemos unas IP entre 100.68.110.150 y 100.68.110.175.
Podemos establecer exclusiones (reservamos unas IP para otros usos: un servidor, p. e.).
Importante el apartado de la “duración de la concesión”: dependiendo del tipo de empresa las IP serán más o menos volátiles. Ejemplo: para un cicer-café, la volatilidad será muy elevada (podríamos 2 horas, p. e.)
También creamos un ambito para IPV6. Muy similar.
Se nos indicó que todas las tarjetas tienen un nº mac. También se nos explicó el concepto “hacer una reserva DHCP”: se trata de asignar siempre la misma IP a la tarjeta de ese nº mac.
Para conocer el nº mac de un ordenador se puede hacer así en Símbolo del sistema: ‘> getmac / s corsair6 (el ordenador de destino) | clip’.
NOTA: sólo se puede crear un ámbito en cada subred. Se puede disponer de varias subredes: cada una tendrá su propio ámbito. Probamos a crear un 2º ámbito: se produce un conflico. O modificamos la máscara de subred o las direcciones IP.
El lunes 8 e agosto dedicamos gran parte de la clase a hacer ejercicios de cómo dividir una subred en el caso en el que necesitemos emplear un rango de direcciones. Adrián muestra el siguiente ejercicio: resulta muy clarificador.
Hemos tenido una clase muy interesante al respecto. Este documento de Adrián es muy revelador: describe los pasos más importantes para la creación de un dominio DNS. Se trata de un documento de 20 páginas (la mayoría muy descritivas) del que destacamos lo siguiente:
- Tras señalar el nombre del dominio (nombre Net Bios, por ejemplo, “DOMINIO1”), la máquina virtual pasa a llamarse “dcsrv1.dominio1.local”. éste será su nombre DNS.
- Crear zonas de búsqueda inversa para poder llamar al ordenador por su IP (en el documento se detalla despacio cada uno de los pasos a seguir). Los DNS tienen 2 zonas de búsqueda directa:
§ Se les pregunta por el nombre y devuelve la IP.
§ Se les pregunta por la IP y devuelve el nombre.
- Nota: se crearía una zona ARPA si dejamos vacío el tercer segmento al crear la zona de búsqueda inversa: se puede dividir en subredes.
- Lo hacemos también en IPV6 y forzamos al registro del dominio con ‘ipconfig/registerdns’.
En la 2ª parte del documento se nos detallan las referencias que puede tener un ordenador de sí mismo.
Después, viene la descripción de cómo añadir un ordenador a un dominio.
En otra sesión se nos explicó la manera de fusionar 2 dominios. En el dibujo del documento (nos fue imposible añadirlo al blog directamente) se describe lo que pretendimos hacer.
Debemos hacer uso de un reenviador condicional. Adrián muestra en detalle cómo hacerlo.
Después hemos visto los tipos de registros que se pueden crear en un DNS (a mano). Hicimos un ejercicio para crear un CNAME.
Para finalizar estudiamos el protocolo APIPA.
Este día lo hemos dedicado a realizar ejercicios en IPV4: conocer cuántas subredes podemos disponer, nº de host libres en una subred. Los cálculos son sencillos: se requiere un método sencillo que Adrián ha recogido en este documento.
Mucha atención a las explicaciones de cómo se puede realizar la división de subredes en IPV4. Las indicacionesde Adrián son muy valiosas; recoge todos los ejercicios que Javier nos puso en clase.
Al finalizar, desactivamos IPV4, activamos IPV6 y borramos el DNS. El propósito era realizar la división de una subred en IPV6. Vemos que a diferencia de los cálculos de IPV4, en IPV6 son innecesarios.
Si tenemos una red ULA del tipo fd00::221, harímos lo siguiente:
fd00:: | 1 | : 0: 0: 0: 221 |
| Se asigna a la subred | Éstos son los 4 segmentos del host en la red |
Dirección de la red | |
Otra subred será, por tanto: fd00::2:0:0:0:222.
También hicimos un ejercicio de repaso de la división de subredes en IPV4. Se trata de un caso particular de 2 dominios. se peude ver aquí.
Adrián nos explica en este documento la estructura que mantiene cada tipo de dirección en IPV6 (ya explicado el otro día). Con un ejercicio vemos cómo es el despliegue de una IPV6.
Las últimas páginas del documento explican en qué consiste el enrutamiento en IPV4. Se nos insiste que, en lugar de routers, se puede emplear un server para que realice esta función. Entenderemos qué es un rango de difusión, Puerta de enlace (o IP interna) e IP externa. De esta manera gráfica entendemos porqué se repiten las IP de los ordenadores: los router van cambiando las IP para que puedan llegar a su destino.
Como conclusión sacamos lo siguiente: para conectar un grupo de ordenadores a un concentrador nos basta con una IP y una máscara de subred (se puede prescindir de la puerta de enlace y de la DNS si es innecesario el acceso a internet).
Otro interesante ejemplo nos lo muestra aquí Adrián: se trata de un ejercicio propuesto por Javier sobre las posibilidades de disponer de un router “caro”. Se trata de un espacio de dirección con subredes.
De la misma manera realizamos el ejercicio de un espacio de dirección sin subredes. Y así, modificando la máscara, podemos hacer o deshacer subredes.
Nuevo informe de Adrián al respecto. De forma muy gráfica nos explica cómo cambiar los nombres Net Bios y la dirección IP a través del archivo lmhost.
Después Adrían nos va describiendo los 4 tipos de nodos.
En clase Javier nos puso el siguiente ejercicio: agregamos una dirección en WINS. Nuestra idea es que empela ésta y, el el caso de que no exista, pase a nodo-b. debemos ir a equipo (botón derecho) --- administrar características --- instalar WINS. Luego podemos comprobar en 2Herramientas administrativas” que aparece WINS.
Al hacer ‘getmac/s 192.168.55.217’ obtendremos la dirección Mac de una tarjeta remota.
Con ‘getmac/s 192.168.55.217 | clip’ nos imprime la dirección Mac de una tarjeta remota en el portapapeles.
Este documento de Adrián detalla muy bien los pasos a seguir.
Atención al empleo de ‘ipconfig / registerdns’: se necesita reiniciar el ordenador virtual después de esto.
También se puede hacer ‘dnscnd’ para acceder al entorno de comandos de DNS. Con este ejercicio podemos crear nuestro propio servidor (en una de las ma´quinas virtuales).
En este link Adrián nos enseña nuestro ordenador y el mecanismo de resolución de su DNS. El gráfico es muy clarificador. Con mucho detalle se nos explica el funcionamiento de la caché.
Reflexiones sobre la zona 1 del gráfico (el propio ordenador).
Haciendo ‘nslookup’ llama al mecanismo (completo) de resolución DNS.
Si probamos a borrar la DNS… seguiremos accediendo porque la DNS se guarda en la Host. De esta manera podremos tener una red entre varios ordenadores sin conexión a internet (o controlar los accesos a internet… si quedan en el Host).
Reflexiones sobre la zona 2 del gráfico (fuera del ordenador local).
Se accede a esta zona cuando el ordenador es incapaz de dar respuesta a la búsqueda de una IP. Nota: en los servidores puede haber varias zonas DNS.
Un servidore DNS es “autorizativo” para una zona cuando puede responder en esa zona (esto ya está fuera de nuestro ordenador). Q son las preguntas y A las respuestas.
Si la respuesta no está en nuestro ordenador | à Q2 à | va al servidor DNS | à Q3 à | Se hace una consulta a sus zonas compras.chapuzastel.es 100.90.80.31 |
ß A2 ß | ß A3 ß |
Ahora esta dirección sí se almacenará en la caché del ordenador.
Otro ejemplo: un ordenador pregunta por una web. Va a la caché à va al servidor à va a las zonas à va a la cahé del servidor DNS à llama a otros DNS [Q5] à un DNS responderá (siendo autorizativo) [A3] à se almacena en la caché del servidor DNS [A4] à se almacena esa dirección en el caché de resolución del ordenador [A2].
Reflexiones sobre la zona 3 del gráfico (otros servidores DNS). Explicamos con unos ejemplos. Aparecerán algunos conceptos de interés.
- Otro ordenador (diferente al nuestro) pregunta por una dirección concreta à acabará guardando en la caché del servidor DNS. Si nuestro ordenador pregunta por esa misma dirección… habrá respuesta desde la caché. Cuidado: en el caso de que la web cambia su IP… el DNS contestará erroneamente.
- Cuando un nuevo ordenador es servidor DNS, aparece el siguiente comando: dnscmd.Para obligar al servidor a borrar la caché: /clearcache.
- Otro caso: supongamos que el servidor DNS reside en nuestra empresa (con la dirección 10.10.1.2) è todos los ordenadores de la empresa tendrán esta DNS.
- Archivo de sugerencias de raiz: cache.dns. aquí almacena las IP de todos los ordenadores raiz (por tanto, son direcciones fijas, se actualizan automáticamente – se pueden actualizar a mano-; son víctimas de ciberataques).
- Reenvidores: indican al DNS básico qué DNS debe consultar para reolver. Nos los facilita nuestro ISP o servidor DNS (R, Telefónica…).
Empezamos el mes de agosto. En este documento de Adrián se nos enseña a cambiar una interfaz a través de comandos. Probaremos los comandos:
· ‘netsh’: permite (a través de comandos) acceder a las funciones de red.
· ‘netsh dnscmd’: para los servidores DNS.
· Para cambiar una IPV4 por comandos: netsh interface ip set address “Conexión de área local” (éste es el nombre de la Conexión de Red) static 192.168.55.217 (la IPv4 deseada) 255.255.255.0 (la máscara de subred).
· Comando para cambiar una DNS: netsh interface ip set dnsserver “Conexión de área local” (éste es el nombre de la Conexión de Red) static 192.179.1.100 (la IPv4 deseada).
· Para cambiar una IPV6: netsh interface ipv6 set address “Conexión de área local” (éste es el nombre de la Conexión de Red) static fd00::7 (la IPv6 deseada).
El 28 de julio estuvimos trabajando con IPV4. Gracias a los ejemplos resolvimos los conceptos de máscara de subred, dirección IP y dirección Broadcast. Adrián ha tenido la gentileza de desarrollar toda la sesión en este documento: es muy claro y representa todos los ejercicios de clase.
La sesión del día 29 de agosto la dedicamos a realizar ejercicios de detección de redes. Ya con Virtual PC operativo y las máquinas virtuales con Windows Server 2008 fuimos haciendo distintas pruebas.
- Ejercicio 1. Conectamos las 2 máquinas virtuales a internet en red local, sin IPV6, desastivando Net Bios y con IPV4 señalada por nosotros.
Haciendo “ping” en Símbolo del sistema se nos contesta cuando enviamos la IP del otro equipo. Sin respuesta en el caso del envío del nombre Bios. Probamos que Net Bios sólo actúa dentro de su subred.
- Ejercicio 2. Conectamos las 2 máquinas virtuales a internet en red local, activando IPV6 e IPV4, desabilitado Net Bios y con desactivando la detección de redes. En el link de Adrián se detalla el proceso y las consecuencias.
- Ejercicio 3. Activado IPV4, Net Bios activado, IPV6 desactivado y la detección de redes desactivada.
Hacemos los “ping” correspondientes. Nos quedamos sin contestación para el nombre IPV6 y, además, la red sigue sin funcionar.
- Ejercicio 4. Activado IPV4, Net Bios activado, IPV6 activado y la detección de redes desactivada. En detalle, aquí (otro documento de Adrián).
- Ejercicio 5. Activado IPV4, Net Bios activado, IPV6 activado y la detección de redes activada. Gracias a esto ya podemos ver todos los ordenadores del aula. Más datos: aquí.
- Ejercicio 6. Activado IPV4, Net Bios desactivado, IPV6 desactivado y la detección de redes activada. Al hacer el “ping boston”… ¡Hay contestación! Por regla general, la detección de redes no activa la Net Bios. Puede funcionar en unos ordenadores y en otros no.
- Ejercicio 7. Activado IPV4, Net Bios activado, IPV6 desactivado y la detección de redes activada. Vemos en este documento de Adrián cómo responden los envíos de paquetes.
- Ejercicio 8. Desactivado IPV4, Net Bios desactivado, IPV6 activado y la detección de redes activada. Aquí se nos explica en detalle que, de inicio, nos quedamos sin internet (en España va por IPV4). Si hacemos “ping boston”… ¡Nos contesta IPV6! ¿Por qué?
1. Las direccciones de vículo local son asignadas por Windos.
2. Todas las direcciones de vinculo local empiezan por fe80. Es decir: una LLA (no son enrutables ni salen de la subred a la qu pertenecen).
3. Como las LLA empiezan por fe00, al final añade “%” y un nº… que representa la interfaz de red. De esta manera Windows puede reconocer unas LLA de otras dentro del mismo ordenador.
Llegamos a la siguiente conclusión: para conectar una máquina virtual con otra debemos…
· Tener IPV6 y la detección de redes activada, o
· Tener IPV4 y Net Bios activado.
- Ejercicio 9. Ahora activamos todo. Vemos en detalle en otro archivo de Adrián cómo se contestan entre las máquinas virtuales.
- Ejercicio 10. Quitamos IPV6 (para evitar interferencias). Cambiamos las IPV4 de los ordenadores virtuales de toda la clase: unos poniendo IP 10.10.2.2… y otros 10.10.3.2... Borramos la puerta de enlace. De esta forma nos quedamos divididos en 2 subredes. Sólo podemos ver los de nuestra propia subred.
Conclusión: para tener una red local nos basta con una IP y una máscara de subred (la puerta de enlace y la DNS son prescindibles: sólo necesarias para internet).
- Ejercicio 11. Siguiendo con el ejercicio anterior. Si todos cambiamos la puerta de enlace a 255.255.0.0 ya podemos conectarnos entre todos los ordenadores. Si esta máscara la tuviera el administrador de la red, éste podría ver todos los ordenadores y los demás sólo los de su subred.
Técnicas de identificación de ordenadores en una red. Cómo comparten recursos en IPV4 e IPV6.
Otra sesión de trabajo del día 27 de julio. Actualmente existen 3 técnicas o protocolos:
- Net Bios. Es antigua. Se mantiene por compatibilidad. A cada ordenador le asigna un nombre sin lógica (ni jererquía).
Es un protocolo muy sencillo. Sólo funciona sobre IPV4. Net Bios no sale de la subred a la que pertenece. Si el ordenador que buscamos está en otra subred necesitamos un servidor WINS.
- IPV4. Empieza a estar en deshuso (convivirá muchos años).
- LLMNR. Es el sistema del futuro. Es el equivalente a Net Bios para IPV6.
De forma más gráfica se puede ver en este documento de Adrián.
Sesión de trabajo del día 27 de julio. Comenzamos con el estudio de la generación actual del protocolo TCP/IP: este informe de Adrián es muy descriptivo al respecto. Recurriremos al gráfico de inicio en próximas ocasiones: es muy completo y necesario para tener una visión amplia de todo el protocolo.
Es muy importante conocer la capa de interfaz de red (vemos el caso particular de Ethernet) y el dominio de difusión. Se explica en detalle cómo desea transmitir según el protocolo Ethernet. Se hacen ejercicios para distinguir distintas subredes.
NOTAS:
a) Recordamos que tanto para las redes wifi como para Ethernet se trabaja con direcciones MAC en lugar de con las direcciones IP.
b) TOKEN RING tiene sus propios concentadores. Switch y hub pertenecen a Ethernet.
Vamos a empezar con los objetos contextuales empelando los 2 más sencillos:
BindingManagerBase: administra todos los objetos enlazados en la misma BD. Es una clase abstracta onde no se pueden crear objetos.
BindingContex: administra los BindingManagerBase del formulario. è puede hacer distintos BindingManagerBase en un formulario.
Veremos su uso en el proyecto 040811ADO_Objetos_contextuales.
Como indicaciones, hacemos lo siguiente:
- Agregamos un SQLDataAdapter con esta consulta SELECT CLIENTES.* FROM CLIENTES.
- Agregamos un conjunto de datos en el SqlConection. Nombre, “Datos”. Así tenemos en DataSet (ya automático).
- Ponemos un DataGriedView.
- Sincronizaremos los TextBox con los datos. En la propiedad DataBinding --- otros orígenes.. --- formulario --- tabla “CLIENTES” --- y la selección correspondiente de cada TextBox con el CIF, Nombre y Dirección (los que deseamos conectar). Las demás explicaciones se pueden ver en el formulario.
El pasado día 26 estudiamos cuáles son los TIPOS DIRECCIONES IPv6. Lugo veremos las diferencias con IPV4.
1) LLA (Local Link Address) o direcciones de vínculo local.
- No salen de la subred. Sólo funcionan dentro de una subred.
- No son enrutables. Ni siquiera dentro de la misma LAN o red local
- No pueden salir a internet.
- Las asigna automáticamente Windows.
- Empiezan por fe (nota: a las fec0 les ocurre lo mismo --> son las direcciones de autodesubrimiento de DNS). Terminan en % número (representa el interfaz de red).
2) ULA (Unique Link Address) o enlaces locales únicos.
- Empiezan por fd.
- Son enrutables entre subredes.
- No pueden salir a internet.
- Las configura el administrador.
3) GA (Global Address). También llamadas direcciones globales . Recorren el mundo conectando redes locales.
- El primer segmento va desde 2001 hasta 3FFF.
- Enrutables por Internet.
Nota: todos los rodenadores tienen una dirección ULA y una LLA, como mínimo.
¿Cómo son las direcciones en IPV4? En este documento de Adrián nos explica en detalle la configuración de una red LAN típica, qué es la máscara de subred y cómo se asigna una IP a cada ordenador dentro de una red LAN (3 sencillas reglas).
Siguiendo con nuestro repaso, vamos a hacer breves ejercicios para ver en detalle los objetos de ADO automáticos.
1. DataSet. No se puede borrar. Es dónde están los datos.
2. BindingSource: es un sincronizador. Tiene como origen un DataSet. El DataSet tiene tablas y relaciones (por ej.): debemos indicar en el DataMembrer qué componente del DataSet debemos mostrar (sincronizar, mejor dicho). ¿Qué hace el sincronizador? Al modificar un dato, el sincronizador hace que los elementos enlazados muestren los mismos datos. Si quiero los datos del mismo registro debemos mantener el sincronizador.
En el DataBinding (del TextBox donde aparecen los datos, por ej.) aparece el enlace con la BD correspondiente.
Si mostramos los datos en un DataGried es innecesaria la actualización: se podría borrar (con matices: en el ejercicio 030811Prescindible necesitamos el DataSource).
3. TableAdapter: su función es llenar el DataSet con datos. Igual que hacía el SQLTablaAdapter. Es un componente automático (no aparece en el cuadro de herramientas). El TableAdapter es genérico (sirve para todos: SQL, Oracle…): está limitado a devolver tablas. Et TableAdapter es el que introduce losd atos de una tabla en el DataSet… a través del método Fill [Me.nombre_del_DataSet.nombre_de_la_tabla]. Por tanto el TableAdapter es indispensable (descartamos su eliminación).
4. El TableAdapterManager es poco recomendable crearlo con código. Siempre da funcionalidades extendidas. Siempre asociado a un TableAdapter. TableAdapter o puede guardar datos: para ello necesita al TableAdapterManager ( es decir: actúa con INSERT, UPDATE y DELETE). Se puede borrar si sólo hacemos una consulta.
5. BindingNavigator. En el caso que sea innnecesaria la barra de navegación, podemos eliminarla. Los botones del navegador son editables. El único modificable es el SaveItem.
Proyecto 030811ADOPrescindible.
Añadimos la tabla de clientes de Almacén y vemos que al eliminar el DataSource se hace imposible la conexión.
Vamos a intentarlo resolvar al revés. Vamos al DataGriedView. En su DataSource elegimos “Otros orígenes de datos” y seleccionamos el DataSet del formulario. En ese momento desaparecerá el DataSource del formulario. Luego me voy al DataMember y selecciono la tabla que deseo visualizar.
De esta manera me basta con el DataSet y el TableAdapter.
Proyecto 030811ADOPrescindible2.
Si creamos un DataGriedView debajo de la tabla que hemos agregado. En su DataSource elegimos la relación del bindindSource. En ese momento aparecerán los registros relacionados con la tabla de arriba (“Clientes”): en este caso se trata de la tabla “Pedidos”.
De esta manera deebemos mantener el DataSet, el BindingSource, los TableAdapter correspondientes a cada una de las 2 tablas (las que aparecen en la relación) y el BindingSource de la relación FK.
Proyecto 030811ADOPrescindible3.
Colocamos 3 TextBox y un ComboBox. En éste último vamos a su botón irzdo de la caja y seleccionamos “elementos enlazados a datos”. Gracias a esta operación ya me aparece un DataSet, un TableAdapter y un DataSource.
Ahora voy a cada TextBox y en el Text de su DataBindings seleccionamos una de las columnas que queremos mostrar de la tabla “Clientes”: elegimos CIF, Nombre y Dirección parab cada uno de los 3 TextBox.
De esta manera ya tenemos sincronizados el ComboBox con los TextBox.
Luego probamos los objetos de la colección Me.CLIENTESBindingSource.
En concreto ensayamos con MovePrevious, MoveNext, Find y Filter. Lo hacemos con un botón para cada objeto.
A estas alturas del curso hemos estudiado Bases de Datos, programación orientada a objetos en VISUAL BASIC y hemos empezado a estudiar y manejar ADO. Ahora empezaremos a estudiar redes: con ello nos podremos meter en ASP.NET.
Iremos añadiendo archivos de Adrián que explican muy bien las indicaciones que Javiar nos señala en clase.
Antes de comenzar nos dedicamos a dominar las posibilidades de realizar máquinas virtuales en nuestro ordenador. Gracias a ello se puede ahorrar hardware (podemos emplear 5 máquinas en lugar de adquirir 5 ordenadores). Debemos conocer que un servidor está activo sólo unn 10% de su tiempo. Ello permite emplear esos recursos ociosos. También se puede emplear para realizar particiones de memoria.
Instalamos WMware Server con la ISO de Window Server 2008. Nuestra idea es instalar Windows Server 2008 en esas máquinas virtuales. Acabaremos instalando Virtual PC en lugar de WMware ya que ofrece más garantías.
¿Por qué IPV6? ¿Qué es la DNS? En este documento de Adrián se puede ver en detalle las notas más importantes al respecto. Hemos realizado diversos ejercicios para ver las respuestas de las máquinas creadas al envío de paquetes de información entre unos y otros. Vemos la coexistencia que mantienen IPV4 e IPV6, cómo convivirán durante años (sobre todo en España) y las diferencias de estructura entre ambas.
Necesitaremos conocer qué son los servidores raíz: Adrián nos lo detalla en este otro documento.
Para continuar mejorando en ADO hemos realizado el proyecto 220711ADOInsertar_ Manual_Real: con Odbc tuvimos problemas para dejar el ejercicio más completo (Odbc impide el uso de parámetros). Sólo lo hicimos con una BD de SQL. Se puede ver completo aquí.
Repasamos los temas de ayer enlazando con MySQL. Entre los cambios, también vamos a borrar y modificar registros por una vista además de insertar. Aquí se puede ver completo el proyecto 200711RealADOMySQL. Cada botón ejecutará cada opción.
En este otro ejercicio seguimos trabajando sobre lo mismo. Esta vez, conectaremos con una BD de Acccess a través de ODBC. Ver aquí el Proyecto 200711ADO_TOTAL completo.
Como detalle sí comentamos el empleo del evento RowEnter del DataGridView. De esta forma podremos hacer que aparezcan los datos de cada fila del DataGridView en los TextBox que queramos a medida que pasamos por cada uno de esos datos. Se hace de la forma siguiente (0 y 1 son los datos de cada columna):
tbEditIdAutor.Text = dgvDatos.Rows.Item(e.RowIndex).Cells.Item(0).Value.ToString
tbEditNombre.Text = dgvDatos.Rows.Item(e.RowIndex).Cells.Item(1).Value.ToString
Vamos a continuar profundizando en los temas de ayer. Empezamos con temas de MySQL. Tenemos que descargarlos de la propia web:
- mysql-5.5.14-winx64 (community server: elegimos el de 64 bits).
- mysql-gui-tools-5.0-r17-win32 (el entorno gráfico).
Se pueden ver los pasos más conflictivos aquí.
Tenemos que ir a odbcad32 - Acceso directo para agregar los drivers de MySQL. Si hubiera problemas de desactualización nos obligaría a descargarlos. Tendremos que poner estos datos al agregar: ver aquí. También señalamos los detalles del cambio de conexión al “agregar nuevo origen de datos”.
Sobre los ejercicios de hoy. Veremos el esquema siguiente:
1º, los ob jetos que dependen de la BD empleada:
a.1 Conexión. Ej.: ConexionMySQL.Open()
a.2 Adaptador. Ej.: Dim Adaptador As New MySqlDataAdapter("SELECT * FROM AUTORES", ConexionMySQL)
Después, se ponen los INDEPENDIENTES de la BD.
b.1DataSet. Ej.: Dim Datos As New DataSet + llenado del DataSet: Adaptador.Fill(Datos, "AUTORES")
Ya con el DataSet pueden aparecer otros objetos independientes como:
- Manejador. Ej.: Dim Manejador As New DataViewManager(Datos)
b.100 DataSource y DataMember (ya para publicar los datos):
dgv.DataSource = Datos: dgv.DataMember = "AUTORES"
En el primer proyecto (se puede ver el formulario aquí completo) vamos a conectarnos por NET y por ODBC. Comprobaremos que se hace de la misma forma en un caso y en otro.
Importando la librería correspondiente y abriendo la conexión (con Try), hacemos lo siguiente para mostrar los datos en un DataGriedView (con su cadena de conexión bien declarada en el formulario de diseño):
Dim Adaptador As New MySqlDataAdapter("SELECT * FROM AUTORES", ConexionMySQL)
Dim Datos As New DataSet
Adaptador.Fill(Datos, "AUTORES")
dgv.DataSource = Datos
dgv.DataMember = "AUTORES"
Ya lo hemos visto en otros post: aquí se puede ver de forma más sencilla y clara.
Si la conexión fuera a través de ODBC se haría exactamente igual (sustituimos MySQL por ODBC donde corresponda).
Ya dejando MySQL, nos metimos más en ADO con este otro proyecto. Empezamos a utilizar un Manager con ADO. Para ver el proyecto completo, hacer click aquí: 190711 Forzoso ADO Real Manager.
Veremos de qué manera se peude forzar una conexión a una BD de SQL. En el primer caso, vamos a realizar una búsqueda de clientes de nuestra BD.
Como en el ejercicio anterior, creamos el DataAdapter y el DataSet de igual forma y con la misma selección de datos de la tabla en cuestión. Añadimos lo siguiente con idea de recuperar la clave principal (entre el DataAdapter y el DataSet):
Adaptador.MissingSchemaAction = MissingSchemaAction.AddWithKey
Conociendo la clave principal nos permite realizar búsquedas, inserciones, eliminaciones…
Vamos a probar con una búsqueda a través de un TextBox. Creamos un manejador y ya está:
Dim Manejador As New DataViewManager(Datos)
Manejador.DataViewSettings("Tabla").RowFilter = "NOMBRE LIKE '" + tbConsulta.Text + "%'"
Cerramos la conexión y declaramos el DataSource y el DataMember del DataGriedView.
2º caso del mismo proyecto. Vamos a añadir una fila.
Todo igual que antes hasta:
Adaptador.MissingSchemaAction = MissingSchemaAction.AddWithKey
Dim Comando As New SqlCommandBuilder(Adaptador)
Ahora nuestro Adaptador ya puede emplear Insert, Delete y Update. Creamos el DataSet y vamos a crear una fila de la siguiente manera:
Dim Fila As DataRow = Datos.Tables("Tabla").NewRow
'Obtenemos una nueva fila vacía con la estructura que tendrá esta tabla.
Fila("CIF") = "12312312P": Fila("NOMBRE") = "REINOSA": Fila("DIRECCION") = (etc.)
Ahora añadimos la fila y actualizamos el DataSet (con Try, por seguridad):
Datos.Tables("Tabla").Rows.Add(Fila)
Try
Adaptador.Update(Datos, "Tabla")
'Forzamos al DataSet a aceptar los cambios y grabar en origen.
Datos.AcceptChanges()
Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.Critical, "Conflicto con clave principal")
End Try
Cerramos la conexión y declaramos el DataSource y el DataMember como otras ocasiones.
Caso 3º del mismo proyecto. IMPORTANTE: veremos cómo introducir datos a través de una vista.
Es muy semejante al caso anterior hasta la creación del DataSet. Ahora (por ejemplo) vamos a hacer una vista de los clientes de la provincia de Ourense.
Dim Vista As New DataView(Datos.Tables("Tabla"), "PROVINCIA='OURENSE'",
"NOMBRE ASC", DataViewRowState.CurrentRows)
'Creamos una nueva fila en la vista.
Dim Fila As DataRowView = Vista.AddNew()
Fila("CIF") = "12312312B": Fila("NOMBRE") = "RAMONASA": etc.
'Finalizamos la edición.
Fila.EndEdit()
'Actualizamos el origen de datos.
Adaptador.Update(Datos, "Tabla")
Y terminamos según lo acostumbrado.
Hoy nos hemos dedicado a profundizar en la estructura de ADO. Dominando ADO podremos dominar cualquier estructura de programación: ASP, internet, BD, móviles…
Empezaremos por la estructura más humilde: SQLCONNECTION. Crearemos una BD en Access para demostrar esto y comprar.
En el siguiente documento de Adrián se explica con claridad qué objetos de ADO dependen de la BD y cuáles son independientes. Como veremos los ejercicios, una vez que lleguemos al DataSet (el primer objeto de ADO independiente del origen de los datos) podemos dominar toda la estructura.
Hay que tener cuidado con los controladores de cada BD. Debemos comprobar si en ‘Datos’ del ‘Control de Herramientas’ podemos eleguir esos elementos. En concreto, hoy hemos necesitado descargar los drivers de los controladores de MySQL de la web de MySQL.
Para las conexiones hemos añadido los objetos de las procedencias siguientes:
- ODBC. Sirven para todo. Los MySQL son menos flexibles (por eso hemos tenido que descargar los drivers).
- OleDb. Se emplean para las aplicaciones de Microsoft. Y, en general, para cualquier origen de datos 8como último recurso: siempre empezar con los específicos).
- MySQL. Sólo para MySQL.
- SQL. Hace tiempo que ya los usamos. Ahora veremos que los demás se emplean de la misma manera que éstos.
Los ejercicios de hoy tenía por función estudiar todo esto. En este link se puede ver el primer ejercicio: contiene definiciones muy crecisa sobre el uso de cada objeto de ADO.
El 2º ejercicio. Aquí podemos ver distintas formas de comunicarnos con un determinado origen de datos y empezar a trabajar con el DataSet.
IMPORTANTE: para crear un ODBC debemos crear con anterioridad un DSN apuntando al Origen de datos. Con los demás componentes específicos (OracleConnetion, SqlConnetion…) esto es innecesario. Para poder ver todos los controladores, debemos ir a la carpeta:
C:\Windows\SysWOW64
Allí buscamos el archivo Odbcad32.exe. è agregamos un acceso directo. Una vez abierto podemos apuntar a la DSN del sistema (podríamos elegir la de un usuario concreto, por ejemplo). Lo hacemos de esta manera:
---> Agregar ----- Microsoft Access Driver
---- Nombre del origen de datos.
---- seleccionar (buscamos la tabla deseada de Access en la carpeta Users)
En el último ejercicio,añadimos 3 DataDridView y conectaremos con todos a la vez de forma muy sencilla. Lo vemos aquí mismo:
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'Creo un DataSet.
Dim Datos As New DataSet
SqlDataAdapter1.Fill(Datos, "Clientes")
OleDbDataAdapter1.Fill(Datos, "Autores")
OdbcDataAdapter1.Fill(Datos, "Editoriales")
dgv1.DataSource = Datos : dgv1.DataMember = "Clientes"
dgv2.DataSource = Datos : dgv2.DataMember = "Autores"
dgv3.DataSource = Datos : dgv3.DataMember = "Editoriales"
End Sub
End Class
Comprobamos que en automático el propio VISUAL abre y cierra la conexión. Además, vemos que al agregar un SqlDataAdapeter(por ejemplo), ya aparecerá un SqlConnetion (está por debajo del SqlDatAdapter).
Se comprueba que de forma muy sencilla podemos exponer los datos de 3 orígeens diferentes en el mismo DataSet.
Hoy hemos estudiado los tipos de archivos más comunes y cómo poder controlarlos desde el VISUAL.
En el proyecto vamos añadiendo botones y comprobamos cómo son los atributos de un archivo, de una carpeta y de la unidad de disco.
En el siguiente link se puede ver en detalle y con claridad. La apariencia es de ser un archivo muy largo: más bien es monótono ya que podemos mensajes para cada tipo de archivo. Es sencillo. Ver AQUÍ.
Como hemos estado trabajando diferentes temas a medida que avanzamos en los proyectos de gestión largos (GESTOCK2 y 130711FINAL), intentaremos añadir temas con liks desde Google Doc o en otra ayuda auxiliar al blog.
Hoy regresamos al SQL SERVER. Creamos una nueva tabla con 4 disparadores:
- Para eliminar clientes (un AFTER DELETE).
- Para modificar datos de clientes (con AFTER UPDATE).
- Para insertar clientes (con INSERT): en este caso queremos evitar que se repitan valores (como el CIF) que sin ser clave. Un INSTEAD OF INSERT. Un ejemplo de cómo se hace uno, ver aquí o en este otro.
- Otro que compruebe que el cliente está en la tabla de pedidos (queremos evitar la eliminación de clientes con pedidos asociados). Con INSTEAD OF DELETE.
Otros archivos subidos a GoogleDocs para el repaso:
https://docs.google.com/document/d/1ADiIx2txlEj5F9A8AXGiOnX8epp8F28fR-FWvQjdfko/edit?hl=es
https://docs.google.com/document/d/1JMZPOLMkk2Yw1cTJbMBGOi2iJKyegusIU0ssgJkplV8/edit?hl=es
https://docs.google.com/document/d/1mawKxCwOhlquFAIeod2Ud2rkaF457n6ZDX6WOad7Zy0/edit?hl=en_US
Después hemos comprobado su funcionamiento con este proyecto del VISUAL.
Un tema mportante es SERIALIZAR: se trata de convertir un objeto en flujo de bytes susceptible de ser guardados. Por tanto, DESERIALIZAR será convertir el flujo de datos en objeto de la clase.
Curiosidad: el sistema de archivo directo sólo funciona en el Visual 2010. Serializar funciona en 2008 y 2010.
Podemos ver más en: http://msdn.microsoft.com/es-es/library/aa984468(v=vs.71).aspx
Otro link interesante (un poco más detallado) es el siguiente: http://web1.taringa.net/posts/info/4250633.R/Serializacion-de-objetos-_Programacion_.html
Creamos una clase Persona en un módulo, como otras veces.
Aquí vamos a importar al principio del formulario. Vemos cómo serializar y deserializar:
Imports System.IO
Imports System.Runtime.Serialization.Formatters.Binary
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim p As New Persona("Pepe", 30)
Dim p2 As New Persona("Juan", 23)
Dim p3 As New Persona("Luis", 34)
'Crea un archivo y lo asocia a Archivo.
Dim Archivo As Stream = File.Create("C:\ARCHIVOS\Data1.dat") 'Con Create reescribirá encima del archivo.
Dim Serializador As New BinaryFormatter() 'Creamos el serializador.
'Gracias al serializador guardaremos el objeto en el archivo.
Serializador.Serialize(Archivo, p)
Serializador.Serialize(Archivo, p2)
Serializador.Serialize(Archivo, p3)
'Cerramos el flujo asociado al archivo.
Archivo.Close()
Archivo.Dispose()
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
'Ahora vamos a DESERIALIZAR.
'Creamos un flujo y lo asociamos a Data.dat
Dim Archivo As Stream = File.OpenRead("C:\ARCHIVOS\Data1.dat") 'Con Create reescribirá encima del archivo.
Dim Deserializador As New BinaryFormatter() 'Creamos el deserializador.
'Declaramos un objeto del tipo Persona.
Dim p As Persona
'Leemos p a través del deserializador y lo convertimos en tipo Persona.
p = CType(Deserializador.Deserialize(Archivo), Persona)
'Mostramos los datos de p.
MsgBox("Nombre: " + p.Nombre + " ; Edad: " + CStr(p.Edad))
Archivo.Close()
Archivo.Dispose()
End Sub
End Class
En la clase del lunes hemos trabajado con las funciones de registro para controlar los archivos. El otro día ya habíamos planteado trabajar con ARCHIVOS BINARIOS. Este link de Microsoft puede ser ilustrativo: http://msdn.microsoft.com/es-es/library/9tk3bdxw.aspx
1. Primeramente, aprendemos a cargar (abrir) archivos con FileSystem. En este caso, abriremos una imagen:
Dim bytes = My.Computer.FileSystem.ReadAllBytes(My.Computer.FileSystem.SpecialDirectories.MyPictures + "\Tulips.jpg")
'Ahora indicamos al PictureBox que cargue esos bytes desde la memoria con IO.MemoryStream: es un flujo de memoria.
pbImagen.Image = Image.FromStream(New IO.MemoryStream(bytes))
Así de sencillo. Si empleamos ReadAllText podríamos abrir cualquier archivo de texto. Ene se caso hay que indicarle la codificación de propio texto:
My.Computer.FileSystem.ReadAllText("C:\ARCHIVOS\Contenido.txt", System.Text.Encoding.Default)
El otro método es con System.IO. El otro día vimos cómo hacerlo (con Imports; en este ejemplo vamos a direccionarlo):
Dim Archivo As New System.IO.StreamReader("C:\ARCHIVOS\Contenido.txt", System.Text.Encoding.Default)
'Esto es un ejemplo de lectura de una sola vez. Con ReadToEnd lee todo hasta <eOF> (el final).
Dim Contenido As String = Archivo.ReadToEnd()
'Lo mostramos.
tbTexto.Text = Contenido
Archivo.Close() ' Se cierra el flujo.
Archivo.Dispose() 'Se libera la memoria.
Como caso particular, podemos hacer un ejemplo de lectura por líneas de texto. Sería como antes, en lugar del ReadToEnd:
Do While Archivo.EndOfStream <> True
'Añade una línea del archivo a tbTexto. Ojo: Readline() no incorpora el final de línea.
tbTexto.Text = tbTexto.Text + Archivo.ReadLine() + vbCrLf
Loop
Leyendo por caracteres sería así, sustiyendo esto en el anterior:
tbTexto.Text = tbTexto.Text + Chr(Archivo.Read())
2. Para guardar archivos binarios… Muy sencillo también. Veamos este ejemplo de guardar un Array de 6 items.
Dim Datos() As Byte = {10, 20, 30, 40, 50, 60} My.Computer.FileSystem.WriteAllBytes("C:\ARCHIVOS\Datos.dat", Datos, False)
'NOTA: con bytes funciona siempre. Si hay problemas, mal asunto.
Un nuevo ejercicio de Objetos. Consiste en: usando Objetos y sobrecarga de métodos y operadores, hacer un programa que guarde los datos de varias personas (FASE 1). Se podrá buscar personas por Nif y Nombre. Novedad: los datos de las personas se podrán guardar en un archivo. También tendrá una opción de recuperar esos datos (se pueden guardar en un archivo binario o de texto) (FASE 2). La lógica del contenido se meterá dentro de una clase. Así será independiente del formulario y se puede emplear para otras necesidades (FASE 3).
La FASE 1 se hace como otras veces. Creamos un ArrayList como hace unos días. Las otras fase sí necesitremos esta ayuda.
Para guardar los datos en un archivo meteremos un MenuStrip en el formulario (con Abrir, Guardar…). También tendremos que meter un OpenFileDiagog (ofd) y un SaveFileDialog (sfd). Así aparece en el botón “Guardar”.
'Así guardará los datos en el Escritorio. Podría ser en MyDocuments, etc.
sfd.InitialDirectory = My.Computer.FileSystem.SpecialDirectories.Desktop
'Guarda todos los registros de la colección en un archivo.
sfd.ShowDialog() 'Abre el control de guardar archivo.
'Si deseamos calcelar, hacemos lo siguiente. El cancel directo funciona mal.
If sfd.ShowDialog = Windows.Forms.DialogResult.Cancel Then
Exit Sub 'Se calcela y termina.
End If
'PASOS PARA GUARDAR UN ARCHIVO. Pasos:
' 1. Se crea un flujo de escritura asociado al archivo.
' IMPORTANTE: tiene un 2º parámetro que puede valer True o False. Se presupone False. Con True, si no existe archivo, se creará; si existe, se añadirán datos al final. Si es False, exista archivo o no, se crea uno nuevo y se pierde su contenido previo.
' Recibe como parámetro la ruta del archivo.
Dim Archivo As New StreamWriter(sfd.FileName)
'Para probar el TRUE. Quitaríamos el ShowDialog para que sobreescriba (con False) o añada datos (con True).
'Dim Archivo As New StreamWriter("C:\datos.txt", True)
'Nota: Si al principio, evitamos poner el Imports System.IO, aquí deberíamos poner: Dim Archivo As New System.IO.StreamWriter(sfd.FileName)
' 2. Ahora recorremos los Item de la coelcción y los guardamos en el archivo.
For Each p In Personas
'Escribimos cada campo de una persona como una línea de texto en el archvo.
'Nuestro FLUJO se llama... Archivo
Archivo.WriteLine(p.nif)
'NOTA: Si ponemos Write simplemente, los agregará en el archivo de forma consecutiva: esto posiblemente producirá errores ya que confundiría unos datos con otros.
Archivo.WriteLine(p.Nombre)
Archivo.WriteLine(CStr(p.Edad))
Next
' 3. Se cierra el Archivo.
Archivo.Close()
' 4. Se libera el DTA (memoria RAM que consume) del Archivo.
Archivo.Dispose()
'COMENTARIO: Marcas que son invisibles en un archivo de texto:
' Cuando se hace un fin de línea = <EOL>
' <EOF> = Fin de archivo
End Sub
Para el botón “Abrir” (para abrir un archivo creado con anterioridad) ponemos:
ofd.InitialDirectory = My.Computer.FileSystem.SpecialDirectories.Desktop
ofd.ShowDialog()
Dim Archivo As New System.IO.StreamReader(ofd.FileName)
Dim Contenido As String = Archivo.ReadToEnd()
MsgBox(Contenido)
Archivo.Close()
Archivo.Dispose()
Si en el MenuStrip metemos el botón “Abrir la colección”, metemos lo mismo. Emplearemos 2 técnicas (después del FileName y antes del Close):
1ª técnica:
'Ahora borro la colección.
Personas.Clear()
Dim Linea As String
Linea = Archivo.ReadLine()
'Hacer Hasta Linea vale Nothing. Cuando Linea vale Nothing, termina.
Do Until Linea Is Nothing 'Lee linea antes del bucle.
MsgBox(Linea)
Linea = Archivo.ReadLine() 'Lee la siguiente Linea.
' A esta técnica se le llama LECTURA ADELANTADA.
Loop
La otra técnica es así:
Do While Archivo.EndOfStream <> True ' LECTURA RETRASADA.
'MsgBox(Archivo.ReadLine(), Archivo.ReadLine(), CByte(Archivo.ReadLine())) 'Para probar.
Personas.Add(New Persona(Archivo.ReadLine(), Archivo.ReadLine(), CByte(Archivo.ReadLine())))
Loop
'Otra técnica: LECTURA RETRASADA. EndOfStream retorna True cuando llega al final del archivo.
'Do While Archivo.EndOfStream <> True ' "Hacer Mientras no llegue al final del archivo".
' Linea = Archivo.ReadLine()
' MsgBox(Linea)
'Loop
Hoy nos dedicamos a “dar de alta productos”. Problema: está del lado N de 3 tablas è hay 3 claves foráneas que necesita conocer la persona que da de alta a los artículos.
Creamos 3 ComboBox para esas claves foráneas.
à Flecha – “usar elementos enlazados a datos”.
à buscamos la tabla de la que procede (“Categoria”, por ej.) --- aparece su BindingSource.
à en “mostrar miembro”, ponemos “Descripción”, por ejemplo.
à en “miembro valor”, ponemos MargenID, que es el dato que se necesita guardar.
Para los textbox de los datos de entrada de los productos, se mete el SQLDataAdapter. Con el botón de “Alta”, se pondría lo siguiente (con pocas variantes a los que hemos hecho estos días: con los ComboBox, básicamente):
If Me.tbCodigo.Text.Trim.Length <> 6 Then
MsgBox("Error nº de código")
tbCodigo.Focus()
Exit Sub
End If
Try
Dim Datos As New DataSet
'Llenamos el DataSet con los dtos.
Adaptador.Fill(Datos, "PRODUCTOS")
'Creamos una fila a partir de la tabla.
Dim Fila As DataRow = Datos.Tables("PRODUCTOS").NewRow
Fila("CODIGO") = (tbCodigo.Text)
Fila("NOMBRE_PRODUCTO") = tbNombre.Text
Fila("DESCRIPCION_PRODUCTO") = tbDescripcion.Text
Fila("PRESENTACION") = tbPresentacion.Text
Fila("PESO") = CDbl(tbPeso.Text)
Fila("COSTE") = CType(tbCoste.Text, System.Decimal)
Fila("MARGENID") = CInt(Me.cbMargen.SelectedValue)
Fila("CATEGORIAID") = CInt(Me.cbCategoria.SelectedValue)
Fila("STOCKMINIMOID") = CInt(Me.cbStockMinimo.SelectedValue)
Fila.EndEdit()
' Insertamos la nueva fila
Datos.Tables("PRODUCTOS").Rows.Add(Fila)
' Actualizamos el DataSet a través del Adaptador
Adaptador.Update(Datos, "PRODUCTOS")
' Forzamos al DataSet a aceptar los cambios
Datos.AcceptChanges()
'Mensaje de todo OK.
MsgBox("Alta procesada correctamente", MsgBoxStyle.Information, "Alta Producto")
Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.Critical, "Error al insertar")
End Try
End Sub
End Class
El ejercicio de objetos de hoy fue para practicar la creación de formularios y objetos con código.
Los objetos y formularios que hemos creado son PARTIAL: es una clase particular. Es decir: puede funcionar como objeto o como clase (en Java esto es imposible). Hace que Form1 se comporte como clase o como objeto (por ej.).
NOTA IMPORTANTE: Los componentes siempre son objetos (nunca pueden ser Partial).
De forma resumida se puede ver aquí:
'Ahora trato la clase Prueba como objeto.
Prueba.Text = "Sigo estando hermanado"
Prueba.StartPosition = FormStartPosition.Manual
Prueba.Location = New Point(50, 50)
Prueba.Show()
'Ahora trato Prueba como clase. Vamos a clonar las ventanas del formulario.
Dim p1 As New Prueba '¡Se comporta como una clase!.
Dim p2 As New Prueba
Dim p3 As New Prueba
p1.Show() : p2.Show() : p3.Show() 'Así está clonado el formulario.
Comenzamos con un ejercicio de objetos. Hacer un programa para dar de alta un paciente cuando llega al médico (datos: nombre, NSS y hora de llegada). En otra zona del formulario, aparecen los datos del paciente y el médico le da al botón de “atender”. Los pacientes vienen en una cola (queue): el 1º en llegar será el 1º en ser atendido.
En el formulario:
Public Class Form1
Private Cola As New Queue(Of Paciente) '(Of Paciente) se puede evitar el ponerlo.
'Contendrá sólo objetos de la clase Paciente.
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
'Inserta un paciente en la cola de espera.
Dim p As New Paciente(tbInsertarNombre.Text, tbInsertarNSS.Text, CDate(tbInsertarHora.Text))
'Inserta al final de la cola.
Cola.Enqueue(p)
tbInsertarNombre.Clear() : tbInsertarNSS.Clear() : tbInsertarHora.Clear()
tbInsertarNombre.Focus()
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
'Si la cola está vacía....
If Cola.Count = 0 Then
MsgBox("No hay pacientes para atender", MsgBoxStyle.Information, "Cola de espera")
Exit Sub
End If
'Extrae al paciente al frente de la cola.
Dim p As Paciente = Cola.Dequeue()
'Vuelco los datos del paciente.
tbAtenderNombre.Text = p.Nombre : tbAtenderNSS.Text = p.NSS : tbAtenderHora.Text = p.Horallegada
End Sub
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
tbInsertarHora.Text = CStr(dtpHora.Value)
End Sub
End Class
Como se puede ver, también hemos practicado con el DateTimePicker.
En el módulo, creamos la clase “Paciente” (similar a la clase “Persona” de otra ocasiones).
Otro ejemplo de cola. Esta vez… UNA PILA. Pondremos STACK en lugar de QUEUE.
Con respecto al ejercicio anterior, son éstos los cambios:
Pila.Push(c) ‘Push es quien inserta al pricipio de la pila.
-----------------
Dim c As Contenedor = Pila.Pop() 'Extrae al contenedor del principio de la pila.
El resto de la mañana repasamos temas de ADO.NET. Me permito señalarlo ya que éste sería el primer post sobre ADO.
En nuestro proyecto GESTOCK hacemos el siguiente ejercicio:
Por el método semi-automático (que es el más usado), dar de alta a un proveedor. Lo hemos realizado en uno de los ejercicios de ADO (ver proyecto ADO 11).
Hemos tenido que crear un sQLDataAdapter (ene ste caso, de la tabla de “Proveedores”, como se verá en los comentarios del ejercicio.
En el formulario que creamos aparecerá:
Public Class frmAltaProveedor
'DE FORMA SEMI-AUTOMÁTICA. Posiblemente, el más usado.
'Cuando hay problemas, recurrimos a los comandos y siempre funcionará.
Private Sub bkAlta_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bkAlta.Click
Try
'Creamos un DataSet.
Dim Datos As New DataSet
'Llenamos el DataSet con los dtos.
Adaptador.Fill(Datos, "PROVEEDORES")
'Creamos una fila a partir de la tabla.
Dim Fila As DataRow = Datos.Tables("PROVEEDORES").NewRow
Fila("PROVEEDORID") = CInt(tbCodigo.Text)
Fila("NOMBRE_PROVEEDOR") = tbNombre.Text
Fila("CIF") = tbCif.Text
Fila.EndEdit()
' Insertamos la nueva fila
Datos.Tables("PROVEEDORES").Rows.Add(Fila)
' Actualizamos el DataSet a través del Adaptador
Adaptador.Update(Datos, "PROVEEDORES")
' Forzamos al DataSet a aceptar los cambios
Datos.AcceptChanges()
'Mensaje de todo OK.
MsgBox("Alta procesada correctamente", MsgBoxStyle.Information, "Alta Proveedor")
Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.Critical, "Error al insertar")
End Try
End Sub
End Class