Archivo de noviembre 2009


Cursores en SQL Server

Jueves, 26 nov, 2009 @ 10:27 | Por Dario Krapp | SQL Server

Introducción, conceptos y definiciones básicas

En SQL Server un cursor puede definirse como un elemento que representará a un conjunto de datos determinado por una consulta T-SQL, el cursor permitirá recorrer fila a fila, leer y eventualmente modificar dicho conjunto de resultados.

SQL Server ofrecerá una amplia variedad de opciones y de funciones para crear y operar sobre cursores. En este articulo, donde hemos utilizado SQL Server 2008 Enterprise Edition en los ejemplos, daremos un paseo por las posibilidades disponibles.

La creación y utilización de un cursor estará compuesta, como es de esperarse, por una serie de instrucciones T-SQL, las cuales podrán separarse en grupos bien diferenciados, los cuales son: Declaración, Apertura, Acceso a datos, Cierre y Desalojo, a continuación detallaremos cada grupo de instrucciones.

Declaración

El primer paso constará de la declaración del cursor, donde se indicarán (junto con el nombre del cursor) la consulta que el mismo representará y algunas otras características bastante interesantes.

Un ejemplo de declaración de cursor es el siguiente:

DECLARE ProdInfo CURSOR FOR SELECT Name FROM Production.Product

Donde ProdInfo representará al nombre del cursor y la sentencia “SELECT ProductNumber,Name FROM Production.Product” será el conjunto de datos del mismo.

Como comentamos previamente, es posible en este paso definir algunas características del comportamiento del cursor, por ejemplo la sentencia:

DECLARE ProdInfo CURSOR READ_ONLY FOR SELECT Name FROM Production.Product

Indicará que el cursor será de solo lectura, más adelante veremos en detalle las opciones disponibles, por el momento nuestro objetivo es crear un cursor lo más simple posible.

Apertura

La apertura del cursor ejecutará la consulta definida en el paso previo y cargará los datos en el mismo. La función OPEN de T-SQL permitirá efectuar esta terea, para continuar con el ejemplo previo la forma de abrir el cursor será la siguiente:

OPEN   ProdInfo

Recorrido del cursor y acceso a los datos

Este paso constará de recorrer los resultados del cursor, la instrucción FETCH permitirá efectuar dicha operación. Las filas leídas podrán copiarse a variables utilizando la sentencia INTO en combinación con la sentencia FETCH, por ejemplo la sentencia:

FETCH NEXT FROM ProdInfo INTO @Description

Tomará la siguiente fila de resultados del cursor y lo alojará en la variable @Description.

Un detalle a comentar es que en la sentencia INTO (como puede verse en el ejemplo anterior) el mapeo entre columnas del cursor y variables se realizará implícitamente, asignándose la primera columna a la primera variable, la segunda columna a la segunda variable y así sucesivamente. Esto implica que deberán crearse tantas variables como columnas se definan en la declaración del cursor y las mismas deberán ubicarse en el mismo orden que se encuentran definidas las columnas en la sentencia SELECT de la declaración.

Como cada sentencia FETCH leerá un registro, una pregunta interesante que podríamos hacernos es, ¿de qué manera podremos saber si existe un próximo o previo registro, o si hemos llegado al límite (ya sea superior o inferior)?. La respuesta se encontrará en una variable de SQL Server llamada @@FETCH_STATUS que tomará el valor 0 si la lectura del registro ha sido correcta.

En este punto será también posible modificar o eliminar las filas que se van recorriendo, como veremos al final del artículo.

Cierre del cursor

En el cierre del cursor se liberarán los registros tomados por el mismo. Una vez que el cursor es cerrado ya no podrá recorrerse el conjunto de resultados hasta que el mismo sea reabierto, la sentencia CLOSE cerrará un cursor abierto y la sintaxis puede verse a continuación:

CLOSE  ProdInfo

Desalojo del cursor

Este paso eliminará la referencia al cursor definido previamente, por lo que ya no será posible realizar una reapertura del mismo, en este caso la sintaxis será:

DEALLOCATE ProdInfo

Ejemplo de cursor

A continuación juntaremos todos los pasos descriptos previamente y crearemos el ejemplo más simple de un cursor el cual recorrerá la tabla Production.ProductDescription de la base de datos AdventureWorks y mostrará por pantalla el valor del registro Description luego que el mismo ha sido copiado a la variable @Description.

DECLARE @Description AS nvarchar(400)
DECLARE ProdInfo CURSOR FOR SELECT [Description] FROM Production.ProductDescription
OPEN ProdInfo
FETCH NEXT FROM ProdInfo INTO @Description
WHILE @@fetch_status = 0
BEGIN
    PRINT @Description
    FETCH NEXT FROM ProdInfo INTO @Description
