domingo, 16 de abril de 2017

Xamarin, WCF, Stored Procedures y Entity Framework (Parte 1)

¡Hola! En días anteriores en el grupo de Facebook de Xamarin Diplomado ITC me hicieron una consulta sobre el uso de Xamarin con SQL, lo cual ya había publicado con anterioridad aquí. Como bien sabemos, lo ideal es NO hacer la conexión directa entre la app móvil y la base de datos, pues la cadena de conexión queda expuesta al ser incluida en la applicación, lo cual implica un alto riesgo a la seguridad de nuestra información.

Dado que la conversación siguió hasta tratar el tema de procedimientos almacenados (para las operaciones CRUD) y servicios WCF (para el acceso a la información) y en vista de que una actualización de la publicación de SQL era necesaria, pues he decidido hacer una serie titulada Xamarin, WCF, Stored Procedures y Entity Framework, la cual constará de 3 a 5 partes en la que construiremos una aplicación móvil que obtiene información de un servidor (primero local con IIS, luego lo montaremos a Azure) utilizando un servicio web.

El repositorio de GitHub donde actualizaré el proyecto poco a poco se encuentra aquí.

Consideraciones si descargas y quieres ejecutar la solución inmediatamente:

  • Ninguna, solo ejecuta el script de la base de datos :)


En cada parte trataremos un punto específico de la aplicación. ¿Listos? ¡Pues comenzamos!

En esta primer parte trabajaremos con algo sencillo: la base de datos. Solo necesitas tener SQL Server instalado, así como SQL Server Management Studio, desde donde escribiremos y ejecutaremos el script. Cualquier versión te sirve (2008, 2012, 2016... yo lo hice con 2012).


El script completo lo puedes bajar desde GitHub. Se encuentra ubicado en la carpeta BaseDatos. Simplemente descárgalo y ejecútalo por completo en SQL Server Management Studio.


Para este ejemplo definiremos una base de datos llamada Musica, la cual contiene 4 tablas muy sencillas: 

  • Artistas (Se define el nombre y nacionalidad)
  • Canciones (Consta de título y duración)
  • Conciertos (Contiene el artista, lugar y fecha del evento)
  • DetallesConcierto (Incluye la canción, el concierto y el orden de la canción en el evento)

Además, definiremos para este proyecto las siguientes especificaciones (las cuales puedes determinar a partir del diagrama anterior):

  • Un artista participa en N conciertos y un concierto incluye solo a un artista (Por tanto la relación es 1 a N).
  • Un concierto incluye N canciones y una canción puede ser interpretada en M conciertos (por tanto, existe una relación N a M, la cual crea la tabla asociativa DetallesConcierto).
  • No me gustan los nulos (xD), así que cada campo de las tablas NO admite nulos (obviamente en una implementación real dependerá de las reglas de negocio, tal vez un valor sí debe admitir nulos por alguna razón)

(Se dan clases de Bases de Datos por si algo no se comprendió, pregunte aquí jajaja)

Bien. Si se comprendieron las reglas anteriores, el script que permite definir la base de datos, las tablas y las relaciones anteriores se muestra a continuación:

/* Creación y uso de la base de datos Musica */
CREATE DATABASE Musica
GO

USE Musica
GO

/* Parte 1. Tablas */
CREATE TABLE Artistas(
  Id INT IDENTITY(1,1) PRIMARY KEY NOT NULL,
  Nombre VARCHAR(100) NOT NULL,
  Pais VARCHAR(100) NOT NULL
)

CREATE TABLE Canciones(
  Id INT IDENTITY(1,1) PRIMARY KEY NOT NULL,
  Titulo VARCHAR(200) NOT NULL,
  Duracion VARCHAR(10) NOT NULL
)

CREATE TABLE Conciertos(
  Id INT IDENTITY(1,1) PRIMARY KEY NOT NULL,
  IdArtista INT NOT NULL,
  Lugar VARCHAR(100) NOT NULL,
  Fecha SMALLDATETIME NOT NULL,
  CONSTRAINT FK_Artista FOREIGN KEY (IdArtista) REFERENCES Artistas(Id) ON DELETE CASCADE
)

