Continuando con la guía del sistema de gestión de citas, en esta entrada veremos la creación del CRUD de especialidades.Lo primero que haremos es programar las funciones que nos permiten leer, registrar y actualizar datos de las especialidades en nuestra base de datos
Comenzaremos creando la clase Conexion en la capa de datos, el cual tendrá el siguiente código fuente:
Procedimientos Almacenados
Bien, antes de continuar con la programación en C# tenemos que programar los procedimientos almacenados en nuestra BD. Para seguir un estándar en los nombres de los SP, la estructura a utilizar será la siguiente:
GC_[ACCION]_[OBJETO]_SP
Donde:
- [ACCION]: puede ser LEER, EDITAR, INSERTAR
- [OBJETO]: el dato que se quiere leer por ejm: especialidad (singular) o especialidades (plural)
Vamos a crear al SP que nos permita listar todas las especialidades registradas (activas e inactivas):
A continuación crearemos el SP que nos permite obtener una especialidad en especifico, para eso haremos uso de la variable @ID (línea 2 y línea 11):
Hasta el momento ya tenemos los SP que nos traen la data de la BD, ahora necesitamos crear el SP que nos permite registrar datos:
En este punto tengo que detenerme a explicar el código de la inserción ya que como habrán notado no es el clásico INSERT INTO. Cuando insertamos datos en una tabla que tiene un campo auto generado (identity), sabemos que podemos hacer uso de @@IDENTITY o SCOPE_IDENTITY para obtener el identificador generado, pero existen situaciones en las cuales esas funciones nos pueden dar dolores de cabeza por lo que recomiendo hacer uso de OUTPUT (en caso quieran saber más googleen o lean este post).
Retomando el tema del INSERT, básicamente lo que hago es crear una variable tabla con un único campo llamado IDGENERADO del tipo de dato INT (línea 7), luego entre las instrucciones INSERT e VALUES uso la instrucción OUTPUT seguido de la palabra reservada INSERTED, a partir de este punto puedo acceder a los campos que tiene la tabla, en este caso como ya sé que el campo autogenerado en mi tabla se llama "ID", entonces hago el llamado del campo a través de INSERTED.ID, como ya tengo acceso a ese dato, ahora lo puedo hacer es insertar dicho dato en una tabla, entonces lo que hago a continuación es llamar a INTO @TABLA(IDGENERADO) para que guarde la información que acabo de generar al momento de insertar el registro(esto me permite guardar un conjunto de identificadores generadores, pero para este caso siempre guardará un solo dato). Ahora que ya tengo el identificador auto generado simplemente tengo que hacer un select a la variable @TABLA y obtener el valor del campo IDGENERADO (línea 23 a 25).
Por último nos quedaría programar el procedimiento almacenado para modificar una especialidad ya existen:
Continuando con la programación en la capa de datos, ahora tenemos que crear la clase EspecialidadDAL la cuál contendrán las llamadas a los SP que acabmos de programar:
Imagen 1: agregar clase a visual studio. (Fuente propia)
Imagen 2: creación de clase EspecialidadDAL. (Fuente propia)
La línea 6 y 7 nos permite hacer uso de las clases de sql server, la línea 8 nos permite hacer uso de las clases de la capa entidades, en este caso de EspecialidadDTO. Recuerden que en todas las clases vamos a implementadar debemos tener el patrón singleton (Línea 14 a 20).
A continuación tenemos el método ListarEspecialidades que retorna una Lista de objetos del tipo EspecialidadDTO, como ya tenemos creada la clase Conexion, la cuál nos retorna la conexión a nuestra base de datos, simplemente invocamos a la función conectar de la clase Conexion a través de la función estática Instancia (línea 29). ahora que ya tenemos la conexión de la base de datos lo que sigue es llamar a nuestro procedimiento almacenado que nos permite listar todas las especialidades registradas (línea 30), las siguientes línea son la clásicas de configuración (línea 31), apertura de la conexión (línea 32), luego se ejecuta la llamada al procedimiento almacenado y la data se guarda en la variable dr. Mientras la variable dr tenga datos se leerá la información que trajo desde la bd y se irá agregando a la variable lista de especialidades que declaramos líneas arriba (línea 26). Una vez haya terminado la lectura de los datos, la función retornará la lista de especialidades encontradas.
El método ObtenerEspecialidad nos devuelve un objeto del tipo EspecialidadDTO, en caso no encuentre información nos retornará un objeto null.
El método GrabarEspecialidad recibe dos parámetros: el primero es la especialidad como tal y el segundo parámetro es el nombre del usuario que realiza la acción de grabar (el dato del usuario se obtendrá desde la sesión). Si la inserción de datos funciona correctamente lo que nos devolverá el SP es el nuevo identificador generado (línea 90).
El método EditarEspecialidad recibe dos parámetros: el primero es la especialidad como tal y el segundo parámetro es el nombre del usuario que realiza la acción de modificar. Si la modificación de datos funciona correctamente lo que nos devolverá el SP es el número de filas afectadas (línea 115), en caso se haya modificado un registro entonces la función retornará verdadero.
Capa Componentes Comunes
Algo que nos faltó agregar al momento de crear la solución es la capa de componentes comunes, en este caso agregaremos un proyecto de biblioteca de clases a nuestra solución actual, como la capa comunes es una capa que se puede reutilizar en otro proyecto la llamaremos: Base.Comunes.
Imagen 3: Agregar nuevo proyecto a la solución. (Fuente propia)
Imagen 4: creando la capa de componentes comunes. (Fuente propia)
A continuación crearemos la clase MensajeSistema la cuál contendrá los mensajes predeterminados para cuando se inserte/modifique/elimine un registro.
Imagen 5: agregar clase a capa comunes. (Fuente propia)
Imagen 6: Creando la clase MensajeSistema. (Fuente propia)
Como habrán notado la clase MensajeSistema tiene el modificador sealed que sirve para que otras clases no hereden de ella, ya que es una clase que sólo servirá para usar las constantes que tiene.
Imagen 7: agregar clase a capa comunes. (Fuente propia)
Imagen 8: Creando la clase RespuestaSistema. (Fuente propia)
Esta clase servirá para transportar la acción exitosa o de error de la capa lógica y su respectivo mensaje hacia la capa presentación.
Capa Lógica de Negocio
Ahora en la capa de lógica de negocio agregamos la referencia de la capa de componentes comunes.
Imagen 9: Agregar referencia. (Fuente propia)
Imagen 10: Agregar referencia a la capa componentes comunes. (Fuente propia)
Agregamos la clase EspecialidadBLL.
Imagen 11: Agregar clase en capa lógica. (Fuente propia)
Imagen 12: Creando clase EspecialidadBLL. (Fuente propia)
Al igual que la capa EspecialidadDAL usamos el patrón singleton en esta clase, la variable Mensaje servirá para almacenar los mensajes de éxito o error que podamos tener. La función Valida sirve para verificar que la especialidad a registrar y/o modificar traiga los campos obligatorios (Nombre y Descripción), el campo Id no se valida ya que esa validación se realiza en la línea 59, si una especialidad viene con el Id = -1 entonces es un nueva especialidad entonces se invoca a la función GrabarEspecialidad de la capa de datos, si la función nos retorna un valor mayor a 0 entonces el registro de la especialidad fue exitoso. En caso el campo Id tenga un valor entonces se trata de una modificación, entonces se invocará a la función EditarEspecialidad, si la función devuelve el valor true se retorna un mensaje de éxito. Independientemente de lo que pase al final la función, retorna el objeto resultado con la información de la acción de éxito (true o false) y un mensaje que se mostrará en la presentación.
Las demás funciones simplemente invocan a sus respectivas funciones de la capa de datos, no hay mucha magia en esa parte :).
Capa Presentación: Plugin DevExtreme, JqueryUI y DatePicker.
Vamos a utilizar el plugin DevExtreme para hacer uso del control Data Grid y así poder mostrar el listado de los datos de una manera fácil y sencilla. A continuación vamos a nuestra solución de visual y creamos la carpeta "DevExtreme", después descomprimimos los archivo del plugin y nos dirigimos a la carpeta Demos/WidgetsGallery y seleccionamos las carpetas "css" y "js" y con el cursor arrastramos hasta nuestra carpeta "DevExtreme" de nuestra capa de presentación.
Imagen 13: Carpeta DevExtreme en la capa presentación. (Fuente propia)
Imagen 14: archivos del plugin DevExtreme. (Fuente propia)
Imagen 16: Carpetas agregadas a la capa presentación
En el Web.config agregamos las siguiente líneas entre las etiquetas <system.webServer>:
quedaría así:
Imagen 17: Webconfig. (Fuente propia)
En la carpeta Scripts agregamos 3 archivos:
Ahora que ya tenemos los archivos necesarios para invocar a DevExtreme, solos nos queda agregarlo al html de nuestro layout.
Capa de Presentación: Controlador
Imagen 18: agregar referencia en capa presentación. (Fuente propia)
Imagen 19: agregar referencia a la capa componentes comunes. (Fuente propia)
Después de agregar la referencia lo que tenemos que hacer es agregar el controlador para las especialidades. Nos ubicaremos en la carpeta Controllers, damos clic derecho vamos a la opción Agregar -> Controlador.
A continuación haremos clic derecho sobre la función Index y agregaremos la vista.
Imagen 20: agregando controlador. (Fuente propia)
Imagen 21: Seleccionar controlador de mvc en blanco. (Fuente propia)
Imagen 22: Nombre del controlador. (Fuente propia)
A continuación haremos clic derecho sobre la función Index y agregaremos la vista.
Imagen 23: Agregar vista. (Fuente propia)
Imagen 24: seleccionar layout. (Fuente propia)
Imagen 25: seleccionar el archivo "_Layout.cshtml". (Fuente propia)
Imagen 26: crear vista Index. (Fuente propia)
Una vez creada la vista, ahora iremos al controlador y llamaremos a la funciones de la capa lógica, al final nuestro controlador tiene que quedar de la siguiente manera:
La única pantalla que manejaremos será Index, las demás funciones las invocaremos mediante AJAX para recolectar la información y mostrarla en la pantalla, así como las respuestas de las funciones.
Capa de Presentación: RouteConfig
Para que las llamadas a las vista index funcionen correctamente, tenemos que modificar el archivo RouteConfig que se encuentra en la carpeta App_Start.
Imagen 27: archivo RouteConfig.cs
el código que tenemos que agregar es la línea 15.
Capa de Presentación: Vista
En la vista simplemente ingresamos el siguiente html:
En la línea 13 invocamos un archivo JS, el cuál contiene toda la funcionalidad de la pantalla.
Capa de Presentación: Funcionalidad (JS)
Ahora nos toca crear la carpeta que contendrá los archivos JS de todas las vistas de nuestro proyecto. La carpeta se llamará "App_CodeJS", una vez creada la carpeta agregaremos la carpeta "Especialidades" en esta carpeta agregaremos el archivo "MantenedorEspecialidades.js".
El archivo MantenedorEspecialidades.js tiene el siguiente código:
Imagen 28: Agregar carpeta a capa presentación. (Fuente propia)
Imagen 29: Carpeta App_CodeJS. (Fuente propia)
Imagen 29: Agregar carpeta. (Fuente propia)
Imagen 31: Carpeta Especialidades. (Fuente propia)
Imagen 32: Agregar archivo Javascript. (Fuente propia)
Imagen 33: Archivo MantenedorEspecialidades. (Fuente propia)
El archivo MantenedorEspecialidades.js tiene el siguiente código:
Todo el código esta contenido dentro de una función anónima, la cuál contiene dos variables: item y model, la variable item sirve para contener la información que se enviará y/o traerá de la especialidad a registrar/editar, mientras que la variable model contiene las funciones que permiten interactuar al usuario con la vista.
Las funciones que contiene model, son las siguiente:
- ConfigurarGrilla: Esta función permite asignar la cantidad de columnas que tendrá el data grid.
- RecogerDatosFormulario: Esta función recoge los datos escritos en el formulario modal y lo inserta dentro de la variable especialidad.
- CargarLista: invoca a la función "ListarEspecialidades" del controlador y carga la información en el data grid.
- LimpiarDatosFormulario: Limpia los valores ingresados en los controles del modal.
- Guardar: Invoca a la función RecogerDatosFormulario y luego envia la información de la especialidad a la función "GrabarEspecialidad", al final la función retornará un objeto del tipo RespuestaSistema el cual contiene la propiedad Correcto, si esa propiedad es devuelta en true, entonces quiere decir que se ha grabado o modificado con éxito la especialidad.
- Nuevo: Invoca a la función LimpiarDatosFormulario y muestra el modal de especialidad.
- Cancelar: Oculta el modal de especialidad.
- Obtener: Recibe como parámetro el id de la especialidad a buscar, luego invoca a la función "ObtenerEspecialidad" y carga la información de la especialidad encontrada.
- MarcarMenu: Sirve para mantener seleccionado las opciones en el menú principal del sistema.
- Inicio: Invoca a función MarcarMenu, asigna las funciones a los eventos de los botones, crea el modal de especialidad, configura la grilla, obtiene la información de las especialidades registradas y finalmente muestra el contenido de la página.
Imagen 34: Vista Index de controlador Especialidad. (Fuente propia)
Imagen 35: Modal de editar especialidad. (Fuente propia)
Este tutorial esta muy bueno. Muy bien explicado por parte del autor
ResponderEliminar