END
CLOSE ProdInfo
DEALLOCATE ProdInfo

En el ejemplo puede verse la utilización de la variable @@FETCH_STATUS para verificar la existencia de la fila leída, por otra parte la sentencia FETCH NEXT devolverá la próxima fila de datos, siempre que la misma exista.
Este ejemplo, a pesar de parecer tan trivial y claro esconde un amplia variedad de comportamientos que el cursor asumirá, y que en este caso han tomado el valor por defecto, ya que no los hemos definido explícitamente.
El próximo paso será dar una recorrida por estas opciones y entender cuales se adaptarán mejor a nuestras necesidades.

VN:F [1.7.3_972]
Rating: 9.4/10 (5 votos cast)

Silverlight 4 Beta

Miércoles, 18 nov, 2009 @ 16:44 | Por Gustavo Cantero (The Wolf) | Silverlight

Microsoft® Silverlight
En el día de hoy, 18 de noviembre de 2009, en Los Angeles en el Professional Developer’s Conference 2009 (conocido como PDC09), Microsoft anuncia la disponibilidad de la beta de Silverlight® 4, justo 8 meses después de que en el MIX09 se presentara la beta de Silverlight® 3 (el 18 de marzo).

Entre las nuevas características que nos trae esta nueva versión encontramos:

  • Soporte para impresión, incluyendo una vista previa del documento
  • Más de 60 controles personalizables
  • Mejoras en la localización de los textos
  • El CLR ahora permite ejecutar el mismo código compilado en el escritorio como en Silverlight sin cambios
  • Soporte para la utilización de webcams y micrófono
  • Deep Zoom ahora utiliza la aceleración por hardware
  • Multicast networking
  • Soporte para Google® Chrome
  • Soporte Multi-touch
  • Eventos de botón derecho del mouse
  • Acceso al Portapapeles
  • Se podrán utilizar en el escritorio como “trusted applications”, permitiendo acceder a documentos, aplicaciones como Outlook® (por ejemplo, para enviar mails), a dispositivos utilizando COM automation, etc.
  • Y muchas novedades más…. (para más detalles pueden visitar el sitio de Silverlight)

Para probarlo sólo necesitan tener la beta de Visual Studio® 2010 y el SDK de Silverlight® 4.

Cabe mencionar que en el día de hoy también salió el nuevo release del Silverlight® Toolkit, el cual ahora también soporta la beta de Silverlight 4.

Esta noticia seguramente va a alegrar a varios de los desarrolladores que ya utilizamos Silverlight® en nuestras aplicaciones.

Enlaces

VN:F [1.7.3_972]
Rating: 0.0/10 (0 votos cast)

Cómo crear una clase dinámicamente y ejecutarla

Sábado, 14 nov, 2009 @ 19:13 | Por Gustavo Cantero (The Wolf) | .NET Framework

Revisando los newsgroups de Microsoft encontré una persona que preguntaba cómo hacer para “ejecutar un string”, o sea, escribir una fórmula matemática en una cadena de texto y luego obtener el resultado de la misma. En ese momento recordé que hace unos años tuve que hacer esto mismo utilizando .NET Framework 1.1, fue entonces cuando me decidí a buscar aquel código y escribir este artículo.
Para hacer esto necesitamos crear una clase, compilarla en memoria, luego instanciarla y por último ejecutar el método que devuelva el resultado en cuestión.

La clase la debemos crear en un string incluyendo los using necesarios, el namespace a utilizar y el método a ejecutar, el cual va a resolver la fórmula. Al compilador debemos pasarle varios parámetros a través de la clase CompilerParameters, donde vamos a indicarle que debe generar el ensamblado en memoria, que no debe generar un ejecutable y que no incluya (o si, depende de la necesidad) la información para debug.

CompilerParameters Parametros = new CompilerParameters()
{
    GenerateInMemory = true,
    GenerateExecutable = false,
    IncludeDebugInformation = false
};

Luego debemos crear el compilador con el método estático CreateProvider de la clase CodeDomProvider, al cual debemos pasarle el lenguaje que queremos utilizar, en nuestro ejemplo “CSharp”. Hay que tener en cuenta que el nombre del lenguaje es “case sensitive”, por lo que hay que tener cuidado de escribirlo con las mayúsculas y minúsculas correspondientes.

CodeDomProvider objCompiler = CodeDomProvider.CreateProvider("CSharp");