CREATE TABLE DetallesConcierto(
  IdConcierto INT NOT NULL,
  IdCancion INT NOT NULL,
  Orden INT NOT NULL,
  CONSTRAINT FK_Concierto FOREIGN KEY (IdConcierto) REFERENCES Conciertos(Id) ON DELETE CASCADE,
  CONSTRAINT FK_Cancion FOREIGN KEY (IdCancion) REFERENCES Canciones(Id) ON DELETE CASCADE,
  CONSTRAINT PK_DetalleConcierto PRIMARY KEY (IdConcierto, IdCancion)
)
GO

Notas del script anterior:
  • Cada tabla (excepto DetallesConcierto) contiene un identificador autoincremental entero (lo definimos a partir del IDENTITY que servirá de llave primaria. Si bien es un esquema aceptado, en muchas ocasiones se sugiere el uso de Unique identifiers (GUID) secuenciales (SQL Azure lo maneja así). Para mantener la simplicidad en esta serie, lo dejaremos así con IDENTITY y en una futura publicación hablaré de estos identificadores GUID.

  • Las llaves foráneas han sido definidas como una CONSTRAINT que incluye el borrado en cascada (ON DELETE CASCADE). Esto quiere decir que si por ejemplo se elimina un Artista de la tabla, automáticamente se eliminarán los conciertos en los que haya sido registrado.


Ahora que las tablas han sido definidas, vamos a lo bueno de esta publicación. Para realizar las operaciones CRUD (Create, Read, Update y Delete) sobre las tablas, definiremos Procedimientos Almacenados (Stored Procedures), los cuales permiten definir operaciones parametrizadas a realizar sobre las tablas en el gestor de base de datos. Esto permite que en las llamadas a las operaciones, solo se envíen los valores (parámetros) en lugar de una instrucción SQL (es inseguro enviar la consulta como cadena porque puede ser interceptada, mejor enviamos la llamada a un procedimiento almacenado).

Sin embargo, vamos a complicarlo un poquito jeje, pues fue uno de los requerimientos que me preguntaron :)

¿Podemos definir un procedimiento almacenado que devuelva 2 cosas al mismo tiempo? 

  • Primero, un valor 1 o 0 en caso de éxito o fracaso en la operación, respectivamente.
  • Y segundo, un mensaje que indique lo mismo, que la operación se realizó correctamente o con error.

La respuesta es que si se puede. Para el primer caso utilizaremos la instrucción RETURN, mientras que para el segundo definiremos un parámetro OUTPUT (de salida) en la definición del procedimiento almacenado. Va la explicación:

  • Cuando llamamos un procedimiento almacenado, normalmente se devuelve el resultado de una consulta o un valor utilizando la instrucción RETURN. Esto es como en programación, cuando un metodo retorna un valor entero, cadena, objeto, etc.

  • Todo mundo conoce los parámetros de entrada al llamara una función o procedimiento almacenado. Son los valores que se están enviando al método para realizar algo. Sin embargo, existen también los parámetros de salida (OUTPUT) que funcionan en dos sentidos: cumplen la función de parámetro de entrada (es decir, envían algo al método) pero al finalizar su ejecución, su valor también podrá ser recuperado en la llamada al método.

Expliquémoslo mejor con el siguiente script que agrega un nuevo artista a la tabla: 

CREATE PROCEDURE Procedimiento_AgregarArtista (@Nombre VARCHAR(100), @Pais VARCHAR(100), @mensaje VARCHAR(MAX) OUTPUT)
AS
  SET NOCOUNT ON
  BEGIN TRANSACTION
    INSERT INTO Artistas VALUES (@Nombre, @Pais)
    IF @@error = 0
   BEGIN
     SELECT @mensaje = 'Correcto'
   END
    ELSE
   BEGIN
     SELECT @mensaje = 'Error al insertar'
     ROLLBACK TRANSACTION
     RETURN 0
   END
  COMMIT TRANSACTION
  RETURN SCOPE_IDENTITY()
