Anda di halaman 1dari 34

Realizar una aplicacin que se encargue de gestionar una bodega que distribuye vinos a sus clientes.

Un cliente realiza a la bodega un pedido con los productos que desea y la bodega se lo enva directamente a su domicilio. La gestin de los clientes y de los pedidos se hace a travs de un formulario M ! con tres formularios hi"o# nuevo cliente, realizar pedido y mostrar pedidos.

$ara empezar% arrancamos &isual 'tudio y creamos un nuevo proyecto Aplicacin de Windows Forms denominado bodega.

Base de datos

(omo siguiente paso vamos a crear la base de datos. 'i instal &isual ()*&isual 'tudio y '+L 'erver ,-press% entonces es posible a.adir al proyecto elementos nuevos de tipo base de datos. /aga clic con el botn secundario del ratn sobre el nombre del proyecto y a.ada un nuevo elemento del tipo 0ase de atos '+L denominado bd1bodega. ,sta accin generar2 una base de datos vaca.

3 continuacin% el asistente para la configuracin de bases de datos mostrar2 una ventana que le permitir2 elegir los ob"etos de la base de datos con los que va a traba"ar4 como est2 vaca% haga clic en el botn (ancelar.

. 5bsrvese que los ficheros de la base de datos han sido guardados en el directorio de la aplicacin. (uando se e"ecute la aplicacin% se traba"ar2 sobre una copia ubicada en la carpeta donde se encuentre el fichero e"ecutable. 'eleccione el apartado de la base de datos en el e-plorador de soluciones y aseg6rese de que la propiedad Copiar en el directorio de resultados tiene el valor Copiar si es posterior.

,n el siguiente paso vamos a a.adir las tablas a la base de datos. &amos a crear tres tablas# clientes, productos y pedidos. $ara ello% dir"ase al explorador de soluciones y haga doble clic

sobre el nodo bd_bodega.mdf . ,sto har2 que se muestre el explorador de servidores con la composicin de la base de datos#

$ara a.adir las tablas% haga clic con el botn secundario del ratn en el nodo Tablas% en el explorador de servidores, y e"ecute la orden Agregar nueva tabla del men6 conte-tual que se visualiza. 'e muestra el editor de tablas. ,dite la tabla clientes como se muestra a continuacin#

5bsrvese que Cliente 7n6mero de cliente8 se ha establecido como clave principal 7clic con el botn secundario del ratn sobre la cabecera de la fila y e"ecutar la orden stablecer clave principal del men6 conte-tual que se visualiza8. 9uarde la tabla y pngale como nombre clientes% posteriormente cerrarla.

'iguiendo un proceso an2logo% edite las tablas productos y pedidos seg6n se muestra a continuacin#

:a tenemos las tres tablas. 'lo nos falta establecer las relaciones entre ellas. /ay una forma muy sencilla de hacer esto% y es creando un diagrama visual de base de datos4 dir"ase al explorador de servidores, haga clic con el botn secundario del ratn en el nodo !iagramas de base de datos y e"ecute la orden Agregar nuevo diagrama del men6 conte-tual que se visualiza. 3 continuacin% a.ada todas las tablas a ese diagrama. $ara relacionar el campo Cliente de la tabla pedidos con el campo Cliente de la tabla clientes haga clic con el botn primario del ratn en el primero y arrastre la correspondencia hasta el segundo. 3cepte los valores por defecto establecidos para la relacin a.adida. ;dem para relacionar el campo Clave de la tabla pedidos con el campo Clave de la tabla productos.

$ara poder hacer pruebas con la base datos construida% vamos a a.adir algunos registros. $ara ello% haga clic con el botn secundario del ratn en el nodo de cada tabla y e"ecute la orden "ostrar datos de tabla del men6 con te-tual que se visualiza.

<inalmente% guardamos todo el proyecto. Capa de acceso a datos (ontinuando con la aplicacin% vamos a crear una capa de acceso a datos que nos permita abstraernos de las operaciones con bases de datos. $ara ello% dir"ase al panel #r$genes de datos, o bien e"ecute la orden "ostrar or$genes de datos del men6 !atos para mostrarlo% y haga clic en Agregar nuevo origen de datos. 3 continuacin cree tres con"untos de datos 7 ata'et8# dsClientes, ds%roductos y ds%edidos. $ara crear uno de estos con"untos de datos eli"a# = >ipo de origen de base de datos# &ase de datos. = (one-in de datos# bd_bodega.mdf = ?ombre del ata'et# dsClientes. = 5b"etos de base de datos# tabla clientes.

Repita este proceso para ds%roductos y ds%edidos. Una vez creados% obsrvese que se puede abrir el DataSet y analizar su contenido.

3s mismo% si hace clic con el botn secundario del ratn sobre el nombre del DataSet y e"ecuta la orden ditar !ata'et con el dise(ador del men6 conte-tual que se visualiza% se mostrar2 la siguiente ventana#

La figura anterior muestra dos ob"etos# pedidos de la clase DataTable y pedidos TableAdapter de la clase TableAdapter. ,l primero hace referencia a la tabla del DataSet y el segundo al adaptador que se utilizar2 para% e"ecutando la orden '+L adecuada% llenar la tabla del DataSet. ,sto es lo que anteriormente denominamos acceso desconectado a base de datos. ,l adaptador presenta dos mtodos# Fill y )et!ata. ,l mtodo Fill toma como par2metro un DataTable o un DataSet y e"ecuta la orden '+L programada 7puede verla haciendo clic con el botn secundario del ratn en el ttulo de cualquiera de los dos paneles y e"ecutando la orden Configurar del men6 conte-tual que se visualiza8. ,l mtodo )et!ata devuelve un nuevo ob"eto DataTable con los resultados de la orden '+L. >ambin se han creado los mtodos *nsert, +pdate y !elete que se pueden llamar para enviar cambios de filas individuales directamente a la base de datos. 3s mismo% en la vista de clases puede ver la funcionalidad proporcionada por cada una de las clases de los con"untos de datos a.adidos% funcionalidad que utilizaremos cuando sea necesario.

Interfaz grfica ,l siguiente paso es crear la interfaz gr2fica. @sta va a consistir en un formulario principal tipo M ! y tres formularios hi"o# ,uevo cliente, -ealizar pedido y "ostrar pedidos. Llamaremos &odega a la forma <ormA.cs% en la propiedad *s"diContainer seleccionamos True% en tama.o se le asigna 550,3 y le agregaremos lo siguiente# !enuStrip que llamaremos &arra!e"enus y agregaremos los siguientes tres !enuIte"# o ,l primero se llamar2 menu,uevoCliente con la imagenB menu,uevoCliente.*mage con el te-to ,uevo cliente. o ,l segundo se llamar2 menu-ealizar%edido con la imagenB menu-ealizar%edido.*mage con el te-to -ealizar %edido. o ,l tercero se llamar2 menu"ostrar%edidos con la imagenB menu"ostrar%edidos.*mage con el te-to "ostrar %edidos. B $ara a.adir una imagen en propiedades en !mage se da clic en el botn CDE. ,n la ventana que se abre seleccionamos Local resource y despus se da clic en !mportD y selecciona la imagen que se desea.

eber2 quedar de la siguiente manera#

3ntes de crear cada forma de cada opcin vamos a crear una plantilla. (reamos una nueva forma con el nombre form%lantilla. entro de propiedades en color de fondo elegiremos #radientInacti$eCaption% en tama.o le asignamos %33,35& y en ca"a de control elegimos false. 3gregamos una etiqueta y la nombramos 'abel(% en 3nchor se selecciona Top, 'eft, )igt*% en 0acF(olor se selecciona Acti$eCaption% en 3utosize +alse% en <ont !icrosoft Sans Serif, (%.&5pt% en <ore(olor se elige Control'ig*t'ig*t y en modifiers se selecciona ,rotected. 3gregamos un 9roup0o- al que llamamos #roupBo-(% en 3nchor se selecciona Top, Botto", 'eft, )ig*t% en modifiers seleccionamos ,rotected y quitamos el te-to. 3gregamos dos botones% uno con el nombre btAceptar% en 3nchor se selecciona Botto", )ig*t% en modifiers seleccionamos ,rotected y en te-to escribimos Aceptar. ,l otro con el nombre btCancelar% en ialogResult se selecciona Cancel% en modifiers seleccionamos ,rotected% en 3nchor se selecciona Botto", )ig*t y en te-to escribimos Cancelar.

'e da doble clic en el botn (ancelar y ponemos el siguiente cdigo en el mtodo generado#
private void btCancelar_Click(object sender, EventArgs e) { Close(); }

$resionamos <G o 0uild 'olution de la opcin 0uild para verificar que no haya errores y podamos utilizar la plantilla. .ue$o cliente ,n este apartado vamos a implementar el formulario que nos permitir2 a.adir un nuevo cliente a la base de datos. $ara ello% vamos a crear una nueva In*erited +or" llamada form,uevoCliente y presionamos 3.adir.

3 continuacin nos pide que seleccionemos la clase base. ,n este caso es form%lantilla y presionamos 3ceptar.

'i no les permite a.adir !nherited forms y les aparece el error# "Could not locate the project item templates for inherited components " . ebe realizar lo siguiente. !r al folder# (#H$rogram <iles 7-IG8HMicrosoft &isual 'tudio J.KH&()H esigner>emplates o el folder equivalente seg6n el Microsoft &isual 'tudio que tenga instalado. entro encontrar2n un folder% si su versin de Microsoft &isual 'tudio est2 en espa.ol el nombre del folder debe ser LKIM% si su versin est2 en ingls el nombre del folder debe ser AKLL. 'i no concuerda% debe copiar el folder y a la copia del folder debe renombrarlo seg6n el idioma 7LKIM si tiene Microsoft &isual 'tudio en espa.ol y AKLL si lo tiene en ingls8 y con esto se soluciona el problema. ,n el formulario ,uevo cliente hay que a.adir los controles que permitan introducir los datos de un cliente4 una vez introducidos stos% ser2n registrados en la base de datos tras hacer cAic en el botn Aceptar. Una forma sencilla de hacer lo indicado en el p2rrafo anterior es dirigirse al panel #r$genes de datos y arrastrar la tabla clientes del con"unto de datos dsClientes. 5bservando la figura siguiente% vemos a la izquierda de la entidad clientes un icono# !ata)rid.iew, !etalles, etc.

,l icono al que nos hemos referido en el p2rrafo anterior% seleccionable haciendo clic con el ratn en el botn situado a la derecha de la entidad% indica el control o controles que se a.adir2n sobre el formulario para acceder al origen de datos. ?osotros vamos a elegir !etalles para que se a.ada una ca"a de te-to por cada uno de los campos que forman un registro de un cliente. ,stablezca la propiedad Anc*or para esas ca"as de te-to al valor Top, /e0t, -ig1t. 'eg6n lo e-puesto% visualice el formulario ,uevo cliente y arrastre sobre l el detalle de un registro de clientes desde el origen de datos dsClientes. ,sta operacin a.adir2 al formulario form,uevoCliente un con"unto de datos dsClientes, de tipo dsClientes, un adaptador clientesTableAdapter para llenar la tabla de dsClientes y un control Binding.a$igator con su origen de datos BindingSource conectado al origen de datos dsClientes. ,sta barra de navegacin no la necesitamos ya que lo que se pretende con este formulario es simplemente a.adir un nuevo cliente a la tabla clientes de la base de datos. $or lo tanto% la ocultaremos poniendo su propiedad /isible a false. 3 Label A le cambiamos el te-to a .ue$o Cliente y las ca"as de te-to se le aumentar2 el ancho hasta que quede de la siguiente manera#

$ara guardar el nuevo registro% en lugar del navegador utilizaremos el botn Aceptar. $ara editar el controlador de este botn haga doble clic sobre l. ,n el panel de cdigo que se visualiza% observaremos dos mtodos% form,uevoCliente_/oad y binding,avigalor'ave*tem_Clic2, que fueron a.adidos por el asistente cuando arrastramos la tabla. ,l primero carga los datos en la tabla clientes del con"unto de datos 7se e"ecuta cuando se carga el formulario8 y el segundo actualiza la base de datos con los cambios que se hayan efectuado 7se e"ecuta al hacer clic en el botn guardar del navegador8. ,l mtodo binding,avigalor'aveltem_ Clic2 ya no tiene sentido puesto que hemos ocultado el navegador. ,sta operacin la realizar2 ahora el botn Aceptar. $or lo tanto% copie el cdigo de ese mtodo en btAceptar_Clic2 y elimine el mtodo billding,avigator'aveltem_ Clic2.
private void btAceptar_Click(object sender, EventArgs e) { if (this. alidate()) { tr! {

this.clientes"inding#o$rce.EndEdit(); this.clientes%ableAdapter.&pdate(this.dsClientes.clientes); } catch (E'ception e') { (essage"o'.#ho)(*Error+ * , e'.(essage); } } else (essage"o'.#ho)(this, *Errores de validaci-n.*, *.$ardar*, (essage"o'"$ttons./0, (essage"o'1con.2arning); this.Close(); }

,l mtodo anterior realiza una validacin de los datos y si resulta positiva actualiza la base de datos. ,l mtodo /alidate valida el 6ltimo control no validado y sus predecesores% pero sin incluir el control actual. ,sta versin del mtodo siempre realiza la validacin% independientemente del valor de la propiedad 3uto&alidate del control padre. $or consiguiente% 6selo para forzar una validacin incondicional. ,ota3 elimine el mtodo btAceptar Clic2 de la plantilla 7clase padre del formulario8 ya que si no% ser2 invocado antes de e"ecutar el mtodo anterior% y cierre el formulario desde ste 6ltimo. N(on qu se actualizar2 la base de datos al hacer clic en el botn Aceptar4 $ues tiene que actualizarse con el nuevo cliente. ,ntonces hay que crear un nuevo registro cuyos datos introduciremos a travs de form,uevoCliente. ,sta operacin es la que tiene que hacer el mtodo form,uevoCliente _/oad. $or lo tanto% redefina este mtodo como se indica a continuacin#
private void for34$evoCliente_5oad(object sender, EventArgs e) { 66 A7adir $n n$evo registro this.clientes"inding#o$rce.Add4e)(); }

,ste mtodo crea un nuevo registro en la tabla de dsClientes que despus guardamos haciendo clic en el botn Aceptar. $ero% f"ese que no hemos hecho ninguna validacin de los datos antes de guardar el registro. @ste ser2 el siguiente paso a desarrollar. $ara validar los datos introducidos en el formulario% podemos hacer uso de los mane"adores para los eventos /alidating 0 /alidate, del control 1rror,ro$ider del control !as2edTe-tBo-, etc. ?osotros% a modo de e"emplo% vamos a realizar una validacin sencilla# que el contenido de las ca"as de te-to para los campos Cliente, ,ombre% Apellidos y !ireccin, no sea nulo% que es lo que e-igimos al crear la base de datos. 'eg6n esto% a.ada el controlador del evento /alidating para estas ca"as de te-to y edtelas an2logamente como se indica a continuacin para la ca"a de te-to ClienteText&ox3
private void cliente%e't"o'_ alidating(object sender, CancelEventArgs e) { if (cliente%e't"o'.%e't.5ength 88 9) e.Cancel 8 tr$e; }

?o olvidar que debe hacer lo mismo para cada ca"a de te-to a e-cepcin de telfono y correo electrnico que puede quedar vaco. 3dem2s a cada ca"a de te-to se le debe asignar el mtodo de validacin. ,n propiedades presionar ,ventos y en &alidating y elegir el mtodo seg6n la ca"a de te-to.

3dem2s de la validacin anterior% es necesario tambin mostrarle al usuario informacin de qu es lo que est2 haciendo mal. $ara hacer esto vamos a utilizar el control 1rror,ro$ider que nos permite asociar un mensa"e con un control determinado% de forma que si en ese control ocurre un error% aparecer2 un icono al lado que mostrar2 el mensa"e nada m2s pasar el ratn sobre l. 'eg6n lo e-puesto% a.ada uno de estos controles al formulario. Una vez a.adido el control rror%rovider5% modifique los controladores que acabamos de a.adir de forma an2loga como se indica a continuacin#
private void cliente%e't"o'_ alidating(object sender, CancelEventArgs e) { if (cliente%e't"o'.%e't.5ength 88 9) { e.Cancel 8 tr$e; error:rovider;.#etError(cliente%e't"o', *1ntrod$<ca el identificador del cliente*); } else error:rovider;.#etError(cliente%e't"o', n$ll); }

3.adiremos al men6 principal la posibilidad de llamar a esta forma que acabamos de crear dando doble clicF sobre la opcin ,uevo Cliente y escribir el siguiente cdigo en la funcin que se acaba de crear dentro de Form5.cs#
private void 3en$4$evoCliente_Click(object sender, EventArgs e) { foreach (=or3 f in this.(diChildren) { if (f.4a3e 88 *for34$evoCliente*) { f.Activate(); ret$rn; }

} for34$evoCliente for3>ijo 8 ne) for34$evoCliente(); for3>ijo.(di:arent 8 this; for3>ijo.2indo)#tate 8 =or32indo)#tate.(a'i3i<ed; for3>ijo.#ho)();

3hora puede e"ecutar y comprobar el funcionamiento de la aplicacin. )ealizar pedido ,n este apartado vamos a implementar el formulario que permitir2 realizar un pedido que registraremos en la tabla pedidos de la base de datos. Un pedido se har2 en base a los elementos disponibles en la tabla productos. La forma de crear esta forma es de manera similar a la manera en la que creamos la forma ?uevo (liente pero ahora con el nombre Realizar pedido. ,l aspecto de este formulario se muestra a continuacin.

,n primer lugar% cambios Label A por Realizar pedido. 'e muestra una etiqueta y una ca"a de te-to que llamaremos ctCliente para escribir el cdigo del cliente que realiza el pedido. $ara facilitar la obtencin del cdigo del diente% hemos a.adido un botn que llamaremos btBuscar a la derecha de la ca"a que mostrar2 un di2logo &uscar cdigo del cliente. ,stablezca la propiedad 3nchor el valor Top, /eft, -ig1t para estos controles. espus% muestra una re"illa vinculada con el origen de datos productos. 3rrastre esta entidad desde el panel origen de datos. $ara personalizar esta re"illa% abra su men6 de tareas% deshabilite las operaciones de agregar% editar y eliminar filas% y quite la columna 'toc2.

espus% desde la ventana de propiedades asigne a su propiedad AutoSizeColu"ns!ode el valor AllCells, a Selection!ode el valor Full-ow'elect, a !ultiSelect el valor false para que slo se pueda seleccionar una fila cada vez y a su propiedad Anc*or el valor Top, /eft, -ig1t. eba"o de la re"illa se muestra una etiqueta y una ca"a de te-to que nombraremos ctCantidad para escribir la cantidad comprada del producto elegido 7por omisin ser2 A8. <inalmente% oculte la barra de productos&iding,avigator'aveltem_Clic2. navegacin y elimine el mtodo

&amos a dise.ar el di2logo &uscar cdigo del cliente. 3.ada al proyecto un nuevo formulario llamado for"BuscarCodCliente y haga que se derive de plantilla de formularios. ,l formulario tendr2 el aspecto de la figura mostrada a continuacin#

!nsertaremos una etiqueta con el te-to .o"bre o apellido% una ca"a de te-to llamada ctApellidos.o"bre. La ca"a de te-to permitir2 introducir el nombre o apellidos total o parcialmente 7se trata de una subcadena para buscar en los campos ,ombre y Apellidos6 con la intencin de obtener en una re"illa los registros coincidentes y seleccionar el cliente buscado para obtener su cdigo de cliente.

3.ada la re"illa a la que hemos hecho referencia 7ob"eto Data#rid/ie38. /2galo arrastrando la entidad clientes desde el panel origen de datos. 3 continuacin% abra su men6 de tareas para configurarla. 3sgnele el origen de datos clientes, deshabilite las operaciones de agregar% editar y eliminar filas y quite las columnas !ireccin, Tel7fono y Correo _e. espus% desde la ventana propiedades asigne a su propiedad AutoSizeColu"ns!ode el valor Fill% a !ultiSelect el valor false y a su propiedad Anc*or el valor Top, /e0t, -ig1t. +ueda escribir el cdigo del controlador del botn &uscar llamado btBuscar. 3l hacer clic en este botn% la re"illa tiene que mostrar los registros de clientes que en sus campos ,ombre o Apellidos contengan el te-to escrito en la ca"a de te-to. 'i la ca"a de te-to se de"a vaca% se mostrar2n todos los registros. ir"ase al panel #r$genes de datos y muestre el DataSet dsClientes en el dise.ador#

'i lo desea% puede comprobar que el adaptador actual est2 configurado para e-traer todos los registros de la tabla clientes 7mtodo Fil*6. $or lo tanto% tenemos que escribir una nueva orden ',L,(> que nos filtre estos registros. $ara ello% e"ecute la orden Agregar 8 Consulta del men6 conte-tual del con"unto de datos. 'e mostrar2 el asistente para la configuracin de consultas. ,li"a usar una instruccin '+L que devuelva filas y utilice el generador de consultas para generar dicha consulta#

5bsrvese en la figura anterior que la consulta se realizar2 en base al par2metro cadena. Una vez que tenemos la instruccin '+L% el asistente nos permitir2% a continuacin% elegir los mtodos que se van a agregar al TableAdapter para e"ecutar la consulta# Fill&9,ombreApellidos y )et!ata&9,ombreApellidos.

Una vez a.adida la nueva consulta al adaptador% volvemos al di2logo% eliminamos el mtodo form&uscarCodCliente _/oad y editamos el controlador del botn &uscar as#
private void bt"$scar_Click(object sender, EventArgs e) { clientes%ableAdapter.=ill"!4o3breApellidos(dsClientes.clientes, *?* , ctApellidos4o3bre.%e't , *?*); }

5bsrvese que este mtodo% e"ecutando la consulta implementada por Fill&9,ombreApellidos en el adaptador clientesTableAdapter, llena la tabla dsClientes.clientes que es el origen de datos especificado para la re"illa. ,l mtodo Fill&9,ombreApellidos especifica en su segundo par2metro la cadena utilizada para realizar la b6squeda. $ara mostrar este di2logo% como modal% edite el controlador del botn de ttulo ODO% que pusimos en el formulario -ealizar pedido, como se indica a continuacin#
private void bt"$scar_Click(object sender, EventArgs e) { for3"$scarCodCliente for3"$scar 8 ne) for3"$scarCodCliente(); for3"$scar.#ho)@ialog(); }

Una vez mostrado el di2logo &uscar cdigo del cliente, queremos que al hacer clic en el botn Aceptar se obtenga el cdigo del cliente de la fila seleccionada y se utilice para rellenar la ca"a correspondiente del di2logo -ealizar pedido. ,ste cdigo de cliente lo vamos a almacenar en un atributo p6blico% codigoCliente% que vamos a a.adir a la clase del formulario &uscar cdigo del cliente3
p$blic partial class for3"$scarCodCliente + bodega.for3:lantilla { p$blic string codigoCliente;

66..

espus% editamos el controlador del botn Aceptar del formulario &uscar cdigo del cliente como se indica a continuacin#
private void btAceptar_Click(object sender, EventArgs e) { codigoCliente 8 dsClientes.clientesAclientes"inding#o$rce.:ositionB.Cliente; Close(); }

,l ob"eto BindingSource hace de puente entre el control y el con"unto de datos proporcionando acceso a los datos actualmente mostrados por el control de una forma indirecta% incluyendo navegacin% ordenacin% filtrado y actualizacin. $ara rellenar la ca"a correspondiente del di2logo -ealizar pedido, a.ada al controlador de su botn de ttulo O ... O la sentencia indicada a continuacin#
private void bt"$scar_Click(object sender, EventArgs e) { for3"$scarCodCliente for3"$scar 8 ne) for3"$scarCodCliente(); for3"$scar.#ho)@ialog(); ctCliente.%e't 8 for3"$scar.codigoCliente; }

3gregamos el siguiente cdigo en <ormA.cs para que se pueda llamar a la vista recin creada#
private void 3en$Ceali<ar:edido_Click(object sender, EventArgs e) { foreach (=or3 f in this.(diChildren) { if (f.4a3e 88 *for3Ceali<ar:edido*) { f.Activate(); ret$rn; } } for3Ceali<ar:edido for3>ijo 8 ne) for3Ceali<ar:edido(); for3>ijo.(di:arent 8 this; for3>ijo.2indo)#tate 8 =or32indo)#tate.(a'i3i<ed; for3>ijo.#ho)(); }

(orre la aplicacin y se ver2 lo siguiente#

N+u tenemos que hacer a continuacinP 3 la vista del formulario anterior% el usuario de la aplicacin elegir2 el producto deseado% escribir2 la cantidad de unidades requerida y har2 clic en el botn Aceptar. La respuesta a este clic tiene que ser guardar este pedido en la tabla de pedidos si hay stoc2 suficiente% decrementar el stoc2 y actualizar la tabla productos con el nuevo stoc2. $arte de este proceso 7lo que no est relacionado con el componente ds%roductos de este formulario8 lo vamos a implementar en una clase /ogica,egocio con el fin de no incluir en el formulario operaciones tpicas de la capa de acceso a datos. 'eg6n esto el formulario simplemente invocar2 a un mtodo -ealizar%edido de esta clase pas2ndole como argumentos el cliente que realiza el pedido% el producto y la cantidad pedida del mismo. espus decrementar2 el stoc2 y actualizar2 la tabla productos.
private void btAceptar_Click(object sender, EventArgs e) { 66 #i no se introd$jo el c-digo de cliente. solicitarlo if (ctCliente.%e't.5ength 88 9) bt"$scar.:erfor3Click(); 66 Ceali<ar pedido si ha! stock if (Convert.%o1ntDE(ctCantidad.%e't) F8 ds:rod$ctos.prod$ctosAprod$ctos"inding#o$rce.:ositionB.#tock) { ds:rod$ctos.prod$ctosCo) prod$cto 8 ds:rod$ctos.prod$ctosAprod$ctos"inding#o$rce.:ositionB; 5ogica4egocio.Ceali<ar:edido(ctCliente.%e't, prod$cto, Convert.%o1ntDE(ctCantidad.%e't)); ds:rod$ctos.prod$ctosAprod$ctos"inding#o$rce.:ositionB.#tock G8 Convert.%o1ntDE(ctCantidad.%e't); prod$ctos%ableAdapter.&pdate(ds:rod$ctos.prod$ctos); Close(); } else (essage"o'.#ho)(*5a cantidad s$pera el stock*); }

Las sentencias sombreadas deberan realizarse como una operacin atmica. ,sto es% supongamos que al e"ecutarse 4pdate ocurre un error. ,l resultado sera que hemos realizado un pedido pero no se ha decrementado el stoc2 en la tabla pedidos, lo cual no es coherente. $ara evitar incoherencias como la mencionada% este tipo de operaciones sobre la base de datos deben ser transaccionales. ,sto es% las operaciones mencionadas anteriormente deben ocurrir en una misma transaccin para si ocurre un error% poder echar atr2s toda esa

transaccin. &isual 'tudio proporciona una nueva tcnica para traba"ar con transacciones a travs de la biblioteca S0ste".Transactions. N(mo guardar datos utilizando una transaccinP La forma m2s f2cil de implementar una transaccin es crear un ob"eto de la clase TransactionScope del espacio de nombres S0ste".Transactions% para utilizarlo despus en una sentencia using. ,l cdigo e"ecutado dentro de using participar2 en la transaccin. $rimero hay que hacer referencia a S0ste".Transactions en References dentro del e-plorador de soluciones. 'e presiona clic derecho en References y se selecciona A(adir referencia en .?,> buscar S0ste".Transactions y se presiona aceptar.

D
$sing #!ste3.2indo)s.=or3s; $sing #!ste3.%ransactions; na3espace bodega {

D $ara e"ecutar la transaccin hay que invocar al mtodo Co"plete al final del bloque using% y para echar atr2s la transaccin basta con que se lance una e-cepcin antes de la llamada al mtodo Co"plete.
private void btAceptar_Click(object sender, EventArgs e) { 66 #i no se introd$jo el c-digo de cliente. solicitarlo if (ctCliente.%e't.5ength 88 9) bt"$scar.:erfor3Click(); 66 Ceali<ar pedido si ha! stock if (Convert.%o1ntDE(ctCantidad.%e't) F8 ds:rod$ctos.prod$ctosAprod$ctos"inding#o$rce.:ositionB.#tock) { %ransaction#cope tr 8 ne) %ransaction#cope(); $sing (tr) { ds:rod$ctos.prod$ctosCo) prod$cto 8 ds:rod$ctos.prod$ctosAprod$ctos"inding#o$rce.:ositionB; 5ogica4egocio.Ceali<ar:edido(ctCliente.%e't, prod$cto, Convert.%o1ntDE(ctCantidad.%e't)); ds:rod$ctos.prod$ctosAprod$ctos"inding#o$rce.:ositionB.#tock G8 Convert.%o1ntDE(ctCantidad.%e't); prod$ctos%ableAdapter.&pdate(ds:rod$ctos.prod$ctos); tr.Co3plete(); } Close();

} else } (essage"o'.#ho)(*5a cantidad s$pera el stock*);

'i ahora% cuando e"ecute la aplicacin% la aplicacin lanza la e-cepcin siguiente% es porque el servicio >( 7coordinador de transacciones distribuidas8 no est2 arrancado. Muestre los servicios de su m2quina y arranque el servicio >(. ,sto lo puede hacer dando clic derecho en (omputerQManage.

Una vez dentro ir a 'ervices and 3pplicationsQ'ervices

!r al servicio istributed >ransaction (oordinator e iniciar el servicio.

'i llega a aparecer un error que dice que ha fallado el servicio M' >(% simplemente reinicia este servicio en esta misma pantalla. ,l paso siguiente es a.adir a la aplicacin la clase /ogica,egocio y escribir su mtodo static -ealizar%edido. N+u tiene que hacer este mtodoP $ues% a.adir un nuevo pedido a la tabla pedidos de la base de datos. Los datos para este nuevo registro son proporcionados por los par2metros del mtodo# cliente, producto y cantidad. ,ste mtodo% seg6n se puede observar a continuacin% crea un adaptador de la clase pedidosTableAdapter que se a.adi al proyecto cuando se cre el origen de datos ds%edidos, crea un con"unto de datos de la clase ds%edidos, obtiene los datos para el nuevo registro% a.ade este registro al con"unto de datos anteriormente creado% y actualiza la tabla pedidos de la base de datos desde ese con"unto de datos invocando al mtodo 4pdate del adaptador. La e"ecucin de este mtodo hace que el adaptador conecte con la base de datos y e"ecute las instrucciones '+L adecuadas para actualizar la tabla pedidos de la base de datos. ebe a.adir una nueva clase al proyecto.

p$blic class 5ogica4egocio { p$blic static void Ceali<ar:edido(string cliente, ds:rod$ctos.prod$ctosCo) prod$cto, int cantidad) { 66 Agregar $n pedido ds:edidos%ableAdapters.pedidos%ableAdapter adaptador 8 ne) ds:edidos%ableAdapters.pedidos%ableAdapter(); ds:edidos datos 8 ne) ds:edidos(); adaptador.=ill(datos.pedidos); 66 A7adir el pedido a la tabla pedidos desde *datos* int pedido 8 datos.pedidos.Co$nt,;; string clave 8 prod$cto.Clave; float coste 8 prod$cto.: : H cantidad; @ate%i3e fecha 8 @ate%i3e.4o); bool servido 8 false; datos.pedidos.AddpedidosCo)(pedido, cliente, clave, cantidad, coste, fecha, servido); 66 Act$ali<ar la base de datos desde *datos* adaptador.&pdate(datos); } }

!ostrar pedido ,n este apartado vamos a implementar el formulario que nos permitir2 mostrar y servir los pedidos registrados en la base de datos. ,l aspecto de este formulario se muestra a continuacin llamado for"!ostrar,edidos.

(ambiar el Label A por !ostrar perdidos. ,l formulario de la figura anterior muestra una re"illa vinculada con el origen de datos pedidos. ,sto lo puede conseguir arrastrando esta entidad desde el panel origen de datos. 3 continuacin% para personalizar la re"illa abra su men6 de tareas y deshabilite las operaciones de agregar% editar y eliminar filas. espus% desde la ventana de propiedades asigne a su propiedad AutoSizeColu"ns!ode el valor Fill% a !ultiSelect el valor false% a Selection!ode el valor Full-ow'elect y a su propiedad Anc*or el valor Top, &ottom, /eft, -ig1t. <inalmente% oculte la barra de pedidosbinding,avigator'aveltem_Clic2. navegacin y elimine el mtodo

5bserve el formulario de la figura anterior4 muestra cuatro pedidos% dos de ellos realizados por el mismo cliente% y ninguno est2 servido. $ara servir un pedido% el usuario de la aplicacin har2 cAic en la fila correspondiente y despus en Aceptar. N+u tiene que ocurrir en este instanteP 'implemente se actualizar2 la tabla p edidos de la base de datos con el nuevo valor del campo 'ervido3
private void btAceptar_Click(object sender, EventArgs e) { if (pedidos"inding#o$rce.:osition F 9) ret$rn; int pos 8 pedidos"inding#o$rce.:osition; if (Ids:edidos.pedidosAposB.#ervido) { ds:edidos.pedidosAposB.#ervido 8 tr$e; pedidos%ableAdapter.&pdate(ds:edidos.pedidos); } else (essage"o'.#ho)(*Ese pedido !a f$e servido*); Close(); }

3 <ormA.cs le agregamos el siguiente cdigo para acceder a la vista recin creada#


private void 3en$(ostrar:edidos_Click(object sender, EventArgs e) { foreach (=or3 f in this.(diChildren) { if (f.4a3e 88 *for3(ostrar:edidos*) { f.Activate(); ret$rn; } } for3(ostrar:edidos for3>ijo 8 ne) for3(ostrar:edidos(); for3>ijo.(di:arent 8 this; for3>ijo.2indo)#tate 8 =or32indo)#tate.(a'i3i<ed; for3>ijo.#ho)(); }

(on esto la aplicacin ya est2 terminada

Anda mungkin juga menyukai