Una vez creado el compilador debemos pasarle la clase y los parámetros creados anteriormente para que genere el ensamblado necesario en memoria:

CompilerResults objResultados = objCompiler.CompileAssemblyFromSource(objParametros, strClase);

Por último debemos crear una instancia de la clase y llamar al método que creamos y que va a calcular la fórmula:

object objClase = objResultados.CompiledAssembly.CreateInstance("MiNamespace.MiClase", false, BindingFlags.CreateInstance, null, null, null, null);
return objClase.GetType().InvokeMember("MiMetodo", BindingFlags.InvokeMethod, null, objClase, null);

El método CreateInstance posee varios parámetros para globalización, parámetros para pasarle al método, etc., pero para nuestro ejemplo, al no necesitarlos, los vamos a establecer en null.

Una vez explicado lo que necesitamos hacer, les paso el código del método a ejecutar para que resuelva fórmulas o cualquier línea de C# (por ejemplo, búsquedas de cadenas de texto, etc.) y devuelva el valor:

namespace WebApplication1
{
    using System.CodeDom.Compiler;
    using System.Reflection;

    public static class Formula
    {
        /// <summary>
        /// Resuelve el valor de una fórmula
        /// </summary>
        /// <param name="Formula">Fórmula a resolver</param>
        /// <returns>Resultado</returns>
        /// <example>double Resultado = Formula.Resolver("2 * 8 + 3");</example>
        public static object Resolver(string Formula)
        {
            //Parámetros del compilador
            CompilerParameters objParametros = new CompilerParameters()
            {
                GenerateInMemory = true,
                GenerateExecutable = false,
                IncludeDebugInformation = false
            };

            //Clase
            string strClase =
                "using System;" +
                "namespace Scientia {" +
                "public class Formula {" +
                    "public object Ejecutar() {" +
                        "return " + Formula +
                ";}}}";

            //Compilo todo y ejecuto el método
            CodeDomProvider objCompiler = CodeDomProvider.CreateProvider("CSharp");

            //En .NET 1.1 usaba esta linea:
            //ICodeCompiler ICC = (new CSharpCodeProvider()).CreateCompiler();

            CompilerResults objResultados = objCompiler.CompileAssemblyFromSource(objParametros, strClase);
            object objClase = objResultados.CompiledAssembly.CreateInstance("Scientia.Formula",
                false, BindingFlags.CreateInstance, null, null, null, null);
            return objClase.GetType().InvokeMember("Ejecutar", BindingFlags.InvokeMethod, null, objClase, null);
        }
    }
}

Como ejemplo podemos crear una página donde el usuario pueda ingresar una fórmula y al pulsar en un botón se muestre el resultado en la misma. La página debería quedar así:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication1._Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Ejemplo de Scientia® Soluciones Informáticas</title>
</head>
<body>
    <form id="form1" runat="server">
    <asp:Panel DefaultButton="btnCalcular" runat="server">
        <asp:TextBox ID="txtFormula" runat="server" />
        <asp:Button ID="btnCalcular" runat="server" Text="=" OnClick="btnCalcular_Click" />
        <asp:Label ID="lblResultado" runat="server" />
    </asp:Panel>
    </form>
</body>
</html>

Y en el code behind de ésta debería tener lo siguiente:

using System;

namespace WebApplication1
{
    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
        }

        protected void btnCalcular_Click(object sender, EventArgs e)
        {
            lblResultado.Text = Formula.Resolver(txtFormula.Text).ToString();
        }
    }
}

Espero que este artículo les sea de utilidad y, como siempre, les dejo el proyecto de ejemplo para Visual Studio® 2008.Descargar proyecto de ejemplo

VN:F [1.7.3_972]
Rating: 10.0/10 (1 voto cast)

Versión final de Bing Maps Platform

Martes, 10 nov, 2009 @ 12:28 | Por Gustavo Cantero (The Wolf) | GIS, Silverlight

bing
Para aquellos que, como nosotros, utilizan la versión CTP del control de Silverlight para Virtual Earth les comento que este control funcionará hasta el 31 de diciembre de 2009 inclusive. Para poder seguir utilizando los servicios de Bing Microsoft acaba de lanzar (ayer) la versión final de Bing Maps Platform 1.0, el cual incluye la versión final del control para usarse desde Silverlight.

Para conocer más de la nueva versión del control o para conocer cómo utilizar los servicios del control de Silverlight para bing pueden leer el Getting Started Using the Silverlight Map Control.

También pueden ver el video del anuncio de esta nueva versión en Microsoft Bing Maps for Enterprise.

VN:F [1.7.3_972]
Rating: 0.0/10 (0 votos cast)