GO


  • Línea 1: Se define el procedimiento almacenado con 2 parámetros de entrada (Nombre y Pais) y 1 de salida (mensaje)
  • Línea 3: Se indica al gestor que no muestre la salida de contador de resultados (ése que luego dice 5 registros afectados).
  • Línea 4: Comienza la transacción. Si la operación es exitosa se confirma la transacción haciendo Commit (línea 16) y en caso de error, se deshacen los cambios mediante un Rollback (línea 13)
  • Línea 5: Se indica la operación a realizar: Es un Insert sobre la tabla Artistas indicando el nombre y nacionalidad a registrar.
  • Línea 6: La variable @@error indica si la operación anterior fue un éxito (contiene cero) o fracaso (contiene un valor distinto de cero), por lo que es necesario comprobar su valor mediante la sentencia IF.
  • Líneas 8 y 12: Se establece el valor de la variable de salida @mensaje, pasando una cadena de texto de acuerdo al resultado de la operación.
  • Líneas 13 y 14: Si el insert falló, se hace rollback en la transacción y se retorna 0 (fracaso).
  • Líneas 16 y 17: Si el insert fue exitoso, se hace commit de la operación y se retorna el ID del registro insertado mediante la instrucción Scope_Identity, lo cual es útil cuando se quiere agregar más información del registro recién insertado.

Vamos a demostrar su funcionamiento. Para ello, pues ejecutamos el siguiente script:

DECLARE @Id INT
DECLARE @Nombre VARCHAR(100)
DECLARE @Pais VARCHAR(100)
DECLARE @mensaje VARCHAR(MAX) 

SET @Nombre = 'Katie Melua'
SET @Pais = 'Georgia'
EXEC @Id = Procedimiento_AgregarArtista @Nombre, @Pais, @mensaje OUTPUT

SELECT @Id AS ID, @mensaje AS Mensaje
GO


  • Línea 1: Se define la variable Id para recuperar el valor del registro insertado
  • Líneas 2 y 3: Se definen las variables Nombre y Pais, que se pasarán al procedimiento almacenado
  • Línea 4: Se define la variable mensaje, que se pasará al procedimiento almacenado y al finalizar su llamada tendrá un valor indicando si la operación funcionó o no.
  • Líneas 6 y 7: Se establecen los valores de Nombre y Pais
  • Línea 8: Previo a hacer la llamada (EXEC) del procedimiento almacenado, se asigna a la variable Id el valor de retorno. Además, se envían los parámetros Nombre, Pais y mensaje, pero a éste último se le agrega el modificador OUTPUT para indicar que es de salida y contendrá un valor al final.
  • Línea 10: Se muestra en pantalla los valores de las variables Id y mensaje.  
El resultado de la ejecución lo puedes ver a continuación, indicando éxito en la operación:


A continuación te presento el script completo de los procedimientos almacenados, los cuales incluyen su demostración al finalizar, considerando que se definen los siguientes procedimientos almacenados:


  • Procedimiento_Obtener[Tabla]. Es un simple Select * From que devuelve toda la información de la tabla respectiva ordenada por un campo específico.
  • Procedimiento_Buscar[Tabla]. Devuelve un registro específico, determinado por el parámetro Id
  • Procedimiento_Agregar[Tabla]. Define la operación Insert sobre la tabla específica.
  • Procedimiento_Modificar[Tabla]. Define la operación Update sobre la tabla específica.
  • Procedimiento_Eliminar[Tabla]. Define la operación Delete sobre la tabla específica.

En total, crearemos 19 procedimientos almacenados.

El código completo de los procedimientos almacenados se muestra a continuación:

CREATE PROCEDURE Procedimiento_ObtenerArtistas
AS
  SELECT * FROM Artistas ORDER BY Nombre
