viernes, 30 de noviembre de 2012

Cross-Domain en JQuery $.ajax, cuándo y cómo usar Json o Jsonp

Si nos disponemos a usar

Ajax

desde un script para comunicar con un servicio alojado en un dominio diferente al de la página que está originando la llamada hemos de tener en cuenta una serie de aspectos para evitar problemas de seguridad.

Aquí veremos un ejemplo sobre como hacer una llamada

Cross-Domain

con

ajax

a un servicio remoto. Por situarnos un poco, cuando realizamos una llamada a un servicio desde un script el navegador lanza una petición http a la Url y el servidor responde en formato

Json

. Si la Url está alojada en un dominio diferente, el concepto será el mismo, pero por motivos de seguridad hemos de tener en cuenta que el servidor no responderá al script con la respuesta

json

'plana', si no que la encapsulará en un método 'CallBack' que hemos de indicar en la URL desde cliente al invocar el servicio. Esta técnica se conoce como

Jsonp

(Json con Padding), veamos como adaptar el script en cliente.

Ejemplo Ajax mismo dominio:

Script
function localSample() {
        $.ajax({
            type: "POST",
            url: "UrlLocal",
            dataType: 'json',
            success: function (data) {
                //...
            },
            error: function (response) {
                //...
            }
        });   
}
Petición
http://UrlLocal
Respuesta
{"ObjetoJson":[{"id":1,"titulo":"blabla","descripcion":"blabla"},{"id":2,"titulo":"blabla","descripcion":"blabla"}]}
Ejemplo Cross-Domain:

Script
function login() {
        $.support.cors = true;
        $.ajax({
            type: "POST",
            url: "http://UrlRemota",
            dataType: 'jsonp',
            crossDomain: true,
            success: function (data) {
                //...
            },
            error: function (response) {
                //...
            }
        });
    }
}
Petición
http://UrlRemota?callback=jQuery16407422359699849039_1353499175935&_=1353499176045
Respuesta
jQuery16407422359699849039_1353499175935({"ObjetoJson":[{"id":1,"titulo":"blabla","descripcion":"blabla"},{"id":2,"titulo":"blabla","descripcion":"blabla"}]})
En el segundo ejemplo hemos alterado los valores de los atributos crossDomain y dataType del método

$.ajax

. Automáticamente se generará un método CallBack en runtime que tiene como función interpretar la respuesta

json

del servicio y cuya referencia se pasa como parámetro en la petición http al servidor.

Por lo que respecta a servidor hemos de tener en cuenta que el servicio debe estar preparado para procesar respuestas cross-domain. Si tenemos el control del código servidor y no está preparado por defecto podemos investigar como tratar este tipo de peticiones en función del lenguaje en que esté desarrollado el servicio.

Espero os sea útil, como siempre os recuerdo que podéis seguir

areaTIC.net

en las redes sociales!


martes, 27 de noviembre de 2012

Blogger: Gadget Entradas Relacionadas

En el pie de esta entrada podéis apreciar una sección

Entradas Relacionadas

; si intentáis buscarla entre los

gadgets de Blogger

