Guía I Preparar SQL Server con BBDD de ejemplo Índice 1 Introducción...2 2 Instalar SQL Server Management Studio Express...2 3 Incluir la base de datos NorthwindCS...8 Datos de conexión a nuestro servidor...9 4 Crear nuestra primera aplicación de acceso a datos con ayuda del diseñador...15 Asistente para la configuración de orígenes de datos...17 Cadena de conexión...18 Proveedor de datos...18 Objetos de la Base de Datos...22 DataSet...26 TableAdapter...26 TableAdapterManager...26 BindingSource...26 BindignNavigator...27 Excepciones...28 Fill...29 Update...29 EndEdit...30 RejectChanges...31 Rejilla de datos...31 5 Crear nuestra segunda aplicación de acceso a datos con ayuda del diseñador...31 1
1 Introducción. En esta guía, veremos cómo instalar la herramienta de administración visual de SQL Server y cómo utilizarla para ejecutar consultas sobre el motor de Bases de Datos (BBDD). Durante la instalación de Visual Studio.NET se instaló también el motor de bases de datos SQL Server 2008, junto con una herramienta que nos permite configurar su comportamiento: Se trata del motor SQL Server 2008 en su versión Express con la herramienta Administración de configuración de SQL Server y el asistente Configuración de SQL Server. La configuración por defecto con la que se ha instalado este motor de BBDD, nos permitirá que podamos conectarnos a él de forma local (sólo permite conexiones de programas en nuestro equipo -sólo tiene activado el protocolo de comunicación 'Memoria compartida'-); por ahora, eso es suficiente para empezar a crear nuestras aplicaciones de acceso a datos. 2 Instalar SQL Server Management Studio Express. El motor, está instalado y funcionando (está configurado para iniciarse al arrancar nuestra máquina); pero no contiene ninguna base de datos (BD). Bueno, en realidad, sí que contiene algunas BBDD, pero son las que utiliza el propio motor para guardar su información interna, necesaria para su funcionamiento (usuarios, permisos, BBDD, ). Para crear nuestras BBDD para comenzar con nuestros ejemplos, necesitaremos instalar una herramienta que nos permita 'administrar' SQL Server, que nos permita crear nuevas BBDD, lanzar consultas a BBDD, crear nuevos usuarios,... Por supuesto, todo esto se puede hacer en modo comando, pero para nosotros/as será más cómodo hacerlo utilizando una herramienta visual, utilizaremos el SQL Server Management Studio Express. Este herramienta se puede descargar gratuitamente de la página de 2
Microsoft. Pasos a seguir para la instalación: P1. Descargar el instalador de la herramienta desde esta página: http://www.microsoft.com/downloads/es-es/details.aspx?familyid=08e52ac2-1d62-45f69a4a-4b76a8564a2b&displaylang=es Podremos elegir entre la versión para 32 o 64 bits con un tamaño de unos 200 MB para la versión SQL Server 2008 Express. (Aunque tu equipo sea de 64 bits, lo más probable, es que el motor SQL Server Express que tengas instalado sea x86, por lo que tendrás que descargar la versión de 32 bits - x86). P2. Instalaremos la aplicación: Microsoft ha cambiado un poco los pasos de instalación de esta herramienta, y al hacer doble clic sobre el paquete que te descargas, lo que te abre, es el centro de instalación de SQL Server. Y, tiene este aspecto: En esta herramienta, seleccionamos Instalación. 3
Haremos clic, sobre la primera opción: Nueva instalación independiente de SQL Server o agregar características a una instalación existente. 4
En el caso de el equipo en el que he realizado las capturas, el sistema operativo, es un Windows XP, por lo que no tiene instalada la herramienta PowerShell de Microsoft (en Windows 7 ya no tendremos este problema). Si nos encontramos en esta misma situación, podremos descargar PowerShell desde esta url http://www.microsoft.com/downloads/es-es/details.aspx?familyid=60cb5b6c6532-45e0-ab0f-a94ae9ababf5&displaylang=es. Solucionado el problema, podemos continuar con la instalación. En los siguientes pasos, el instalador, nos preguntará si queremos añadir una característica nueva (ojo, que en este paso, el asistente nos lleva a confusión). Seleccionaremos Realizar una nueva instalación de SQL Server. Sino, no podremos agregar SQL Server Management. 5
6
Una vez que hayamos instalado la herramienta, podemos utilizarla para conectarnos a servidores SQL Server Express y realizar tareas administrativas en él. Windows Todos los Programas Microsoft SQL Server 2008 SQL Server Management Studio. 7
3 Incluir la base de datos NorthwindCS. En es apartado, veremos cómo crear una nueva BD y ejecutar un script sql sobre ella. Crearemos una BD llamada NorthwindCS y ejecutaremos un script SQL que creará todo su contenido, incluyendo distintas tablas y datos de ejemplo en ellas. P1. Descargamos el es script SQL de la BD de ejemplo NorthwindCS. http://www.iesalandalus.org/moodle/mod/resource/view.php?id=17056 El archivo que se va a descargar, es un archivo de extensión.sql P2. El navegador nos preguntará si queremos guardar el archivo o abrirlo con la herramienta de administración. Podemos decirle que lo abra con la herramienta. Si preferimos guardarlo, podemos arrancar SQL Management y, sin necesidad de estar conectados a ningún servidor, seleccionar: menú Archivo Abrir Archivo... 8
De cualquiera de las dos formas, la herramienta, nos pedirá los datos para conectarnos al servidor. P3. Datos de conexión a nuestro servidor local: Para poder conectarnos a un servidor, necesitamos especificar el nombre o ip del equipo servidor (en mi caso es JAM porque es así como se llama mi PC); y el puerto por el que estará escuchando el servidor. Esto es lo común, pero en nuestro caso, nos vamos a comunicar con nuestro servidor utilizando memoria compartida, así que como Nombre del servidor, podemos utilizar: Nombre de servidor = localhost\sqlexpress localhost para indicar el nombre del equipo local. Y, \SQLExpress se debe a que el servidor SQL Server gestiona instancias con nombre 1 y la instancia por defecto de SQL Server Express se llama SQLExpress. En cuanto a la autenticación, tenemos dos posibilidades: Autenticación de Windows y Autenticación de SQL Server. Al utilizar Autenticación de Windows, dejamos que el sistema permita que se conecten al servidor aquellos/as usuarios/as que se han logueado correctamente en el sistema (máquina o dominio de Windows), por o que no será necesario incluir los datos del usuario y password (el usuario los ha dado para poder entrar en el sistema). Cuando utilicemos Autenticación de SQL Server, será el motor el que gestione si el usuario y password que deberemos suministrar, permiten la conexión al servidor y a qué recursos de éste. 1 Para ampliar información sobre Instancias en SQL Server http://msdn.microsoft.com/eses/library/ms143531.aspx 9
En nuestro caso, utilizaremos Autentificación = Autentificación de Windows; ya que la configuración actual es la configuración por defecto de SQL Express y permite las conexiones en local a todos/as los/as usuarios/as de la máquina. Damos esos datos y hacemos clic en Conectar. P4. Tendremos cargado el script SQL, pero, no podremos ver el resultado en el Explorador de objetos: Explorador de objetos Para poder ver los resultados, conectaremos a un servidor el Explorador de objetos: 10
Para conectarse volverá a pedirnos los datos del apartado P3. Una vez conectados/as, veremos el contenido actual del servidor: 11
P5. Como el script SQL utiliza una BD llamada NorthwindCS, tendremos que crearla antes de ejecutar el script. Para ello, haremos clic con el botón secundario del ratón sobre la carpeta Bases de Datos y pincharmos sobre Nueva base de datos... Nota: la creación de la BD también se puede incluir en el script, pero lo veremos más adelante. P6. En el siguiente cuadro de diálogo, escribiremos como Nombre de la base de datos: NorthwindCS. Y haremos clic sobre Aceptar (por ahora no es necesario configurar nada más). 12
Tardará un poquito en crear la BD. P7. A continuación, ejecutaremos el script: 13
Cuando termine la ejecución del script, nos indicará si todo ha ido bien o no. El script creará todo el contenido de la BD. Además, también podremos utilizarlo para machacar todos los cambios que hayamos hecho en la BD después de hacer varias pruebas, volviendo a ejecutar el script. 14
4 Crear nuestra primera aplicación de acceso a datos con ayuda del diseñador. Ahora disponemos de una BD con la que poder trabajar en nuestro servidor. Veamos cómo el diseñador de Visual Studio puede ayudarnos a crear rápidamente formularios que 'atacan' esa BD. Comenzaremos con un ejemplo en el que vamos a crear una aplicación que consta de un sólo formulario con el que podremos acceder a todos los registros de la tabla Productos de la BD (la tabla se llama Products). Además, los datos se mostrarán como un listado (rejilla) utilizando un control de tipo DataGridView. Para conseguirlo, sólo tendremos que crear un nuevo origen de datos para la aplicación con la BD y tabla correspondiente; y después arrastraremos esa tabla desde el origen de datos a nuestro formulario. Así, el diseñador hará todo el trabajo por nosotros/as. Obtendremos un formulario con el que podremos ver los datos, modificarlos, añadir nuevos productos y borrarlos. Veamos paso a paso qué tendríamos que hacer: P1. Creamos una nueva aplicación de tipo Windows Form: 15
Yo voy a llamarla BBDD_Ej1. También cambiaré el nombre y el título del formulario creado por defecto. P2. Creamos un nuevo origen de datos. Para ello, utilizaremos la pestaña Orígenes de datos. Esta pestaña normalmente se encuentra debajo del Explorador de 16
Soluciones. Si no es así, la podemos mostrar con la opción de menú Datos Mostrar orígenes de datos (Mayús. + Alt + D). P3. Hacemos clic en el enlace Agregar nuevo origen de datos... o en el botón en Orígenes de datos. Se nos abrirá el Asistente para la configuración de orígenes de datos: 17
Los posibles orígenes de datos que podemos tener son: Base de datos: Nos permitirá conectarnos a una BD y elegir los objetos a los que queremos acceder. Servicio: Nos permite agregar a nuestra aplicación una conexión a un servicio (local o de red) que proporcione datos de la aplicación. Objeto: Nos permite elegir un objeto que tengamos implementado (o exista) para después generar controles enlazados a sus datos. Seleccionaremos BD, ya que lo que queremos es conectarnos a una BD; y, haremos clic en Siguiente >. P4. A continuación pasamos a configurar nuestra Conexión de datos. O, lo que es lo mismo a crear la Cadena de conexión (o ConnectionString) que utilizará nuestra aplicación para conectarse al motor de BBDD. En este paso, pinchamos sobre Nuevo conexión... A continuación, el asistente nos preguntará el tipo de BD a la que queremos conectarnos: Access, Oracle, SQL Server, Estas son las opciones por defecto, para nuestro ejemplo es suficiente, ya que seleccionaremos Microsoft SQL Server; pero, si necesitamos conectarnos a una BD de un servidor de tipo (MySQL, PostgreSQL, ) debemos previamente instalar en nuestro equipo el correspondiente Proveedor de datos (Data Provider). Por ejemplo, el proveedor de datos para aplicaciones.net que accedan a BBDD PostgreSQL lo podemos descargar de esta página: (Npgsql -.Net Data Provider for PostgreSQL) http://npgsql.projects.postgresql.org/. El caso de MySQL nos ofrece más posibilidades, desde esta página: (MySQL Connectors) http://www.mysql.com/products/connector/. Para nuestras aplicaciones.net, 18
podríamos utilizar tanto ADO. NET Driver for MySQL (Connector/NET) como, ODBC Driver for MySQL (Connector/ODBC). No nos hagamos un lío con esto de proveedores, conectores o drivers; son lo mismo, un conjunto de librerías que saben cómo comunicarse con cada motor de BBDD en particular. Volviendo a nuestro ejemplo: seleccionaremos Microsoft SQL Server (con lo que seleccionaremos un proveedor de datos que ya está instalado en la máquina y que nos permitirá comunicarnos con cualquier motor de datos de tipo SQL Server, llamado SQL Native Client); y continuamos. A continuación, nos pide los datos específicos de conexión a nuestro servidor (como nos pasaba para poder ejecutar el script SQL que crea NorthwindCS). Así, que como ya sabemos, el nombre de nuestro servidor es localhost\sqlexpress, y seleccionaremos Usar autenticación de Windows en Conexión con el servidor (-ve a al página 6 de este documento para una explicación más detallada de estos parámetros-). 19
Además, de entre las BBDD a las que tendremos acceso, seleccionamos aquella con la que queremos trabajar: NortwindCS. También podemos hacer clic en Probar conexión, para comprobar que toda la configuración es correcta. Nota: Realmente nuestro equipo se llamará de otra forma (PEARL o JAM, en mi caso), pero localhost nuestras ya es que más así aplicaciones cómodo podremos de utilizar llevar prueba y ejercicios a cualquier equipo: clase, casa, portátil,...; sin tener que modificar los datos de la conexión. Por supuesto, nombre del servidor, sí será sólo uno cuando nuestra aplicación sea una versión definitiva y todas las instalaciones en distintos equipos accedan a un sólo servidor, pero este no es al caso ahora. 20
Ya tenemos nuestra conexión configurada. Hacemos clic en Aceptar. Realmente, nuestras cadenas de conexión, siempre van a ser como la cadena de texto que está seleccionada en la imagen de arriba. Así: Data Source=localhost\SQLEXPRESS;Initial Catalog=NorthwindCS;Integrated Security=True Data Source=<NombreDelServidor>;Initial Catalog=<NombreDeLaBD>;<DatosParaLaAutenticación> Siempre será, PalabraClave1=valor;PalabraClave2=valor;... En la imagen anterior, hacemos clic en Siguiente>. P5. En este paso, nos está preguntando si queremos guardar la cadena de conexión que acabamos de configurar en el archivo de configuración de nuestra aplicación; y además, qué nombre queremos ponerle. Guardar nuestra cadena de conexión en el fichero de configuración de la aplicación, tiene más implicaciones que os comentaré en posteriores guías, pero para este ejemplo, seleccionaremos que sí; y ese nombre por defecto también nos sirve. Así, que haremos clic en Siguiente>. 21
La cadena de conexión NorthwindCSConnectionString, la tendremos accesible desde cualquier sitio de nuestra aplicación y siempre que la utilicemos estaremos haciendo referencia a una string con valor: Data Source=localhost\SQLEXPRESS;Initial Catalog=NorthwindCS;Integrated Security=True P5. Lo siguiente que va a hacer el Asistente por nosotros/as, es conectarse a la BD, y traernos un esquema de todos los objetos que contiene: Como vemos, nos los muestra ordenados según el tipo de objeto: Tablas. Se corresponde con las tablas de la BD. Al desplegar esta categoría 22
veremos un listado de todas las tablas de la BD y dentro de cada una de ellas, sus campos. Seleccionaremos aquellas tablas y campos que necesitemos incluir en nuestro formulario. Al utilizar una tabla, el motor nos devuelve una copia de los datos que contiene en ese momento la tabla en la BD. Vistas. Una vista, es el resultado de una consulta SQL. Aunque cuando utilizamos una vista en nuestras aplicaciones veamos un conjunto de registros y campos como sucede con las tablas, la diferencia es que en la BD no existe la vista, sino, la consulta SQL que la genera. Si al utilizar una tabla, el motor nos devuelve todos los datos que contiene esa tabla en ese instante; al utilizar una vista, el motor ejecuta la consulta asociada a ella y nos devuelve el resultado. También, podremos necesitar todos o algunos de los campos de una vista, como nos sucede con las tablas. Procedimientos almacenados. Al igual que los procedimientos en otros lenguajes de programación, los procedimientos almacenados de Microsoft SQL Server se pueden utilizar para: Aceptar parámetros de entrada y devolver varios valores en forma de parámetros de salida por lotes o al procedimiento que realiza la llamada. Contener instrucciones de programación que realicen operaciones en la base de datos, incluidas las llamadas a otros procedimientos. Devolver un valor de estado a un lote o a un procedimiento que realiza la llamada para indicar si la operación se ha realizado correctamente o se han producido errores (y el motivo de estos). Un ejemplo de procedimiento, puede tener el siguiente código: SET ROWCOUNT 10 SELECT Products.ProductName AS TenMostExpensiveProducts, Products.UnitPrice FROM Products ORDER BY Products.UnitPrice DESC Una llamada a este procedimiento (en el administrador gráfico de SQLServer) suponiendo que se llamara TenMostExpensiveProducts sería: USE [NorthwindCS] GO DECLARE @return_value int EXEC @return_value = [dbo].[ten Most Expensive Products] SELECT 'Return Value' = @return_value GO Nos devolverá los 10 productos más caros, además de indicarnos con el valor de retorno 0, que todo ha ido bien. 23
Funciones. Del mismo modo que disponemos de procedimientos, también podemos definir funciones en SQL Server. Estas funciones pueden utilizar las funciones predefinidas en el motor (para más información: http://technet.microsoft.com/es-es/library/ms174318.aspx ). Volviendo a nuestro ejemplo, nosotros/as seleccionaremos, para nuestro ejemplo, la tabla Products. P5 P6 P6. Al finalizar, veremos cómo en nuestros Orígenes de datos, el entorno nos ha creado un objeto llamado NorthwindCSDataSet (este nombre lo podemos cambiar en el paso anterior -Nombre del DataSet-). De ese DataSet, depende otro objeto llamado Products; que, obviamente, representa la tabla que queremos utilizar de nuestra BD. Un DataSet es un objeto que hace las veces de caché de datos de la BD en nuestras aplicaciones. Este objeto contendrá copias de los datos de la BD, respetando la estructura que tienen éstos en la BD. Si necesitamos una tabla, los datos estarán en una tabla en el DataSet; con sus distintos datos en campos. Esta es una pincelada muy ligera, un DataSet es mucho más que esto, lo iremos viendo a lo largo de estos días. 24
P7. Ya lo tenemos todo preparado (ya podemos hacer formularios como churros). Pinchamos sobre la tabla Products, la arrastramos hacia el formulario y soltamos. Arrastrar Después de esto, veremos que en nuestro formulario, se hay incluido 6 controles nuevos: 25
DataGridView que muestra los campos de la tabla Productos. DataSet llamado northwindcsdataset. TableAdapter llamado productstableadapter y tableadaptermanager. BindingSource llamado productsbindingsource y un BindingNavigator llamado productsbindingnavigator. Veamos el significado de todos estos controles: Un DataGridView muestra sus datos en forma de rejilla de datos. La particularidad del que se ha creado en nuestro formulario, es que, en este caso, está enlazado a los datos que hemos traído de la BD. Como ya os he dicho, un DataSet es como una caché de la BD. Esa caché se carga de datos en el momento que se carga el formulario, y los datos con los que se carga, son los que hemos indicado al crear nuestro origen de datos. Ya podemos intuir que realmente al definir que se traiga los datos de la tabla Productos, lo que estamos haciendo es lanzar un 'SELECT * FROM Products' a la BD; pero ese comando SQL, no lo lanza el DataSet, sino un objeto de tipo TableAdapter. Un objeto de tipo TableAdapter se utiliza como intermediario entre un DataSet y la BD, y es el encargado de lanzar los comandos contra la BD e informar del resultado de éstos a nuestra aplicación. Como vemos en el siguiente gráfico estos objetos, son los principales. Además de estos objetos, tenemos un TableAdapterManager que nos ayudará a la hora de llevar las modificaciones de datos que el usuario realice en nuestro formulario (y por lo tanto en los datos del DataSet) a la BD. Nos quedan los objetos BindingSource y BindingNavigator. La palabra Binding, podemos traducirla como vínculo, atadura o enlace; a lo largo de este documento he 26
utilizado varias veces la palabra enlace para referirme a controles que muestran datos que están en una BD. Pues bien, un BindingSource es un elemento que podemos utilizar como origen de los enlaces de datos de los controles de nuestro formulario. El objeto BindingSource, entonces, será un intermediario común, entre todos los controles y el DataSet. Por último, un BindignNavigator, es sólo la barra de herramientas típica de la navegación por registros en una tabla; y por defecto, se muestra con estos controles: Este BindingNavigator está enlazado a nuestro BindingSource, por lo que todos los movimientos que hagamos con él se verán reflejados en todos los controles que estén enlazados al mismo BindingSource que él. Y no sólo eso, los botones Nuevo, Borrar y Guardar tienen programados sus eventos clic para responder convenientemente a las acciones del usuario (eso sí, sin gestión estructurada de excepciones -lo arreglaremos después-). P8. Ejecutamos la aplicación para ver qué tal funciona. Yo, además he hecho que el DataGridView se Acople en el su contenedor principal (que en este caso es el formulario). P9. Con la programación por defecto que ha hecho el diseñador por nosotros/as, los cambios se llevarán a la BD cuando hagamos clic en el botón Guardar cambios del BindingNavigator. Esto quiere decir, que si hacemos modificaciones en los datos, creamos nuevos registros o borramos alguno; estos cambios, sólo se están haciendo 27
en el DataSet y no en la tabla real de la BD. Por los que si cerramos el formulario sin Guardar los cambios, cuando volvamos a arrancar la aplicación veremos que tiene exactamente los mismos datos que al principio (se está volviendo a traer una copia de los datos sin modificar de la BD). Además, no tenemos gestionadas las posibles excepciones que se puedan producir: No poder conectarnos a la BD. Porque ha caído el motor, o los parámetros de conexión han cambiado. Intentar agregar un registro con valores que no son válidos para el esquema de la BD. Valores no válidos pueden ser: Tipo de valores incorrecto. Introducir valores que no corresponden en tipo al tipo del campo en la BD. No dar valores a los campos que no permiten nulos. No respetar las relaciones entre tablas, asignando por ejemplo un código de proveedor que no existe a un producto. Intentar borrar un registro que no puede ser borrado sin faltar a las restricciones de integridad referencial definidas en la BD. Por ejemplo, no podremos borrar un producto mientras que éste aparezca en alguna línea de pedido; o, borrar un proveedor si es el proveedor de algún producto;... Veamos el código que nos ha incluido el diseñador en nuestro formulario: public partial class frmproductos : Form { public frmproductos() { InitializeComponent(); } private void productsbindingnavigatorsaveitem_click(object sender, EventArgs e){ this.validate(); this.productsbindingsource.endedit(); this.tableadaptermanager.updateall(this.northwindcsdataset); } private void frmproductos_load(object sender, EventArgs e){ // TODO: esta línea de código carga datos en la tabla // 'northwindcsdataset.products' Puede moverla o quitarla según sea // necesario. this.productstableadapter.fill(this.northwindcsdataset.products); 28
} } Revisando un poco el código, podemos llegar a la conclusión de que, la instrucción: this.productstableadapter.fill(this.northwindcsdataset.products); es la encargada de cargar de datos el DataSet. O lo que es lo mismo, el método Fill (llenar) de un TableAdapter se encarga de traer los datos de la BD. Y, la instrucción: this.tableadaptermanager.updateall(this.northwindcsdataset); es la encargada de llevar las modificaciones que se hayan producido en el DataSet a la BD. Si lo vemos de forma esquemática, podría ser así: P10. Como primera aproximación válida a la gestión de excepciones podemos modificar el código así: public partial class frmproductos : Form { public frmproductos() { InitializeComponent(); } private void productsbindingnavigatorsaveitem_click(object sender, EventArgs e){ this.validate(); this.productsbindingsource.endedit(); try { this.tableadaptermanager.updateall(this.northwindcsdataset); } catch (Exception ex) 29
{ MessageBox.Show("Una o más modificaciones no se han + podido llevar a la Base de Datos.\n" + "Revise que los datos sean correctos.\n"+ ex.message); //Deshacemos los cambios en el DataSet this.northwindcsdataset.rejectchanges(); } } private void frmproductos_load(object sender, EventArgs e){ // TODO: esta línea de código carga datos en la tabla // 'northwindcsdataset.products' Puede moverla o quitarla según sea // necesario. try { this.productstableadapter.fill(this.northwindcsdataset.products); } catch { MessageBox.Show("No se han podido recuperar los datos de"+ "Productos.\nRevise la conexión a la Base de Datos."); } } } Prueba el código después de hacer esta modificación. Nota: Re El método UpdateAll, llevará todos los cambios que haya realizado el usuario en los registros, pero si cualquiera de ellos provoca una excepción, no se grabarán ninguno de los cambios. Esto, para el usuario puede ser un poco desconcertante, así que, podemos intentar detectar cuando se cambia uno de los registros para ir lanzando las modificaciones a la BD una a una (lo veremos más adelante). El método EndEdit de un BindingSource, permite que todas las modificaciones de los controles del formulario se lleven al DataSet. Ten en cuenta que los valores que vemos en el DataGridView, realmente, son una copia de los datos que contiene el DataSet, y por lo tanto, debe existir un paso intermedio que lleve los datos de los controles al DataSet. 30
El método RejectChanges de un DataSet, nos permite deshacer todos los cambios que haya realizado el usuario en un DataSet (desde la última modificación que se hubiera tomado como válida con el método AcceptChanges). Un DataSet, es capaz de guardar, para cada registro, una copia de los valores originales que había traído de la BD y otra de los modificados por el usuario. Así, si le indicamos al DataSet que deshaga los cambios, puede hacerlo sin tener que volver a recargarlo con los datos de la BD. P11. Con esto, ya podemos dar por finalizada, nuestro primer formulario de acceso a datos de tipo Rejilla de datos. 5 Crear nuestra segunda aplicación de acceso a datos con ayuda del diseñador. En esta ocasión, vamos a reutilizar todo lo que tenemos hecho hasta ahora. Vamos a crear un formulario de detalle para los productos. P1. Agregamos un nuevo formulario a nuestro proyecto (Proyecto Agregar Windows Forms...). Yo lo voy a llamar frmdetalleproductos.cs. P2. De nuevo, en el panel del Explorador de Soluciones, nos vamos a Orígenes de datos. Pero en esta ocasión, en lugar de arrastrar directamente la tabla productos al formulario, primero hacemos clic en la pestañita al lado del nombre de la tabla Products, y seleccionamos Detalles. 31
Pestañita P3. Una vez que tenemos establecido el modo Detalle, arrastramos al formulario. Este será el resultado: 32
Vemos que lo único que ha cambiado es que en lugar de un DataGridView, tenemos label y TextBox. P4. Para poder ejecutar el proyecto y que el formulario que se muestre sea el de detalle, tendremos que editar el contenido de Program.cs. Arrastrar 33
Cambiaremos donde pone frmproductos ponderemos frmdetalleproductos. Tampoco nos debe costar mucho trabajo añadir un formulario desde el que se abran el resto de formularios, incluso un formulario MDI (http://www.iesalandalus.org/moodle/mod/resource/view.php?id=16663 página 36). Continuamos en la siguiente guía. 34