GO

CREATE PROCEDURE Procedimiento_BuscarArtista (@Id INT)
AS
  SELECT * FROM Artistas WHERE Id = @Id 
GO

CREATE PROCEDURE Procedimiento_AgregarArtista (@Nombre VARCHAR(100), @Pais VARCHAR(100), @mensaje VARCHAR(MAX) OUTPUT)
AS
  SET NOCOUNT ON
  BEGIN TRANSACTION
    INSERT INTO Artistas VALUES (@Nombre, @Pais)
    IF @@error = 0
   BEGIN
     SELECT @mensaje = 'Correcto'
   END
    ELSE
   BEGIN
     SELECT @mensaje = 'Error al insertar'
  ROLLBACK TRANSACTION
  RETURN 0
   END
  COMMIT TRANSACTION
  RETURN SCOPE_IDENTITY()
GO

CREATE PROCEDURE Procedimiento_ModificarArtista (@Id INT, @Nombre VARCHAR(100), @Pais VARCHAR(100), @mensaje VARCHAR(MAX) OUTPUT)
AS
  SET NOCOUNT ON
  BEGIN TRANSACTION
    UPDATE Artistas SET Nombre = @Nombre, Pais = @Pais WHERE Id = @Id
    IF @@ERROR = 0 AND @@ROWCOUNT <> 0
   BEGIN
     SELECT @mensaje = 'Correcto'
   END
    ELSE
   BEGIN
     SELECT @mensaje = 'Error al modificar'
  ROLLBACK TRANSACTION
  RETURN 0
   END
  COMMIT TRANSACTION
  RETURN 1
GO

CREATE PROCEDURE Procedimiento_EliminarArtista (@Id INT, @mensaje VARCHAR(MAX) OUTPUT)
AS
  SET NOCOUNT ON
  BEGIN TRANSACTION
    DELETE FROM Artistas WHERE Id = @Id
    IF @@ERROR = 0
   BEGIN
     SELECT @mensaje = 'Registro eliminado correctamente'
   END
    ELSE
   BEGIN
     SELECT @mensaje = 'Error al eliminar'
  ROLLBACK TRANSACTION
  RETURN 0
   END
  COMMIT TRANSACTION
  RETURN 1
GO

/* b. Tabla Canciones */
CREATE PROCEDURE Procedimiento_ObtenerCanciones
AS
  SELECT * FROM Canciones ORDER BY Titulo
GO

CREATE PROCEDURE Procedimiento_BuscarCancion (@Id INT)
AS
  SELECT * FROM Canciones WHERE Id = @Id 
GO

CREATE PROCEDURE Procedimiento_AgregarCancion (@Titulo VARCHAR(200), @Duracion VARCHAR(10), @mensaje VARCHAR(MAX) OUTPUT)
AS
  SET NOCOUNT ON
  BEGIN TRANSACTION
    INSERT INTO Canciones VALUES (@Titulo, @Duracion)
    IF @@error = 0
   BEGIN
     SELECT @mensaje = 'Correcto'
   END
    ELSE
   BEGIN
     SELECT @mensaje = 'Error al insertar'
  ROLLBACK TRANSACTION
  RETURN 0
   END
  COMMIT TRANSACTION
  RETURN SCOPE_IDENTITY()
GO

CREATE PROCEDURE Procedimiento_ModificarCancion (@Id INT, @Titulo VARCHAR(200), @Duracion VARCHAR(10), @mensaje VARCHAR(MAX) OUTPUT)
AS
  SET NOCOUNT ON
  BEGIN TRANSACTION
    UPDATE Canciones SET Titulo = @Titulo, Duracion = @Duracion WHERE Id = @Id
    IF @@ERROR = 0 AND @@ROWCOUNT <> 0
   BEGIN
     SELECT @mensaje = 'Correcto'
   END
    ELSE
   BEGIN
     SELECT @mensaje = 'Error al modificar'
  ROLLBACK TRANSACTION
  RETURN 0
   END
  COMMIT TRANSACTION
  RETURN 1
