martes, 24 de mayo de 2011

Resumen de ASP.NET con SQL Server Compact Edition 4.0

Ya estamos preparados para nuestro primer proyecto web con SQL Server CE 4.0.

Si recordáis, en anteriores post hablamos ya sobre CE y sobre como romper el hielo por primera vez con esta base de datos y sobre como desplegar nuestra aplicación en un entorno de hosting compartido sin necesidad de que esté instalado CE en el equipo host.

Ahora que un compañero se ha incorporado al proyecto, ha tenido que preparar su máquina y siendo así, ha sido un momento excepcional para hacer un post resumen de “preparación a CE”. Además, al final del post también haremos un resumen sobre despliegue para que queda todo reflejado en un solo post, tanto instalación como despliegue. Los pasos que hemos seguido han sido los siguientes:

Instalar (si es que aún no lo tenías instalado), Visual Studio 2010 Service Pack 1. Lo puedes descargar desde este enlace o desde WPI (Web Platform Installer).

Instalar SQL Server CE 4.0. De nuevo, podemos elegir entre la descarga directa desde aquí aquí, o instalarlo desde WPI. A mí la verdad es que WPI me da más seguridad porque detecta dependencias entre paquetes y si es necesario las instala también.

clip_image002

Si eres un estudioso y te gusta tener la documentación del producto instalada en tu equipo, también puedes descargar los BOL (Book On Line) de CE desde aquí. Por supuesto, este paso es opcional.

En este momento ya tienes instalado el CE en tu equipo, pero para poder trabajar con CE necesitarás, bien WebMatrix (que fue el primer producto en dar soporte a CE 4.0, pero yo no quiero verlo ni en pintura) o bien instalar Visual Studio 2010 SP1 Tools for SQL Server Compact 4.0, de nuevo desde WPI.

clip_image004

clip_image006

Lo cierto es que, aunque el add-in, add-on, plug-in o como quieras llamarlo, de Visual Studio es suficiente, hay otra herramienta que es must-have y que es SQL Server Compact Toolbox. Está disponible en codeplex  en http://sqlcetoolbox.codeplex.com/ o también desde el administrador de extensiones de Visual Studio. Insisto es que un aplicación muy interesante y que viene a complementar la ya existente en VS.

clip_image008

Por último, si estás utilizando Membership en tu proyecto de ASP.NET, hay que agradecer hasta el infinito y más allá, la aportación de un proveedor de Membership, Role y Profile que se han trabajado en http://sqlcemembership.codeplex.com/.

De hecho, el autor de este proyecto es el mismo que el del add-in SQL Server Compact Toolbox. Su web es http://erikej.blogspot.com/ y es toda una página de referencia sobre CE. También te puedes fijar que en codeplex tiene abiertos más proyectos, todos ellos relativos a CE… y digo yo… ¿Por qué no lo contrata Microsoft? ¿O es que Microsoft le despidió porque sabía demasiado? ;-)

Si hablamos ahora del despliegue, nosotros con ASP.NET 3.5 (creo que con ASP.NET 4.0 serían los mismos pero no puede asegurarlo) y proyecto de sitio web (no he podido hacerlo funcionar en una aplicación web y sigo sin poder hacerlo funcionar) son los siguientes:

Copiar todo el contenido del directorio C:\Program Files\Microsoft SQL Server Compact Edition\v4.0\Private (excepto el fichero System.Data.SqlServerCe.Entity.dll) en el directorio \bin de nuestro sitio web.

De este modo, veremos cómo se agrega a nuestro sitio web una referencia a System.Data.SqlServerCe de tipo BIN.

clip_image010

Cuando publiques, también tendrás que dar permisos de “Modificar” al directorio \App_Data (donde estarán nuestras bases de datos .sdf) y también al directorio \bin (esto es importante y nos ha dado más de un dolor de cabeza!!).

Por último, si estás escribiendo código de acceso a datos independiente de la base de datos subyacente (puedes ver un pequeño tutorial aquí), estarás utilizando System.Data.Common. En este caso tienes que agregar lo siguiente a tu fichero web.config:

  <runtime>

    <assemblyBinding appliesTo="v2.0.50727" xmlns="urn:schemas-microsoft-com:asm.v1">

      <dependentAssembly>

        <assemblyIdentity name="System.Data.SqlServerCe" publicKeyToken="89845dcd8080cc91" culture="neutral"/>

        <bindingRedirect oldVersion="4.0.0.0-4.0.0.1" newVersion="4.0.0.1"/>

      </dependentAssembly>

    </assemblyBinding>

  </runtime>

 

  <system.data>

    <DbProviderFactories>

      <remove invariant="System.Data.SqlServerCe.4.0"/>

      <add name="Microsoft SQL Server Compact Data Provider 4.0" invariant="System.Data.SqlServerCe.4.0" description=".NET Framework Data Provider for Microsoft SQL Server Compact" type="System.Data.SqlServerCe.SqlCeProviderFactory, System.Data.SqlServerCe, Version=4.0.0.1, Culture=neutral, PublicKeyToken=89845dcd8080cc91"/>

    </DbProviderFactories>

  </system.data>

 

