Translate

lunes, 12 de agosto de 2013

Creando un sitio web ASP .Net. Parte 3

Roque Rueda
Mi hermano me solicito que le creara un sitio web para venta de ropa así que para apoyarle he decidido crear un sitio web ASP .net en donde el pueda promocionar las ventas.
En el post pasado se creó la estructura de base de datos pero ahora la base de datos usualmente debe contener restricciones para los datos, esto con la finalidad de asegurar que los datos almacenados sean correctos, lo primero que vamos a hacer es crear los scripts para indicar las reglas de los datos en las tablas que tenemos.

Primero tomaremos la tabla Client la cual no pensaremos de momento en sus relaciones si no únicamente en los valores que vamos a permitir sean almacenados.


En este caso debido a que deseamos utilizar una función para validar los datos del email de los clientes y SQLServer no contiene por defecto el soporte para expresiones regulares vamos a crear una función y la vamos a utilizar cuando sea requerido.

Para esto vamos a crear presionar "New Query" lo que nos muestra una ventana donde se pueden ejecutar comandos SQL.



Vamos a escribir en nuestra ventana el siguiente código:

sp_configure 'clr enabled', 1
GO
RECONFIGURE
GO

  

Aquí estamos modificando que se habilite clr que es la capacidad para la ejecución de funciones hechas a mano. Ahora para ejecutar todo el script vamos a presionar F5 con lo que se nos va a mostrar algo como lo siguiente:


Ahora se debe crear el código del proyecto para esto vamos a crear un proyecto de biblioteca de clases y vamos a agregar los métodos que serán las funciones SQL en el futuro (estos métodos deben ser estáticos). Vamos a crear un nuevo proyecto en visual studio iniciando como siempre con una solucion en blanco.



La cual vamos a llamar RegexSqlFunctions, una vez que se nos muestre nuestro explorador de soluciones vamos a agregar un nuevo proyecto.



Vamos a agregar el proyecto de biblioteca de clases y lo llamaremos RegexFuntions. Quedando nuestro explorador de soluciones de la siguiente manera:


Ahora lo que debemos agregar también ya que estamos siguiendo la forma de trabajo  TDD (desarrollo dirigido por pruebas) es contar con otro proyecto el cual será un proyecto de pruebas el cual va a asegurar los resultados de la ejecución de nuestro código.


Ahora bien debemos agregar la referencia a nuestro proyecto de pruebas una vez hecho esto vamos a poder llamar realizar pruebas al código de nuestra biblioteca de clases. También vamos a cambiar el nombre de las clases de nuestros 2 proyectos para que tengan un mejor significado. Vamos a nombrar Regex a la clase de nuestra biblioteca de clases y RegexTest a la de nuestro proyecto de pruebas.


Debemos agregar la referencia a System.Data, donde vamos a agregar los siguientes espacios de nombres.

using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using System.Text.RegularExpressions;
using Microsoft.SqlServer.Server;
using Microsoft.VisualStudio.TestTools.UnitTesting;

Ahora vamos a pensar en nuestra prueba para esto vamos a pensar en el valor de retorno de nuestro método, para este caso True o False sin embargo para SQLServer no se puede utilizar un boolean de C# se debe retornar el tipo SqlBoolean el cual representa un verdadero o falso para SQLServer.
Ahora el codigo para nuestra pruena quedara como se muestra a continuacion:
using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using System.Text.RegularExpressions;
using Microsoft.SqlServer.Server;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using RegexFunctions;

namespace RegexFunctionTest
{
    [TestClass]
    public class RegexTest
    {
        [TestMethod]
        public void MatchTest()
        {
            // Arrange
            var expected = new SqlBoolean(true);
            string value = "skaroque@gmail.com";
            string pattern = @"^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|" +
            @"(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$";

            // Act
            SqlBoolean actual = SQLRegex.MatchRegex(value, pattern);

            // Assert
            Assert.AreEqual(expected, actual);
        }
    }
}



Como se puede ver este método no existe también nótese que se está accediendo a él de forma estática y le estamos dando los nombres a los parámetros que deseamos que aparezcan en la firma del método; todo esto nos ayuda a que visual studio nos genere el método con la firma adecuada. Para que nos genere el código vamos a hacer clic derecho sobre el método. Y seleccionamos Generate method stub.
Ahora nuestra clase la he renombrado como SQLRegex para eviar la colicion de nombres y he agregado el código para la clase con lo siguiente:



/*
 * Copyright 2013 Roque Rueda.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlTypes;
using System.Text.RegularExpressions;

namespace RegexFunctions
{
    /// 
    /// Regex function for SQLServer.
    /// 
    public partial class SQLRegex
    {
        /// 
        /// Evaluates if the value parameter match with the pattern.
        /// 
        /// The string value to ve evaluated.
        /// Pattern that is going to be find in the value.
        ///  indicating if the value match the pattern.
        /// 
        [Microsoft.SqlServer.Server.SqlFunction]
        public static SqlBoolean MatchRegex(SqlString value, SqlString pattern)
        {
            return new SqlBoolean(Regex.IsMatch(value.Value, pattern.Value));
        }
    }
}

Ahora vamos a ejecutar las pruebas a nuestra clase. Para verificar su correcto o incorrecto funcionamiento. Para esto agregamos el siguiente método y ejecutamos las pruebas.

using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using System.Text.RegularExpressions;
using Microsoft.SqlServer.Server;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using RegexFunctions;

namespace RegexFunctionTest
{
    [TestClass]
    public class RegexTest
    {
        [TestMethod]
        public void MatchTest()
        {
            // Arrange
            SqlBoolean expected = new SqlBoolean(true);
            string value = "skaroque@gmail.com";
            string pattern = @"^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|" +
            @"(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$";

            // Act
            SqlBoolean actual = SQLRegex.MatchRegex(value, pattern);

            // Assert
            Assert.AreEqual(expected, actual);
        }

        [TestMethod]
        public void NotMatchTest()
        { 
            // Arrange
            SqlBoolean expected = new SqlBoolean(false);
            string vale = "skaroquegmail.com";
            string pattern = @"^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|" +
            @"(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$";

            //Act
            SqlBoolean actual = SQLRegex.MatchRegex(vale, pattern);

            // Assert
            Assert.AreEqual(expected, actual);
        }
    }
}



Verificamos que las pruebas sean satisfactorias. Ahora para que nuestra biblioteca sea registrada debe estar en el framework 3.5 por lo que vamos a hacer clic derecho en nuestro proyecto y vamos a seleccionar propiedades del menú desplegable. Y modificaremos del framework 4.5 al 3.5.



Ahora que nuestras pruebas son satisfactorias vamos a proceder a registrar nuestra funcion clr para esto vamos a ejecutar el siguiente comando en SQLServer:

CREATE ASSEMBLY
-- name of the assembly from SQL
RegexFunctions
AUTHORIZATION [dbo]
-- full path of the aseembly
from 'C:\Projects\SqlServer\RegexFunctions.dll'
WITH PERMISSION_SET = SAFE

Y si todo es correcto debemos obtener el siguiente mensaje de respuesta:
Command(s) completed successfully.
Esto nos indica que nuestra biblioteca ya se registro en SQLServer (Para borrar el registro de nuestra biblioteca debemos ejecutar un "drop asembly <nombre>"). Ahora solo debemos crear la función (liga nuestro método de la dll a una función de sql) para lo cual vamos a ejecutar el siguiente script:
-- function name like an alias
CREATE FUNCTION RegExp(@Text nvarchar(max), @Pattern nvarchar(255))
RETURNS BIT
-- dll
AS EXTERNAL NAME RegexFunctions.[RegexFunctions.SQLRegex].MatchRegex
GO
Con esto ya podremos ejecutar operaciones llamando a la función que hemos creado. 


Ya podemos visualizar la función dentro de las Funciones de nuestra base de datos. Para ejecutarla podemos hacer clic derecho sobre la función y seleccionamos script comand as.


Y solo debemos agregar los valores que deseamos para probar nuestra funcion.

SELECT [dbo].[RegExp] (
  'skaroque@gmail.com'
  ,'^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$')
GO
La ejecutamos y veremos algo como lo siguiente:


Eso será todo por el momento en el siguiente post vamos a utilizar esta y otras funciones para asegurarnos de la integridad de los datos de nuestra base de datos.