GO

CREATE PROCEDURE Procedimiento_EliminarCancion (@Id INT, @mensaje VARCHAR(MAX) OUTPUT)
AS
  SET NOCOUNT ON
  BEGIN TRANSACTION
    DELETE FROM Canciones WHERE Id = @Id
    IF @@ERROR = 0
   BEGIN
     SELECT @mensaje = 'Registro eliminado correctamente'
   END
    ELSE
   BEGIN
     SELECT @mensaje = 'Error al eliminar'
  ROLLBACK TRANSACTION
  RETURN 0
   END
  COMMIT TRANSACTION
  RETURN 1
GO

/* c. Tabla Conciertos */
CREATE PROCEDURE Procedimiento_ObtenerConciertos
AS
  SELECT * FROM Conciertos ORDER BY Fecha 
GO

CREATE PROCEDURE Procedimiento_BuscarConcierto (@Id INT)
AS
  SELECT * FROM Conciertos WHERE Id = @Id 
GO

CREATE PROCEDURE Procedimiento_AgregarConcierto (@IdArtista INT, @Lugar VARCHAR(100), @Fecha SMALLDATETIME, @mensaje VARCHAR(MAX) OUTPUT)
AS
  SET NOCOUNT ON
  BEGIN TRANSACTION
    INSERT INTO Conciertos VALUES (@IdArtista, @Lugar, @Fecha)
    IF @@error = 0
   BEGIN
     SELECT @mensaje = 'Correcto'
   END
    ELSE
   BEGIN
     SELECT @mensaje = 'Error al insertar'
  ROLLBACK TRANSACTION
  RETURN 0
   END
  COMMIT TRANSACTION
  RETURN SCOPE_IDENTITY()
GO

CREATE PROCEDURE Procedimiento_ModificarConcierto (@Id INT, @IdArtista INT, @Lugar VARCHAR(100), @Fecha SMALLDATETIME, @mensaje VARCHAR(MAX) OUTPUT)
AS
  SET NOCOUNT ON
  BEGIN TRANSACTION
    UPDATE Conciertos SET IdArtista = @IdArtista, Lugar = @Lugar, Fecha = @Fecha WHERE Id = @Id
    IF @@ERROR = 0 AND @@ROWCOUNT <> 0
   BEGIN
     SELECT @mensaje = 'Correcto'
   END
    ELSE
   BEGIN
     SELECT @mensaje = 'Error al modificar'
  ROLLBACK TRANSACTION
  RETURN 0
   END
  COMMIT TRANSACTION
  RETURN 1
GO

CREATE PROCEDURE Procedimiento_EliminarConcierto (@Id INT, @mensaje VARCHAR(MAX) OUTPUT)
AS
  SET NOCOUNT ON
  BEGIN TRANSACTION
    DELETE FROM Conciertos WHERE Id = @Id
    IF @@ERROR = 0
   BEGIN
     SELECT @mensaje = 'Registro eliminado correctamente'
   END
    ELSE
   BEGIN
     SELECT @mensaje = 'Error al eliminar'
  ROLLBACK TRANSACTION
  RETURN 0
   END
  COMMIT TRANSACTION
  RETURN 1
GO

/* d. Tabla DetallesConcierto */
CREATE PROCEDURE Procedimiento_ObtenerDetallesConcierto (@IdConcierto INT)
AS
  SELECT * FROM DetallesConcierto WHERE IdConcierto = @IdConcierto ORDER BY Orden
GO

CREATE PROCEDURE Procedimiento_AgregarDetalleConcierto (@IdConcierto INT, @IdCancion INT, @Orden INT, @mensaje VARCHAR(MAX) OUTPUT)
AS
  SET NOCOUNT ON
  BEGIN TRANSACTION
    INSERT INTO DetallesConcierto VALUES (@IdConcierto, @IdCancion, @Orden)
    IF @@error = 0
   BEGIN
     SELECT @mensaje = 'Correcto'
   END
    ELSE
   BEGIN
     SELECT @mensaje = 'Error al insertar'
  ROLLBACK TRANSACTION
  RETURN 0
   END
  COMMIT TRANSACTION
  RETURN 1