Por último y como apunte sencillo, un ejemplo de cadena de conexión contra nuestras bases de datos .sdf sería algo como:

  <connectionStrings>

    <add name="EjemploCE" connectionString="Data Source=|DataDirectory|\Ejemplo.sdf" providerName="System.Data.SqlServerCe.4.0"/>

  </connectionStrings>

 

Seguro que durante el desarrollo de esta aplicación aparecen más cosas dignas de mención, pero por ahora creo que es un buen comienzo para intentar dar el salto a CE para pequeñas y medianas aplicaciones (sobre todo me entusiasma el no tener que depender de SQL Server Express en el hosting compartido).

Un saludo y a programar ASP.NET sobre CE!

miércoles, 11 de mayo de 2011

Métodos impopulares de jQuery

En este post pretendo exponer un ejemplo claro de aquellas funciones de jQuery menos utilizadas pero no por ello menos útiles.

La mayoría de estas funciones son utilidades (sección utilities de la documentación de jQuery) que nos harán la vida más fácil pero que no son tan intuitivas como el típico selector de elementos.

Las funciones que vamos a tratar en este post son las siguientes:

·         constains

·         each

·         grep

·         inArray

·         isArray

·         isEmptyObject

·         isPlainObject

·         makeArray

·         map

·         merge

constains

$.constains(contendedor, contenido)

Determina si el nodo DOM “contenido” está dentro del nodo DOM “contenedor”.

Por ejemplo:

    <div id="Abuelo">

        <div id="Padre">

            <div id="Hijo">

            </div>

        </div>

    </div>

 

            var abuelo = document.getElementById("Abuelo");

            var padre = document.getElementById("Padre");

            var hijo = document.getElementById("Hijo");

 

            alert($.contains(abuelo, padre)); //true

            alert($.contains(abuelo, hijo)); //true

            alert($.contains(padre, hijo)); //true

 

            alert($.contains(hijo, padre)); //false

            alert($.contains(hijo, abuelo)); //false

            alert($.contains(padre, abuelo)); //false

 

Lo cierto es que antes de saber que existía esta función yo utilizaba esta otra que imagino será menos óptimo pero igualmente funciona. Lo que hacemos aquí es busca un elemento dentro del contexto de otro elemento y después comprobar si la búsqueda devolvió algún elemento.

            alert($("#Padre", "#Abuelo").length == 0 ? false : true); //true

            alert($("#Hijo", "#Abuelo").length == 0 ? false : true); //true

            alert($("#Hijo", "#Padre").length == 0 ? false : true); //true

 

            alert($("#Padre", "#Hijo").length == 0 ? false : true); //false

            alert($("#Abuelo", "#Hijo").length == 0 ? false : true); //false

            alert($("#Abuelo", "#Padre").length == 0 ? false : true); //false

 

each

Lo primero en decirte sobre esta función es que no debes confundir each (función de utilidades) con each (función de traversing).

La primera de ellas (utilidad) sirve para iterar sobre objetos y arrays.

$.each(colección, retroLlamada (indiceEnArray, valorDelElemento))

        function coche() {

            this.marca = "Seat";

            this.modelo = "León";

        }

 

        var miArray = [1, 2, 3, 4, 5];

 

        $().ready(function (e) {

            var miCoche = new coche();

            //iterar sobre las propiedades un objeto

            $.each(miCoche, function (indexInArray, valueOfElement) {

                //this = valueOfElement

                alert(indexInArray); //marca, modelo

                alert(valueOfElement); //Seat, León

                //return false; //detiene la iteración

            });

            //iterar sobre un array

            $.each(miArray, function (indexInArray, valueOfElement) {

                //this = valueOfElement

                alert(indexInArray); //0, 1, 2, 3, 4

                alert(valueOfElement); //1, 2, 3, 4, 5

                //return false; //detiene la iteración

            });

        });

 

Por otro lado, each (de traversing) itera sobre un objeto jQuery. Es decir, itera sobre todos los elementos DOM seleccionados a través del selector que hayamos utilizado. Veamos un ejemplo:

            $("div").each(function (index, element) {

                //this = element

                //element = DOMElement

                //index = índice basado en 0 del elemento en la colección

            });

grep