no lo encontaréis, debéis ir a la página de LinkWithin para configurarlo. Os indico los pasos a seguir:
  1. Entramos en la web de LinkWithin, rellenamos el formulario correspondiente y pulsamos sobre "Get Widget".
  2. Nos aparece la siguiente pantalla con instrucciones para la instalación, pulsamos el botón "Install widget".
  3. En la siguienet página podremos modificar el título para nuestro

    gadget de Entradas Relacionadas

    y ver el contenido que se añadirá a nuestra página; pulsamos sobre el botón "Añadir artilugio".
  4. Una vez pulsado el botón "Añadir artilugio" si vamos a la sección Diseño de

    Blogger

    veremos que se ha añadido un

    gadget "LinkWithin"

    , son nuestras

    Entradas Relacionadas

    . Las podremos ubicar donde mejor nos vaya, en este blog están puestas bajo las entradas.
  5. Si pulsamos editar sobre el

    gadget

    podremos cambiar el título o el código insertado pero... ¿es posible personalizar más el

    gadget

    ? Pues sí es posible, lo haremos personalizando el CSS de nuestra plantilla, editamos el HTML (si no sabes cómo hacerlo puedes ver la explicación en este otro artículo del blog) y localizamos el siguiente código:
    ]]></b:skin>
    
  6. Justo encima del código anterior insertamos los siguientes estilos, puedes personalizarlos (o eliminar los que no necesites) como creas oportuno.
    /* Estilos personalizados para LinkWithin */
    
    .linkwithin_div {
      background: #FFFFFF;  /* Color de fondo */
      padding: 0 10px;
    }
    
    .linkwithin_text {
      font-family: Verdana; /* Estilo de la fuente del título */
      font-size: 11px;      /* Tamaño del título del widget */
      color: #000000;       /* Color del título del widget */
      font-weight: bold;    /* Estilo fuente en negrita */
    }
    
    .linkwithin_posts {
      width: 500px;         /* Ancho del widget */
    }
    
    .linkwithin_title {
      color: #2288BB;       /* Color de los títulos de las entradas */
      font-family: Verdana; /* Estilo fuente títulos de las entradas */
      font-size: 11px;      /* Tamaño de los títulos de las entradas */
      line-height: 14px;
      text-align:center;
      text-decoration: none;
    }
    
    .linkwithin_title:hover {
      color: #000000;       /* Color de los títulos al pasar cursor */
      font-weight: bold;    /* Estilo fuente en negrita */ 
    }
    
    .linkwithin_posts a {
      border: 0; 
      padding-right: 10px; 
    }
    
    .linkwithin_posts a:hover {
      background: #819FF7;  /* Color de fondo al pasar el cursor */
      -webkit-border-radius: 10px;
      -moz-border-radius: 10px;
      border-radius: 10px;
    }
    
    a#linkwithin_logolink_0, a#linkwithin_logolink_1, 
    a#linkwithin_logolink_2, a#linkwithin_logolink_3, 
    a#linkwithin_logolink_4, a#linkwithin_logolink_5, 
    a#linkwithin_logolink_6, a#linkwithin_logolink_7, 
    a#linkwithin_logolink_8, a#linkwithin_logolink_9, 
    a#linkwithin_logolink_10, a#linkwithin_logolink_11, 
    a#linkwithin_logolink_12, a#linkwithin_logolink_13, 
    a#linkwithin_logolink_14, a#linkwithin_logolink_15, 
    a#linkwithin_logolink_16, a#linkwithin_logolink_17, 
    a#linkwithin_logolink_18, a#linkwithin_logolink_19, 
    a#linkwithin_logolink_20 {
      display:none;         /* Elimina enlace a LinkWithin del gadget */
    }
    
    .linkwithin_img_0 div, div.linkwithin_img_0,
    .linkwithin_img_1 div, div.linkwithin_img_1,
    .linkwithin_img_2 div, div.linkwithin_img_2,
    .linkwithin_img_3 div, div.linkwithin_img_3,
    .linkwithin_img_4 div, div.linkwithin_img_4,
    .linkwithin_img_5 div, div.linkwithin_img_5,
    .linkwithin_img_6 div, div.linkwithin_img_6,
    .linkwithin_img_7 div, div.linkwithin_img_7,
    .linkwithin_img_8 div, div.linkwithin_img_8,
    .linkwithin_img_9 div, div.linkwithin_img_9,
    .linkwithin_img_10 div, div.linkwithin_img_10,
    .linkwithin_img_11 div, div.linkwithin_img_11,
    .linkwithin_img_12 div, div.linkwithin_img_12,
    .linkwithin_img_13 div, div.linkwithin_img_13,
    .linkwithin_img_14 div, div.linkwithin_img_14,
    .linkwithin_img_15 div, div.linkwithin_img_15,
    .linkwithin_img_16 div, div.linkwithin_img_16,
    .linkwithin_img_17 div, div.linkwithin_img_17,
    .linkwithin_img_18 div, div.linkwithin_img_18,
    .linkwithin_img_19 div, div.linkwithin_img_19,
    .linkwithin_img_20 div, div.linkwithin_img_20 { 
      -webkit-border-radius: 10px; /* Bordes redondeados */
      -moz-border-radius: 10px;
      border-radius: 10px;
      border:0 !important;
    }
    
Espero que con lo anterior tengáis todo lo necesario para añadir y personalizar vuestro

gadget de Entradas Relacionadas

. Dentro de

areaTIC

puedes encontrar otros artículos interesantes, no dudeis en consultar nuestro archivo; también puedes seguirnos por RSS o las principales redes sociales (twitter, facebook, linkedin...).


viernes, 23 de noviembre de 2012

Cómo depurar Javascript en Google Chrome

A continuación explicaremos como depurar código

Javascript

en

Google Chrome

. En la actualidad podríamos considerar Javascript como una técnica emergente en desarrollos web ya que con la aparición de

Html5

y librerías como

JQuery

permite realizar operaciones en marco cliente que hace unos años eran impensables. Cada vez más, en entorno web, se está extendiendo el uso de Css y el manejo dinámico de elementos del DOM con scripts. Este tipo de lenguajes interpretados se combina en muchas ocasiones con lenguajes servidor compilados, lo cual dificulta al desarrollador disponer de un entorno unificado de desarrollo en el que poder depurar y analizar código.