GO

CREATE PROCEDURE Procedimiento_ModificarDetalleConcierto (@IdConcierto INT, @IdCancion INT, @Orden INT, @mensaje VARCHAR(MAX) OUTPUT)
AS
  SET NOCOUNT ON
  BEGIN TRANSACTION
    UPDATE DetallesConcierto SET Orden = @Orden WHERE IdConcierto = @IdConcierto AND IdCancion = @IdCancion
    IF @@ERROR = 0 AND @@ROWCOUNT <> 0
   BEGIN
     SELECT @mensaje = 'Correcto'
   END
    ELSE
   BEGIN
     SELECT @mensaje = 'Error al modificar'
  ROLLBACK TRANSACTION
  RETURN 0
   END
  COMMIT TRANSACTION
  RETURN 1
GO

CREATE PROCEDURE Procedimiento_EliminarDetalleConcierto (@IdConcierto INT, @IdCancion INT, @mensaje VARCHAR(MAX) OUTPUT)
AS
  SET NOCOUNT ON
  BEGIN TRANSACTION
    DELETE FROM DetallesConcierto WHERE IdConcierto = @IdConcierto AND IdCancion = @IdCancion
    IF @@ERROR = 0
   BEGIN
     SELECT @mensaje = 'Registro eliminado correctamente'
   END
    ELSE
   BEGIN
     SELECT @mensaje = 'Error al eliminar'
  ROLLBACK TRANSACTION
  RETURN 0
   END
  COMMIT TRANSACTION
  RETURN 1
GO

Código completo de las demostraciones.

/* Parte 3. Probar procedimientos almacenados */
/* a. Procedimientos de Tabla Artista */

DECLARE @Id INT
DECLARE @Nombre VARCHAR(100)
DECLARE @Pais VARCHAR(100)
DECLARE @mensaje VARCHAR(MAX) 

SET @Nombre = 'Katie Melua'
SET @Pais = 'Georgia'
EXEC @Id = Procedimiento_AgregarArtista @Nombre, @Pais, @mensaje OUTPUT

SELECT @Id AS ID, @mensaje AS Mensaje
GO

DECLARE @Id INT
DECLARE @Nombre VARCHAR(100)
DECLARE @Pais VARCHAR(100)
DECLARE @mensaje VARCHAR(MAX) 

SET @Nombre = 'The Corrs'
SET @Pais = 'Irlanda'
EXEC @Id = Procedimiento_AgregarArtista @Nombre, @Pais, @mensaje OUTPUT

SELECT @Id AS ID, @mensaje AS Mensaje
GO

EXEC Procedimiento_ObtenerArtistas
GO

DECLARE @Id INT
DECLARE @Nombre VARCHAR(100)
DECLARE @Pais VARCHAR(100)
DECLARE @mensaje VARCHAR(MAX) 
DECLARE @resultado INT

SET @Nombre = 'Katie Melua'
SET @Pais = 'Gran Bretaña'
SET @Id = 1

EXEC @resultado = Procedimiento_ModificarArtista @Id, @Nombre, @Pais, @mensaje OUTPUT

SELECT @resultado AS Resultado, @mensaje AS Mensaje

EXEC Procedimiento_BuscarArtista @Id
GO

DECLARE @Id INT
DECLARE @mensaje VARCHAR(MAX) 
DECLARE @resultado INT

SET @Id = 2

EXEC @resultado = Procedimiento_EliminarArtista @Id, @mensaje OUTPUT

SELECT @resultado AS Resultado, @mensaje AS Mensaje

EXEC Procedimiento_BuscarArtista @Id
GO