Siguiendo con el tema de iterar, grep permite iterar sobre un array y ejecutar una función sobre cada uno de sus elementos y, bien quedarnos con los que hayan satisfecho nuestra función de filtro o bien quedarnos justamente con los que no hayan satisfecho esta condición. En cualquier caso cabe aclarar que el array original no se modifica y que el array devuelto por grep es siempre un subconjunto filtrado del original.

$.grep(array, function(elementoDeArray, indiceEnArray), [ invert ] )

El parámetro invert es opcional, booleano y por defecto tiene el valor false. Si se pasa true, entonces grep devuelve los elementos que no cumplieron la función de filtro.

            var nuevoArray = $.grep([1, 2, 3, 4, 5], function (valor, indice) {

                //this objeto global window

                if (valor == 1 || valor == 2) {

                    return true;

                }

                else { //3, 4, 5

                    return false;

                }

            });

            $.each(nuevoArray, function (indice, valor) {

                alert(valor); //1, 2

            });


inArray

Permite buscar un valor en un array. Devuelve el índice basado en 0 del elemento encontrado o -1.

$.inArray(valor, array)

            alert($.inArray(3, [1, 2])); //-1

            alert($.inArray(3, [1, 2, 3])); //2

 

isArray

Determina si el parámetro suministrado es un array.

$.isArray(obj)

isEmptyObject

Determina si un objeto está vacío (esto es que no tiene propiedades).

$.isEmptyObject(obj)

            var obj1 = {};

            alert($.isEmptyObject(obj1)); //true

            function coche() { //constructor

            }

            var obj2 = new coche();

            alert($.isEmptyObject(obj2)); //true

            //añadir propiedad a obj1

            obj1.propiedad1 = "valor1";

            alert($.isEmptyObject(obj1)); //false

            //añadir método a obj2

            obj2.arrancar = function () {

                alert("arrancar");

            };

            alert($.isEmptyObject(obj2)); //false

 

isPlainObject

Determina si un objeto ha sido creado con {} o con new. Es decir, un objeto “plano/sencillo” es aquel que ha sido creado con {}.

            var obj1 = {};

            alert($.isPlainObject(obj1)); //true

            function coche() {

            }

            var obj2 = new coche();

            alert($.isPlainObject(obj2)); //false


makeArray

Convierte un objeto en un array verdadero. Lo de verdadero es para resaltar que el objeto pasado también se comportaba parecido a un array pero no era un verdadero array. Es decir, objeto tiene que ser un objeto del estilo nodeList (devuelto por document.getElementsByTagName) o similar (tiene propiedad length, se puede iterar, etc.)

map

La función map es muy parecido a la función each (la de utilidades) en el sentido que itera sobre objetos o arrays. También es parecida a makeArray en el sentido en que ambas pueden recibir un objeto o array y devuelven un nuevo array. Además, la función map devuelve un nuevo array (siempre y da igual que el parámetro haya sido un objeto o un array) con todos los elementos del objeto o matriz.

Es decir, map convierte un objeto u array, en otro array. A diferencia de makeArray, con map podemos convertir el valor sobre el que estamos iterando, eliminar el valor del array resultante, etc.

            var obj = { "Propiedad1": "Valor1", "Propiedad2": "Valor2" };

            var nuevoArray = $.map(obj, function (valor, indice) {

                //this objeto global window

                //alert(valor); //Valor1, Valor2

                //alert(indice); //Propiedad1, Propiedad2

 

                return valor + "_map"; //añade valor al array resultante

                //return null; //eliminar el valor del array resultante

                //return [1, 2];

                /*si se devuelve un array entonces agregará tantos elementos

                al array resultante como elementos tiene el array devuelto*/

            });

            alert(nuevoArray.length);

            alert(nuevoArray[0]); //Valor1_map

            alert(nuevoArray[1]); //Valor2_map

 

merge

Agrega el contenido de un segundo array a un primer array. En este sentido, el método de jQuery se asemeja mucho al método nativo concat.

            var array1 = [1, 2, 3];

            var array2 = [4, 5, 6];

            $.merge(array1, array2);

            alert(array1.length); //6


Además, esta función también puede reservar para copiar un array.

            var array1 = [1, 2, 3];

            var nuevoArray = $.merge([], array1);

 

Hasta aquí hemos llegado con los métodos de jQuery que pienso merecían una explicación. Por otro lado, muchas veces pasa que, además de jQuery, también hemos incluido ASP.NET AJAX y entonces tenemos disponible las extensiones de los objetos nativos de javascript que agrega ASP.NET AJAX. Algunos de estos métodos son similares a los de jQuery, otros son nuevos y después no hay que olvidarse de los métodos nativos (aquellos que están disponibles sin jQuery ni ASP.NET AJAX).

En lo relativo a ASP.NET AJAX puedes encontrar información de la extensión que hace del objeto Array aquí, y respecto a código nativo javascript en este otro enlace.

Un saludo!