La mayoría de IDE's siguen esta tendencia y están proporcionando mejoras para facilitar desarrollo javascript-css pero siempre queda todo un poco ligado a compañía, navegador, versión del producto, etc. Otra opción recomendable a día de hoy es depurar scripts cliente directamente en el navegador en que estás ejecutando la página, independientemente del entorno de desarrollo que uses. En este artículo veremos como hacerlo en

Google Chrome

.

En primer lugar hemos de añadir la instrucción

debugger;

en el punto que queremos simular un break-point o punto de interrupción en nuestro código.
function login() {
    if ($("#fieldEmail").val().length > 0)
    {
        //llamada al script servidor
        $.ajax({
            type: "POST",
            url: "http://www.areaTIC.net/Servicios/Ejemplo...",
            dataType: 'json',
            success: function (data) {
                debugger;
                var user = data.usuarios;
                //acción...
            },
            error: function (response) {
                debugger;
                //interesa analizar el motivo del error...
                alert('No ha sido posible comunicar con el servidor.');
            }
        });
    }
}
Lo siguiente, una vez estamos ejecutando la página ya desde Google Chrome usamos la combinación de teclas 'Ctrl + Mayus + j' para acceder a la

Consola Javascript

y esperamos que el hilo de ejecución se sitúe en el punto de interrupción.

Una vez se detiene la ejecución, si navegamos por la consola veremos que se asemeja a las herramientas habituales que nos proporciona cualquier entorno de desarrollo.


De este modo sin complicarse demasiado las cosas ya podríamos depurar código javascript y salir de algún apuro, si esta explicación se queda corta podéis visitar este enlace para profundizar en la herramienta que ofrece Google Chrome para desarrolladores.

Recuerda visitar el archivo de

areaTIC

, también puedes hacerte seguidor en las redes sociales para estar al tanto de las novedades. Esperamos tu participación!


martes, 20 de noviembre de 2012

SQL Server: Cómo saber si hay columnas Identity en una base de datos

Si estáis haciendo algún tipo de importación sobre una base de datos os puede resultar necesario saber si sobre alguna de las tablas en las que se van a insertar datos existen

columnas Identity

ya que se debe tener especial cuidado con la inserción de valores en este tipo de columnas. La siguiente consulta os servirá para saber esquema y tabla de las

columnas Identity

que existan en una base de datos:

-- Buscar columnas identity en base de datos
SELECT SCHEMA_NAME(OBJECTPROPERTY(OBJECT_ID,'SchemaId')) AS SchemaName,
       OBJECT_NAME(OBJECT_ID) AS TableName,
       name AS ColumnName
FROM  SYS.COLUMNS
WHERE is_identity = 1
ORDER BY SchemaName, TableName, ColumnName

A continuación os detallo cómo se ha construido la consulta anterior:
  • La instrucción SCHEMA_NAME de Transact SQL devuelve el nombre de esquema asociado a un identificador de esquema. Podéis encontrar más información sobre esta instrucción en el siguiente enlace del MSDN (SCHEMA_NAME).

  • La instrucción OBJECTPROPERTY de Transact SQL devuelve información acerca de los objetos de ámbito de esquema. Para obtener el nombre del esquema en la consulta anterior necesitaremos utilizar la propiedad "SchemaId". Podéis encontrar más información sobre esta instrucción en el siguiente enlace del MSDN (OBJECTPROPERTY).

  • La instrucción OBJECT_ID de Transact SQL devuelve el número de identificador de un objeto de ámbito de esquema.Podéis encontrar más información sobre esta instrucción en el siguiente enlace del MSDN (OBJECT_ID).

  • La instrucción OBJECT_NAME de Transact SQL devuelve el nombre del objeto para los objetos de ámbito de esquema a partir de un identificador proporcionado. Podéis encontrar más información sobre esta instrucción en el siguiente enlace del MSDN (OBJECT_NAME).

  • La vista SYS.COLUMNS devuelve una fila por cada columna de cada tabla y vista, y una fila por cada parámetro de un procedimiento almacenado. Es recomendable utilizar esta vista en lugar de la tabla SYS.SYSCOLUMNS que se mantiene por compatibilidad con SQL Server 2000 pero que desaparecerá en futuras versiones de SQL Server. Podéis encontrar más información sobre este tema en el siguiente enlace del MSDN (SYS.COLUMNS).

  • La columna "name" de la vista SYS.COLUMNS contiene el nombre de la

    columna

    de tabla, vista o parámetro de procedimiento.

  • La columna "is_identity" de la vista SYS.COLUMNS contiene los valores 0 (no es columna

    Identity

    ) o 1 (es columna

    Identity

    ).

Espero que el artículo os haya sido interesante, dentro de

areaTIC

puedes encontrar otros artículos, no dudes en consultar nuestro archivo; también puedes seguirnos por RSS o las principales redes sociales (twitter, facebook, linkedin...)