DECLARE @mensaje VARCHAR(MAX)
EXEC Procedimiento_AgregarArtista 'The Corrs', 'Irlanda', @mensaje OUTPUT
EXEC Procedimiento_AgregarArtista 'Michael Buble', 'Canada', @mensaje OUTPUT
EXEC Procedimiento_ObtenerArtistas
GO

/* b. Procedimientos de Tabla Canciones */
DECLARE @mensaje VARCHAR(MAX)
EXEC Procedimiento_AgregarCancion 'Better than a dream', '03:16', @mensaje OUTPUT
EXEC Procedimiento_AgregarCancion 'The bit that I don''t get', '03:06', @mensaje OUTPUT
EXEC Procedimiento_AgregarCancion 'What I miss about you', '03:47', @mensaje OUTPUT
EXEC Procedimiento_AgregarCancion 'Nine million bicycles', '03:14', @mensaje OUTPUT
EXEC Procedimiento_AgregarCancion 'I Cried for you', '03:42', @mensaje OUTPUT
EXEC Procedimiento_AgregarCancion 'Only when I sleep', '03:51', @mensaje OUTPUT
EXEC Procedimiento_AgregarCancion 'Somebody for someone', '04:06', @mensaje OUTPUT
EXEC Procedimiento_AgregarCancion 'Radio', '04:15', @mensaje OUTPUT
EXEC Procedimiento_AgregarCancion 'Song for you', '04:06', @mensaje OUTPUT
EXEC Procedimiento_AgregarCancion 'Everything', '03:33', @mensaje OUTPUT
EXEC Procedimiento_ObtenerCanciones
GO

/* c. Procedimientos de Tabla Conciertos */
DECLARE @mensaje VARCHAR(MAX)
EXEC Procedimiento_AgregarConcierto 1, 'Londres', '08-Nov-2008', @mensaje OUTPUT
EXEC Procedimiento_AgregarConcierto 1, 'Utretcht', '01-Nov-2016', @mensaje OUTPUT
EXEC Procedimiento_AgregarConcierto 3, 'Dublín', '12-Nov-1999', @mensaje OUTPUT
EXEC Procedimiento_AgregarConcierto 3, 'Dublín', '06-Nov-2001', @mensaje OUTPUT
EXEC Procedimiento_AgregarConcierto 4, 'Nueva York', '15-Jun-2009', @mensaje OUTPUT
EXEC Procedimiento_ObtenerConciertos
GO

/* d. Procedimientos de Tabla DetallesConcierto */
DECLARE @mensaje VARCHAR(MAX)
EXEC Procedimiento_AgregarDetalleConcierto 1, 4, 16, @mensaje OUTPUT
EXEC Procedimiento_AgregarDetalleConcierto 1, 5, 19, @mensaje OUTPUT
EXEC Procedimiento_AgregarDetalleConcierto 2, 1, 1, @mensaje OUTPUT
EXEC Procedimiento_AgregarDetalleConcierto 2, 2, 2, @mensaje OUTPUT
EXEC Procedimiento_AgregarDetalleConcierto 2, 3, 3, @mensaje OUTPUT
EXEC Procedimiento_AgregarDetalleConcierto 3, 6, 1, @mensaje OUTPUT
EXEC Procedimiento_AgregarDetalleConcierto 3, 8, 3, @mensaje OUTPUT
EXEC Procedimiento_AgregarDetalleConcierto 4, 6, 1, @mensaje OUTPUT
EXEC Procedimiento_AgregarDetalleConcierto 4, 7, 8, @mensaje OUTPUT
EXEC Procedimiento_AgregarDetalleConcierto 5, 9, 10, @mensaje OUTPUT
EXEC Procedimiento_AgregarDetalleConcierto 5, 10, 8, @mensaje OUTPUT
EXEC Procedimiento_ObtenerDetallesConcierto 1
EXEC Procedimiento_ObtenerDetallesConcierto 2
EXEC Procedimiento_ObtenerDetallesConcierto 3
EXEC Procedimiento_ObtenerDetallesConcierto 4
EXEC Procedimiento_ObtenerDetallesConcierto 5
GO

En imágenes:

Agregando un artista


Obteniendo la lista de artistas registrados


Actualizando la información de un artista y mostrando el valor modificado


Eliminando un artista y mostrando que ya no existe


Agregando más artistas y mostrando los datos de la tabla


Agregando canciones y mostrando los datos de la tabla


Agregando conciertos y mostrando los datos de la tabla


Agregando detalles de concierto y mostrando los datos de la tabla


Recuerda que el código completo del script lo puedes obtener desde el repositorio de GitHub creado para este proyecto.

Con esto concluimos con la primer parte del demo. El día de mañana crearemos el servicio WCF que actuará de intermediario entre las aplicaciones y la base de datos.

Si tienes alguna sugerencia, recomendación, comentario o algún paso no te funcionó, házmelo saber y con gusto te atenderé :) déjame un comentario y aquí lo revisamos.

Espero esta entrada te haya sido de utilidad, y si fue así, no dudes en compartirla :)

Te recuerdo que la experiencia de aprendizaje continúa con el #XamarinDiplomado. Únete a nuestro grupo de estudio en Facebook, donde además de hablar del diplomado de Xamarin 3.0 impartido por Microsoft, también comentamos sobre otras oportunidades de aprendizaje, trabajo, resolvemos dudas y compartimos el conocimiento.

¡Saludos y hasta pronto!

11 comentarios:

  1. Hola que tal, oye una pregunta (no exactamente acerca del curso). Que tal es el proceso para adquirir la certificacion Xamarin?? Tiene algun Costo?? Como es que se valida??

    ResponderEliminar
    Respuestas
    1. Hola, como bien comenta Luis Vega, la certificación de Xamarin es a través de Xamarin University, cuya suscripción tiene costo. Como se anuncia en la página oficial (https://www.xamarin.com/university) la suscripción cuesta 83.25 USD mensuales, incluye las clases y el examen (3 intentos, me parece). Para validarla puedes ingresar a https://university.xamarin.com/certification#verify y colocar el correo del desarrollador, asi aparecerá la validez del mismo.

      Eliminar
  2. Hola Ben, la certificacion si no me equivoco lo puedes obtener en Xamarin University (tiene costo), o en todo caso hay varias paginas de personas con mucho conocimiento en xamarin como Luis Beltran que brindan cursos gratuitos de desarrollo xamarin.

    ResponderEliminar
    Respuestas
    1. En efecto, lo que comentas de Xamarin University es correcto; también puedes capacitarte con los diplomados, cursos y revisando nuestras publicaciones :)

      Eliminar
  3. Favor, publiquen el link aquí mañana para darle seguimiento, estoy muy emocionado por seguir este proceso para hacer un proyecto que tengo de WCF a Xamarin

    ResponderEliminar
    Respuestas
    1. Visita el blog en unas horas, estara disponible la parte 2 :) de igual forma lo publicaré en los diferentes grupos de Xamarin en Facebook.

      Eliminar
  4. Mencionabas que no era un curso de BD, en mi opinión si, aunque más Transact-SQL. Gracias por el aporte.

    ResponderEliminar
  5. Sinceramente es maravilloso este curso estoy empezando en este entorno de Xamarin me parece interesante y estoy muy emocionado esperando la segunda parte por favor para seguir con este mundo maravilloso que es programar...
    Gracias por compartir conocimiento Amigo

    ResponderEliminar
    Respuestas
    1. Agradezco tus comentarios, la segunda parte ya está publicada en la el siguiente enlace: http://icebeamwp.blogspot.cz/2017/04/xamarin-wcf-sp-ef-parte2.html Saludos y gracias a tí por leer el blog :)

      Eliminar
  6. Tu muy bien ;)
    Saludos desde Mexico =P

    ResponderEliminar
    Respuestas
    1. Gracias a tí por la idea (y preguntas) ^_^ Saludos desde República Checa :D

      Eliminar