LECTURAS RELACIONADAS RECOMENDADAS POR AREATIC.NET

viernes, 16 de noviembre de 2012

SQL Server: Insertar valor en columna Identity

Es posible que alguna ocasión os hayáis encontrado con una tabla en la que tenéis una

columna identity

[AddressID] (normalmente primary key) y queréis rellenar los

valores

libres en la

columna

(debido a eliminaciones) o queráis importar un conjunto de datos que queréis que tengan determinados

valores

en esa columna; en este ejemplo es explicaré cómo hacerlo, es muy sencillo.

  • Lo primero, supongamos que creamos la siguiente tabla donde la

    columna identity

    se inicializa con el

    valor

    2 y se incrementa en 1 en cada inserción.
    -- Creación de la tabla con la columna [AddressID] identity
    CREATE TABLE [Address](
        [AddressID] [int] IDENTITY(2,1) NOT NULL,
        [Address] [varchar](100) NOT NULL,
        [City] [varchar](30) NOT NULL,
        [PostalCode] [varchar](15) NOT NULL,
    CONSTRAINT [PK_Address_AddressID] PRIMARY KEY CLUSTERED ([AddressID] ASC)
    
  • Una inserción cualquiera en la tabla sería:
    -- Inserción de un fila sin asignar valor a columna identity
    INSERT INTO [Address]         
        ([Address]
        ,[City]
        ,[PostalCode])
         VALUES
        ('Paseo de Gracia 25'
        ,'Barcelona'
        ,'08007')
    
    Si hacemos un SELECT sobre la tabla nos devolverá 1 registro y veremos que el

    valor

    de la

    columna

    [AddressID] es 2. Una observación importante, si queremos saber el

    valor

    que se asigna a la

    columna identity

    (por ejemplo, porque ese

    valor

    será foreign key en otra

    columna

    de otra tabla) la forma correcta de hacerlo sería:
    -- Iniciamos transacción
    BEGIN TRANSACTION
    
    -- Inserción de un fila sin asignar valor a columna identity
    INSERT INTO [Address]         
        ([Address]
        ,[City]
        ,[PostalCode])
         VALUES
        ('Paseo de Gracia 25'
        ,'Barcelona'
        ,'08007')
    
    -- Obtenemos valor asignado a la columna identity 
    SELECT IDENT_CURRENT('[Address]')
    
    -- ... otras instrucciones
    
    -- Confirmamos transacción
    COMMIT TRANSACTION
    
    Si queréis más información sobre la instrucción IDENT_CURRENT de Transact-SQL podéis encontrarla en este enlace del MSDN.

  • Bien, ahora supongamos que queremos insertar una fila con

    valor

    1 en la

    columna identity

    ([AddressID]) de la tabla, la instrucción a ejecutar sería la siguiente.
    -- Activar inserción de valores explícitos en columna identity
    SET IDENTITY_INSERT [Address] ON;
    
    -- Inserción de un fila asignando valor a columna identity
    INSERT INTO [Address]         
        ([AddressID],
        ,[Address]
        ,[City]
        ,[PostalCode])
         VALUES
        (1
        ,'Paseo de Gracia 23'
        ,'Barcelona'
        ,'08007')
    
    -- Desactivar inserción de valores explícitos en columna identity
    SET IDENTITY_INSERT [Address] OFF;
    
    Lo que hacemos en este caso es primero activar la

    inserción de valores

    explícitos en la columna

    identity

    , posteriormente hacemos el INSERT incluyendo el nombre de la

    columna

    y el

    valor

    correspondientes a la

    columna identity

    y por último desactivamos la

    inserción de valores

    explícitos. Igual que en el caso anterior podemos utilizar la instrucción IDENT_CURRENT de Transact-SQL... ¿qué

    valor

    nos devolverá? Pues seguirá devolviendo 2 y no 1 ya que siempre devuelve el último

    valor de identidad

    generado para una tabla o vista especificadas (el 1 no es generado sino asignado explícitamente a la

    columna

    de la tabla).

    Si queréis más información sobre la instrucción SET IDENTITY_INSERT de Transact-SQL podéis obtenerla en el siguiente enlace del MSDN.

Espero que el artículo os haya sido interesante, dentro de

areaTIC

puedes encontrar otros artículos, no dudes en consultar nuestro archivo; también puedes seguirnos por RSS o las principales redes sociales (twitter, facebook, linkedin...)


LECTURAS RELACIONADAS RECOMENDADAS POR AREATIC.NET

martes, 13 de noviembre de 2012

Generar classes (.cs/.vb) a partir de un documento XML o plantilla XSD

El siguiente artículo resume los pasos sobre como obtener las clases .cs o .vb a partir de un esquema

Xsd

o documento

Xml

.

Usaremos la herramienta

xsd.exe

que viene con Visual Studio o si no lo tenemos podríamos obtenerla descargando el SDK del framework 2.0. Como alternativa se podría llegar a hacer lo mismo usando svcutil.exe.

En caso de tener Visual Studio instalado vamos al menú de inicio, Visual Studio, Visual Studio Tools y pulsamos en "Símbolo de sistema de Visual Studio". Veremos que nos abre una pantalla MS-DOS. En caso de no tener visual studio podríamos usar

Xsd

si vamos a la línea de comando (cmd) y nos situamos manualmente en el directorio que esté el ejecutable xsd.exe.

Una vez situado en el directorio que toca, ejecutamos el siguiente comando para convertir de

Xml

a

Xsd

:
C:\Program Files\Microsoft Visual Studio 10.0\VC>xsd.exe /c /l:CS c:\archivo.xml /o:c:\

Utilidad de compatibilidad para esquemas Xml y DataTypes de Microsoft (R)
[Microsoft (R) .NET Framework, Version 4.0.30319.1]
Copyright (C) Microsoft Corporation. All rights reserved.
Escribiendo el archivo 'C:\archivo.xsd'.
Ejecutamos posteriormente el siguiente comando. Si partimos de un

Xsd

en vez de un

Xml

podríamos obviar el paso anterior lo cual sería la situación ideal porque una plantilla

Xsd

contiene más información sobre los tipos que se han de generar en la clase que un documento

Xml

.
C:\Program Files\Microsoft Visual Studio 10.0\VC>xsd.exe /c /l:CS c:\archivo.xsd /o:c:\

Utilidad de compatibilidad para esquemas Xml y DataTypes de Microsoft (R)
[Microsoft (R) .NET Framework, Version 4.0.30319.1]
Copyright (C) Microsoft Corporation. All rights reserved.
Escribiendo el archivo 'C:\archivo.cs'.
Con esto ya podríamos agregar la clase 'archivo.cs' a nuestro proyecto .NET y usar los objetos generados automáticamente a partir del

Xsd

. Para volverlos a pasar a formato

Xml

podríamos serializar el objeto en disco usando

XmlSerializer

o

DataContractSerializer

combinado con

XmlWriter

.

Espero a alguien le sea útil, son bienvenidos todo tipo de comentarios. Recuerda que puedes seguir

areaTIC

en las redes sociales!


viernes, 9 de noviembre de 2012

ASP.NET - Configuración Session Mode

Hoy en

areaTIC

trataremos los modos de almacenamiento de la información de una sesión ASP.NET.

En este otro artículo vimos a modo introducción las diferentes alternativas que

ASP.NET

ofrece para mantener cierta información y hacer que persista entre varias peticiones

de un mismo cliente.

En este caso veremos como configurar

Session Mode

con el modo de almacenamiento de la información de sesión que nos interese en cada caso para evitar posibles problemas y optimizar el rendimiento del site.

Los diferentes modos de session que nos ofrece

ASP.NET

están contenidos en la enumeración

System.Web.SessionState.SessionStateMode

y son los siguientes:
  • InProc

    (defecto): Es la opción que ASP.NET usará por defecto para almacenar la información relacionada con los objetos de session que estemos usando en nuestro site. Este modo de almacenamiento usa la memória RAM de la máquina servidor en la que está alojada el site.

  • StateServer

    : Delegamos el trabajo relacionado con la gestión de la sesión a un servicio windows de un servidor remoto o local.

  • SQLServer

    : Permite definir una base de datos SQLServer para almacenar la información relacionada con los objetos de sesión.

  • Custom

    : Permite personalizar el modo de sesión.

  • Off

    : Deshabilita el uso de objetos Session en nuestro site.

Para modificar el modo de sesión que

ASP.NET

plantea por defecto hemos de añadir el siguiente tag al archivo web.config en la sección <System.Web>
<sessionState mode="InProc"/>
En la mayoría de situaciones usando el modo

InProc

, por defecto, no deberíamos tener problemas aunque se podría dar el caso que almacenemos mucha información en objetos de sesión y/o tengamos muchos usuarios concurrentes, esto podría originar que se supere la RAM asignada para tal propósito en el servidor con lo cual se reiniciaría la sesión de los usuarios y se perdería toda la información asociada. En este tipo de escenarios es recomendable modificar

SessionMode

para delegar la gestión de los objetos de sesión a una base de datos o bien un servicio. Veamos como hacerlo:

SQLServer :
<sessionState mode="SQLServer" sqlConnectionString ="...">
    </sessionState>
Si delegamos la gestión a una base de datos

SQLServer

es necesario tener instalado mínimo un

SQLServerExpress

e indicar la cadena de conexión del servidor. A modo opcional también podríamos definir los atributos

sqlCommandTimeout

y

sqlRetryInteval

.

StateServer:
<sessionState mode="StateServer" stateConnectionString="tcpip=127.0.0.1:42424" cookieless="false" />
En el ejemplo estamos apuntando al mismo servidor en que está alojado el site y le asignamos el rol de

StateServer

, aunque también podríamos apuntar a un equipo remoto. Un requisito para que funcione StateServer es habilitar el servicio de windows correspondiente para realizar esta gestión. En caso de no hacerlo recibiremos el siguiente error al iniciar una sesión.

No se puede realizar una solicitud de estado de sesión al servidor de estado de sesión. Compruebe que el servicio de estado ASP.NET se ha iniciado y que los puertos de cliente y servidor son los mismos. Si el servidor se encuentra en un equipo remoto, compruebe el valor de HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\aspnet_state\Parameters\AllowRemoteConnection para asegurarse de que acepta más solicitudes. Si el servidor se encuentra en el equipo local y si el mencionado valor del registro no existe o está establecido en 0, la cadena de conexión del servidor de estado debe utilizar 'localhost' o '127.0.0.1' como nombre de servidor.



Para solucionarlo hemos de ir a Inicio -> Ejecutar y teclear Services.msc para abrir la consola de administración de servicios del servidor que hayamos indicado en el atributo

stateConnectionString

. A continuación nos situamos en el servicio "Servicio de estado ASP.NET", lo iniciamos y además modificamos el tipo de inicio a modo automático.

Hasta aquí el post de esta semana, os recordamos que podéis seguir

areaTIC

en las redes sociales o vía RSS!


martes, 6 de noviembre de 2012

Control proactivo del espacio disponible en BDs SQL Server 2008

Seguramente si llevas tiempo trabajando con

SQL Server

te habrás encontrado alguna vez con el siguiente error:
No pudo asignar espacio para el objeto 'TableName' de base de datos 'DatabaseName' porque el grupo de archivos 'FilegroupName' está lleno. Elimine archivos innecesarios, quite objetos del grupo de archivos, agregue archivos adicionales al grupo de archivos o establezca la opción de crecimiento automático para los archivos existentes en el grupo de archivos con el fin de crear espacio...
Bien la solución puede ser tan "sencilla" como añadir un nuevo archivo en el grupo, aumentar el tamaño de un archivo del grupo.... hay distintas opciones, y pongo "sencilla" entre comillas porque no siempre tenemos disponible ese espacio en disco necesario para crear un nuevo archivo o aumentar el tamaño de uno existente. Mientras estemos con este error posiblemente tengamos ciertas aplicaciones fuera de servicio y eso puede suponer un grave problema para servicios en producción...

El objetivo de este artículo no es indicar cómo solucionar el problema (es relativamente sencillo para cualquier usuario con cierta experiencia en

SQL Server

) sino indicar cómo

hacer un control proactivo del espacio disponible en una base de datos SQL Server

de manera que sepamos con cierta antelación que se está agotando el espacio disponible y podamos actuar antes de producirse el error "

No pudo asignar espacio para el objeto 'TableName' de base de datos 'DatabaseName' porque el grupo de archivos 'FilegroupName' está lleno...

.

Hasta

SQL Server 2005

la cosa tenía cierta complejidad pero una de las novedades que incorporó

SQL Server 2008

fue la posibilidad de administrar servidores basándonos en

directivas, condiciones y facetas

(policies, conditions y facets en inglés). Esta nueva funcionalidad nos ayudará a

controlar proactivamente el espacio disponible en nuestra base de datos

, a continuación os muestro un sencillo ejemplo. Antes de empezar quizás sería conveniente que consultarais el siguiente enlace de la Technet para haceros una mejor idea de lo que es la administración basada en directivas.

Vayamos a por el ejemplo concreto que supongo es lo que os interesa. Lo que haremos es (en la base de datos AdventureWorks) que cuando el fichero de datos del grupo de archivos 'PRIMARY' tenga un espacio disponible inferior a 100 Mb se envíe una alerta al operador correspondiente; de esta manera podemos actuar antes de quedarnos sin espacio, los pasos a realizar serían los siguientes:
  1. Abrimos el SSMS, vamos a " Administración\Administración de

    directivas

    ", pulsamos botón derecho sobre

    "Condiciones"

    y seleccionamos la opción "Nueva condición..."


  2. Generamos una

    condición

    (conSpaceAvailableData100) que nos compruebe que el espacio disponible es superior a 100 MB, para ello informamos en la siguiente pantalla:
    Nombre de la condición: conSpaceAvailableData100
    Faceta: Data File (fichero de datos)
    Campo: @AvailableSpace (espacio disponible en el fichero de datos)
    Operador: >
    Valor: 1024000 (100 Mb en kilobytes)
    

  3. Generamos otra

    condición

    (conDatabaseName) que nos servirá para aplicar la directiva sobre una base de datos concreta, para ello informamos en la siguiente pantalla:
    Nombre de la condición: conDatabaseName
    Faceta: Database (base de datos)
    Campo: @Name (nombre de la base de datos)
    Operador: =
    Valor: 'AdventureWorks'
    

  4. A continuación creamos la

    directiva

    (dirDatabaseSpaceAvailable) para controlar el espacio disponible. Pulsamos botón derecho sobre

    "Directivas"

    y seleccionamos la opción "Nueva directiva". Introducimos en la pantalla que aparece los siguientes datos:
    Nombre de la directiva: dirDatabaseSpaceAvailable
    Condición comprobación (Check condition): conSpaceAvailableData100
    Para destinos (Against targets): Every File in Every Filegroup in conDatabaseName Database
    Modo de evaluación (Evaluation Mode): Al programar (On schedule)
    Programación: [Hay que crear una nueva pulsando el botón correspondiente, lo comento más adelante]
    

    Como comentaba anteriormente hay que crear una nueva programación pulsando el botón correspondiente, la llamaremos por ejemplo "schDatabaseAvailable" y la crearemos con los valores indicados en la siguiente imagen.


  5. Si en el SSMS expandimos el nodo " Administración\Administración de

    directivas

    " veremos que se nos ha creado la

    directiva

    "dirDatabaseSpaceAvailable" fuera de conexión. Si expandimos el nodo "Trabajos" vemos que se nos ha creado uno nuevo con un nombre generado automáticamente y tb fuera de conexión: lo renombramos a "jobDatabaseSpaceAvailable".


  6. Editamos el trabajo que hemos renombrado en el paso anterior, vamos a la sección de alertas y pulsamos el botón correspondiente para crear una nueva.


  7. Introducimos los datos para la nueva alerta en la sección "General":
    Nombre: aleDatabaseSpaceAvailable
    Tipo: Alerta de evento de SQL Server (SQL Server event alert)
    Número de error: 34052
    
    El error 34052 es el error correspondiente a infracción de una directiva en modo "Al programar". Se puede encontrar más información sobres los distintos errores en el siguiente enlace de la Technet.


  8. Vamos a la sección "Respuesta" (Response) de la alerta, seleccionamos la opción de notificar a operadores y marcamos el envío por email a uno de los operadores existentes. Si quieres saber más sobre

    envío de alertas a operadores de SQL Server

    puedes consultar nuestro artículo de julio de 2012.


  9. Para acabar con el tema de la alerta vamos a la sección "Opciones" (Options), marcamos la opción de incluir un texto de error en la alerta que enviamos por mail y definimos un mensaje adicional para que se vea más clara la

    directiva

    que se está infringiendo, algo del estilo "Directiva dirDatabaseSpaceAvailable: el espacio en el fichero de datos de la DB AdventureWorks es inferior a 100 Mb. Realice las opciones de mantenimiento oportunas.". Informamos el retardo entre respuestas y pulsamos aceptar para dar por concluida la configuración de la alerta.


  10. Ya volviendo al trabajo y para acabar también con su configuración en la sección "Notificaciones" aprovecharemos para hacer que si el trabajo falla se envíe por mail una notificación al operador y también se guarde en el registro de Windows el error correspondiente.


  11. Ya para finalizar, volvemos a la

    directiva

    que hemos creado en el punto 4, hacemos botón derecho del ratón sobre ella y pulsamos "Habilitar". Hacemos exactamente lo mismo para el trabajo que también creamos en el apartado 4, ahora tenemos

    directiva

    y trabajo habilitados. Si queremos probar el funcionamiento de la

    directiva

    pulsamos botón derecho del ratón sobre ella y pulsamos "Evaluar", me aparece la siguiente pantalla.


    Si pulsamos para ver los detalles...


    Puede parecer (por los iconos) que hay un error en la

    directiva

    pero no es así, sale el icono rojo porque se ha producido una infracción en la

    directiva

    que hemos creado: el espacio disponible en el fichero de datos de AdventureWorks es de 3.16 Mb cuando en la

    directiva

    hemos indicado que se produzca una infracción cuando el tamaño sea inferior a 100 Mb. El funcionamiento es correcto, con el trabajo que hemos programado, de lunes a viernes a las 00:00 se evaluará la

    directiva

    y si se produce una infracción se enviará un mail al operador indicado para que realice las operaciones oportunas.

Espero que os sea útil este artículo (mi tiempo me ha llevado escribirlo), con

directivas, facetas y condiciones

se simplifican notablemente las tareas de administración de SQL Server, os recomiendo que leáis sobre el tema. Recuerda que dentro de areaTIC puedes encontrar otros artículos interesantes, no dudes en consultar nuestro archivo.


LECTURAS RELACIONADAS RECOMENDADAS POR AREATIC.NET

sábado, 3 de noviembre de 2012

ASP.NET - Recomendaciones para elegir la técnica de manejo de estado adecuada para nuestro site

El protocolo

HTTP

por defecto no admite estados lo que implica que el servidor web trata cada petición de un navegador como una petición independiente. Ciertos sitios web necesitan mantener persistencia entre las peticiones de un mismo cliente como una tienda on-line con cesta de la compra por poner un ejemplo.

Cuando iniciamos el diseño de un site

ASP.NET

en el que necesitamos mantener un estado entre las peticiones de un mismo cliente-servidor es recomendable analizar parámetros como el tipo de información que almacenaremos, confidencialidad, volumen y previsión del número de clientes simultáneos del site.

ASP.NET

proporciona varias técnicas basadas en cliente y servidor para compartir información en forma de estado entre diferentes peticiones.

  • Si usamos controles de servidor ASP.NET mediante la propiedad

    ViewState

    de estos hacemos que la información viaje en cada petición oculta de modo que es sencillo recuperar valores entre 2 páginas. También se pueden usar otras técnicas cliente como

    Query String

    ,

    Hidden Fields

    o

    Cookies

    . Estas técnicas que acabamos de mencionar se basan en cliente, implica que la información que necesitamos que sea persistente entre las peticiones viaja en cada petición oculta o se almacena en el navegador como es el caso de las cookies.
  • Por otro lado

    ASP.NET

    proporciona técnicas de control de estado basadas en servidor como

    Application State

    ,

    Session State

    o

    Profile Properties

    que permiten al servidor almacenar información por lo que no es necesario que esta viaje en cada petición entre cliente y servidor. A la contra esta alternativa consume más recursos en el servidor web y si no se gestiona bien podría llegar a afectar al rendimiento del site.

La elección de la técnica adecuada dependerá del escenario que se nos plantee veamos algún ejemplo que nos ayudará a verlo más claro.

  • Un particular o pequeña compañía se plantea diseñar un site con visión comercial en el que no sabemos de inicio el número de usuarios que van a registrarse pero interesa que sean el máximo posible. El site dispone de un acceso privado que permite al usuario registrado realizar una gestión on-line en la que los datos persistentes entre páginas no serán estrictamente confidenciales y además no disponemos de servidor web propio y necesitamos hospedar el site con un tercero que ofrece servicios de hosting.

  • Una compañía con un número considerable de empleados y clientes se plantea diseñar un site que proporcione una serie de funcionalidades a sus usuarios. Por ejemplo interesa que los usuarios en función del tipo de perfil puedan realizar unas acciones determinadas de negocio que enlacen con otras aplicaciones. Supongamos que el volumen de información que necesitamos mantener a modo de sesión es elevado y además la información que se manipula es sensible y no conviene que sea accesible a usuarios malintencionados. La compañía dispone en este caso de una granja de servidores web propia alojada en sus sistemas.

En el primer ejemplo, es muy posible que no tengamos control sobre los recursos de máquina que tenemos asignados en el servidor y probablemente tampoco tengamos control total sobre la configuración del site. Además no sabemos el número de usuarios que podrían llegar a usar el site simultáneamente. En este caso sería recomendable no usar técnicas basadas en servidor en nuestro código porque por defecto

ASP.NET

almacenará en RAM del servidor web la información y esto podría originar un problema. Con técnicas basadas en cliente nos aseguraremos que la persistencia de la información se almacena en cliente o hacemos que viaje en cada petición lo que implica que el servidor no necesita almacenar información sobre los clientes que están conectados y no corremos el riesgo de desbordar los recursos de máquina.

En el segundo ejemplo nos interesaría decantarnos por una técnica basada en servidor porque la información que necesitamos hacer persistente contiene datos sobre roles, accesos, cuentas u otro tipo de información confidencial y hay que evitar que viajen entre cliente y servidor en cada petición para no comprometer la seguridad del site. Otra ventaja de este diseño es que la comunicación entre cliente y servidor será más ligera. Es posible que la configuración por defecto sea suficiente dado que no tengamos un número muy elevado de usuarios concurrenetes pero si por lo que sea la situación cambia, como tenemos acceso al servidor, podríamos modificar el comportamiento por defecto de un site

ASP.NET

con el fin de evitar cargar la RAM del servidor almacenando el estado en una base de datos o delegando la gestión a un servicio o equipo remoto... en definitiva podríamos diseñar arquitecturas un poco más complejas, si se da el caso, para garantizar el buen rendimiento y seguridad del site.

Hasta aquí el post de esta semana, en la sección

ASP.NET

podréis encontrar artículos relacionados que os podrían interesar. También podéis seguir

areaTIC

en las redes sociales y RSS!