Development

Stored Procedures y Functions en SQL Server 2005 – II

Functions en SQL Server 2005

 

Al igual que las funciones en los lenguajes de programación, las funciones definidas por el usuario de Microsoft SQL Server 2005 son rutinas que aceptan parámetros, realizan una acción, como un cálculo complejo, y devuelven el resultado de esa acción como un valor. El valor devuelto puede ser un valor escalar único o un conjunto de resultados.

Ventajas de las funciones definidas por el usuario

Permiten una ejecución más rápida.
Al igual que los stored procedures, las funciones definidas por el usuario Transact-SQL reducen el costo de compilación del código Transact-SQL almacenando los planes en la caché y reutilizándolos para ejecuciones repetidas 
  Esto significa que no es necesario volver a analizar y optimizar la función definida por el usuario con cada uso, lo que permite obtener tiempos de ejecución mucho más rápidos.
Las funciones CLR ofrecen una ventaja de rendimiento importante sobre las funciones Transact-SQL para tareas de cálculo, manipulación de cadenas y lógica empresarial
. Las funciones Transact-SQL se adecuan mejor a la lógica intensiva del acceso a datos.

Pueden reducir el tráfico de red.
Una operación que filtra datos basándose en restricciones complejas que no se puede expresar en una sola expresión escalar se puede expresar como una función. La función se puede invocar en la cláusula WHERE para reducir el número de filas que se envían al cliente.

Tipos de funciones

·  Funciones escalares

Las funciones escalares definidas por el usuario devuelven un único valor de datos del tipo definido en la cláusula RETURNS. Las funciones escalares en línea no tienen cuerpo; el valor escalar es el resultado de una sola instrucción. Para una función escalar de múltiples instrucciones, el cuerpo de la función, definido en un bloque BEGIN…END, contiene una serie de instrucciones Transact-SQL que devuelven el valor único

Demo:

IF OBJECT_ID (N‘dbo.ufnGetInventoryStock’, N‘FN’) IS NOT NULL
     
DROP FUNCTION ufnGetInventoryStock;
GO

CREATE FUNCTION dbo.ufnGetInventoryStock(@ProductID int)
   RETURNS int
AS
— Returns the stock level for the product.
BEGIN

DECLARE @ret int;
SELECT @ret = SUM(p.Quantity)  FROM Production.ProductInventory p
WHERE p.ProductID = @ProductID AND p.LocationID = ‘6’;

  IF (@ret IS NULL)
   
SET @ret = 0
   
RETURN @ret
END;
GO

— Utilizando la nueva function
SELECT ProductModelID, Name, dbo.ufnGetInventoryStock(ProductID)AS CurrentSupply
FROM Production.Product
WHERE ProductModelID BETWEEN 75 and 80;

·         Funciones con valores de tabla

Las funciones con valores de tabla definidas por el usuario devuelven un tipo de datos table. Las funciones con valores de tabla en línea no tienen cuerpo; la tabla es el conjunto de resultados de una sola instrucción SELECT

Demo: Creando una Funcion con valores de tabla en linea

IF OBJECT_ID (N‘Sales.ufn_SalesByStore’, N‘IF’) IS NOT NULL
    
DROP FUNCTION Sales.ufn_SalesByStore;
GO

CREATE FUNCTION Sales.ufn_SalesByStore (@storeid int)
  RETURNS TABLE
AS

RETURN SELECT P.ProductID, P.Name, SUM(SD.LineTotal) AS ‘YTD Total’ FROM Production.Product AS P
  
JOIN Sales.SalesOrderDetail AS SD ON SD.ProductID = P.ProductID
 
JOIN Sales.SalesOrderHeader AS SH ON SH.SalesOrderID = SD.SalesOrderID
 
WHERE SH.CustomerID = @storeid
 
GROUP BY P.ProductID, P.Name);
GO

— Utilizando la ufn_SalesByStore function
SELECT * FROM Sales.ufn_SalesByStore (602);

Para una función con valores de tabla de múltiples instrucciones, el cuerpo de la función, definido en un bloque BEGIN…END, contiene una serie de instrucciones Transact-SQL que generan e insertan filas en la tabla que se va a devolver.

Demo: Creando una Funcion con valores de tabla de multiples instrucciones:


CREATE
FUNCTION dbo.ufn_FindReports (@InEmpID INTEGER)
RETURNS @retFindReports TABLE (
     EmployeeID
int primary key NOT NULL,
    
Name nvarchar(255) NOT NULL,
     Title
nvarchar(50) NOT NULL,
     EmployeeLevel
int NOT NULL,
     Sort
nvarchar (255) NOT NULL
)

–Returns a result set that lists all the employees who report to the
–specific employee directly or indirectly.*/
AS
BEGIN
   WITH
DirectReports(Name, Title, EmployeeID, EmployeeLevel, Sort) AS
      
(SELECT CONVERT(Varchar(255), c.FirstName + ‘ ‘ + c.LastName), e.Title, e.EmployeeID,1,
      
CONVERT(Varchar(255), c.FirstName + ‘ ‘ + c.LastName)
      
FROM HumanResources.Employee AS e
          JOIN Person.Contact
AS c ON e.ContactID = c.ContactID
     
WHERE e.EmployeeID = @InEmpID
   
UNION ALL
     SELECT
CONVERT(Varchar(255), REPLICATE (‘| ‘ , EmployeeLevel) + c.FirstName + ‘ ‘ + c.LastName), e.Title, 
      EmployeeID, EmployeeLevel + 1,
CONVERT (Varchar(255), RTRIM(Sort) + ‘| ‘ + FirstName + ‘ ‘ + LastName)
    
FROM HumanResources.Employee as e JOIN Person.Contact AS c ON e.ContactID = c.ContactID
    JOIN DirectReports
AS d ON e.ManagerID = d.EmployeeID )

— copy the required columns to the result of the function
  INSERT @retFindReports SELECT EmployeeID, Name, Title, EmployeeLevel, Sort FROM DirectReports
  RETURN
END
;
GO

— Example invocation
SELECT EmployeeID, Name, Title, EmployeeLevel FROM dbo.ufn_FindReports(109) ORDER BY Sort;

·         Funciones integradas

SQL Server proporciona las funciones integradas para ayudarle a realizar diversas operaciones. No se pueden modificar. Puede utilizar funciones integradas en instrucciones Transact-SQL para:
            
        
ü
  Tener acceso a información de las tablas del sistema de SQL Server sin tener acceso a las tablas del sistema directamente.
        
ü
  Realizar tareas habituales como SUM, GETDATE o IDENTITY.

Las funciones definidas por el usuario se han ampliado en Microsoft SQL Server 2005 para incluir las funciones escritas en cualquier lenguaje de programación que se admita en Microsoft .NET Framework

Remember:

 

Las funciones en línea pueden utilizarse para obtener la funcionalidad de vistas con parámetros. No obstante, las vistas no admiten parámetros en las condiciones de búsqueda especificadas en la cláusula WHERE. Las funciones en línea definidas por el usuario pueden utilizarse para admitir parámetros en las condiciones de búsqueda especificadas en la cláusula WHERE.

No se recomienda el uso de funciones definidas por el usuario que producen efectos secundarios en la base de datos.

Cuando se llama desde una función, el procedimiento almacenado extendido no puede devolver conjuntos de resultados al cliente

En general, si el procedimiento almacenado devuelve un solo conjunto de resultados, defina una función con valores de tabla.

Para las funciones con valores de tabla no son necesarias las instrucciones EXECUTE dinámicas

Las funciones CLR suponen una alternativa más confiable y escalable frente a los procedimientos almacenados extendidos. Muchos procedimientos almacenados extendidos realizan tareas de cálculo que son difíciles de expresar en Transact-SQL Además, los procedimientos almacenados extendidos que devuelven conjuntos de resultados mediante el acceso a un recurso externo, como un archivo o un servicio Web, se pueden volver a escribir mediante una función con valores de tabla CLR.

Development

Stored Procedures y Functions en SQL Server 2005

Stored Procedures en SQL Server 2005

 

Todos sabemos que es un Stored Procedures; a modo de intro a este blog, un Stored Procedure es una colección guardada de instrucciones Transact-SQL o una referencia a un método Common Language Runtime (CLR) de Microsoft .NET Framework

Dicho procedimiento puede recopilar y devolver parámetros proporcionados por el usuario. Los procedimientos se pueden crear para uso permanente o para uso temporal en una sesión, un procedimiento local temporal, o para su uso temporal en todas las sesiones, un procedimiento temporal global.  Los procedimientos almacenados también se pueden crear de modo que se ejecuten de forma automática al iniciarse una instancia de SQL Server.

Tambien sabemos sobre los procedimientos temporales locales o globales, que se pueden crear anteponiendo el signo de número (#) al nombre de nuestro stored procedure (#procedure_name)  para los procedimientos temporales locales y dos signos de número para los procedimientos temporales globales (##procedure_name). Nota: No es posible especificar nombres temporales para los procedimientos almacenados CLR.

Un procedimiento almacenado puede tener un máximo de 2.100 parámetros.

En los procedimientos almacenados CLR, no es posible especificar como parámetros los tipos text, ntext, image, cursor y table. Si el tipo de datos del parámetro es un tipo definido por el usuario CLR, es necesario disponer de permiso EXECUTE en el tipo.

No es posible especificar RECOMPILE en los stored procedures CLR.
La opción ENCRYPTION
no es válida en los stored procedures  CLR.
No es posible especificar FOR REPLICATION en los stored procedures  CLR.
Un stored procedure FOR REPLICATION tendrá un tipo de objeto RF en sys.objects y sys.procedures
.
De manera predeterminada, SQL Server no puede ejecutar código CLR.  Es posible crear, modificar y quitar objetos de base de datos que hagan referencia a módulos CLR; no obstante, no es posible ejecutar esas referencias en SQL Server hasta que se haya habilitado la opción clr enabled. Para habilitar la opción, se utilizará: 
sp_configure ‘clr enable’,y luego:se ejecutará: Reconfigure.

El tamaño máximo de un stored procedure Transact-SQL es de 128 MB.

Utilizar parámetros con procedimientos almacenados CLR

Los parámetros de un procedimiento almacenado CLR pueden ser de cualquiera de los tipos de datos escalares del sistema de SQL Server.
Para que el Database Engine (Motor de base de datos) haga referencia al método correcto cuando está sobrecargado en .NET Framework, el método indicado en <method_specifier> debe tener las siguientes características:
        
ü
  Ser declarado un método estático.
        
ü
  Recibir el mismo número de parámetros que el número de parámetros del procedimiento.
        
ü
  No ser un constructor ni un destructor de su clase.
       
ü
 Utilizar tipos de parámetros compatibles con los tipos de datos de los parámetros correspondientes del procedimiento de SQL Server.
      
ü
  Devolver sus parámetros por referencia y no por valor siempre que se haya especificado OUTPUT para una declaración de parámetros específica.

Obtener información acerca de procedimientos almacenados

 

Para mostrar la definición de un procedimiento almacenado Transact-SQL, se debe utilizar la vista de catálogo sys.sql_modules de la base de datos en la que se encuentra el procedimiento.

Nota: El texto de un procedimiento almacenado creado con la opción ENCRYPTION no se puede ver mediante la vista de catálogo sys.sql_modules

Para obtener un informe sobre los objetos a los que hace referencia un procedimiento, se debe realizar una consulta a la vista de catálogo sys.sql_dependencies o utilizar sp_depends para devolver información sobre los objetos a los que hacen referencia los procedimientos almacenados CLR. Para mostrar información acerca de los procedimientos almacenados CLR, utilice la vista de catálogo sys.assembly_modules de la base de datos en la que se encuentra el procedimiento.

Para mostrar información acerca de los parámetros definidos en un procedimiento almacenado, se debe utilizar la vista de catálogo sys.parameters de la base de datos en la que se encuentra el procedimiento.

Un Remember: En el momento de la creación, sólo se realiza la comprobación de la sintaxis. El procedimiento almacenado no se compila hasta que se ejecuta por primera vez. Solamente durante la compilación se resuelven todos los objetos a los que se hace referencia en el procedimiento almacenado. Cuando un procedimiento se ejecuta por primera vez, se compila para determinar que dispone de un plan de acceso óptimo para recuperar los datos. En las siguientes ejecuciones del procedimiento almacenado se puede volver a utilizar el plan ya generado si aún permanece en la caché de planes del Database Engine

 

Parámetros que utilizan el tipo de datos cursor

 

Los procedimientos almacenados Transact-SQL sólo pueden utilizar el tipo de datos cursor para los parámetros OUTPUT. Si se especifica el tipo de datos cursor para un parámetro, se requieren los parámetros VARYING y OUTPUT.

Demo:Crear un procedimiento almacenado CLR


En el siguiente ejemplo se crea el procedimiento almacenado GetPhotoFromDB que hace referencia al método GetPhotoFromDB de la clase LargeObjectBinary del ensamblado HandlingLOBUsingCLR desde el Microsoft SQL Server Management Studio. Antes de que se cree el procedimiento almacenado, el ensamblado HandlingLOBUsingCLR se registra en la base de datos local.

 

CREATE ASSEMBLY HandlingLOBUsingCLR
Authorization [dbo] <
— si se quiere autorizar a un User Account especifico
From ‘\\MachineName\HandlingLOBUsingCLR\bin\Debug\HandlingLOBUsingCLR.dll’
;
With Permission_Set = safe <
— el modo seguro es by default
GO

CREATE PROCEDURE dbo.GetPhotoFromDB
(
   @ProductPhotoID int
,
   @CurrentDirectory nvarchar(1024
),
   @FileName nvarchar(1024
)
)
AS EXTERNAL NAME HandlingLOBUsingCLR.LargeObjectBinary.GetPhotoFromDB
;
GO

Demo2: Utilizar un parámetro de cursor OUTPUT

USE AdventureWorks;
GO

IF OBJECT_ID ( ‘dbo.uspCurrencyCursor’, ‘P’ ) IS NOT NULL
       DROP PROCEDURE dbo.uspCurrencyCursor;
GO

CREATE PROCEDURE dbo.uspCurrencyCursor
                   @CurrencyCursor
CURSOR VARYING OUTPUT
AS

SET @CurrencyCursor = CURSOR FORWARD_ONLY STATIC FOR
               SELECT CurrencyCode, Name
              FROM Sales.Currency;

OPEN @CurrencyCursor;
GO

–Recuperando las filas desde el cursor
DECLARE @MyCursor CURSOR;
EXEC dbo.uspCurrencyCursor @CurrencyCursor = @MyCursor OUTPUT
;

FETCH NEXT FROM @MyCursor;
WHILE (@@FETCH_STATUS = 0
)
BEGIN
;
   
FETCH NEXT FROM @MyCursor
;
END;

CLOSE @MyCursor;
DEALLOCATE @MyCursor
;
GO

Aunque yo particularmente no utlizó este tipo de parametro en mis SPs de desarrollo, bueno las lineas anteriores para la demo; siempre es bueno utilizar: Begin Try … End Try Begin Catch … End Catch dentro de los SPs.

 

Functions en SQL Server 2005

 

Al igual que las funciones en los lenguajes de programación, las funciones definidas por el usuario de Microsoft SQL Server 2005 son rutinas que aceptan parámetros, realizan una acción, como un cálculo complejo, y devuelven el resultado de esa acción como un valor. El valor devuelto puede ser un valor escalar único o un conjunto de resultados.

 

Development

Biztalk Server 2006 (BTS 2006) : Arquitectura – Parte 1

Antes una breve Introducción:

Integración de Aplicaciones de negocio (EAI)

¢  Integra sistemas y aplicaciones internas

¢  Provee la base para B2B y BPM

¢  Ofrece información de negocio en tiempo real (I.W.)

¢  Provee visibilidad de transacciones de principio a fin

BizTalk_01

Integración Business-to-Business (B2B)

¢  Integra de forma rápida y efectiva una comunidad comercial en los procesos de negocio.

¢  Promueve la interacción automatizada en una comunidad comercial heterogénea

¢  Expone nuevas funcionalidades a clientes y proveedores

BizTalk_02

 
Gestión de procesos de negocio (BPM)

¢  Consiste en la mezcla de procesos y tecnología mediante la integración de flujos de negocio y aplicaciones

BizTalk_03
 

Arquitectura Orientada a Servicios (SOA)

¢  Práctica de diseño para desarrollar aplicaciones con una arquitectura desacoplada y heterogénea.

BizTalk_04

Que es Biztalk Server 2006?

Servidor de Integración de aplicaciones

 

·         EAI: Entreprise Application Integration 

·         B2B: Business to Business

 

Biztalk Server es un “broker”: se sitúa en medio de las aplicaciones que están siendo integradas e interactúa con cada una de ellas


Biztalk server 2006 provee:

¢  Motor de mensajería y gestión de procesos

¢  Integración con Web Services

¢  Motor de reglas de negocio

¢  Single Sign-on

¢  Herramientas de seguimiento de actividad de negocio

¢  Herramientas de monitorización y seguimiento de actividad y salud

¢  Herramientas de desarrollo integradas

Problemas que resuelve BTS 2006

¢  Aplicaciones dispares

¢  Sobrecarga de desarrollo

¢  Despliegue complejo

¢  Informes dispares

¢  Difícil modificación

¢  Falta de procedimientos estándares

¢  Seguimiento y tracking limitado

¢  Lógica de negocio/partners cambiantes

Arquitectura Básica BTS 2006

Visión general Arquitectura BTS:

BizTalk_05

Elementos principales:

¢  MessageBox Universal

¢  Puertos

¢  Pipelines

¢  Adaptadores 

 

MessageBox Universal

¢  Modelo de escalado consistente basado en SQL Server 2000 SP3

¢  Arquitectura Pub/Sub

¢  Servidores sin estado

¢  Baja latencia y alta volatilidad en el enrutado

¢  Soporte de mensajes “huge”

¢  Soporte de adaptadores

¢  Seguridad y auditoria

Puertos

¢  Definen como se envían y reciben mensajes

¢  Un puerto es una instancia de un Port_Type

¢  Puntos de comunicación con el exterior

Pipelines

¢  Normalizar datos que llegan en varios formatos a Xml

¢  Traducir datos de Xml a otros formatos

¢  Ensamblar y desensamblar documentos

¢  Codificar y descodificar documentos

¢  Encryptar y desencriptar documentos

¢  Asignar y verificar firmas digitales

Adaptadores

¢  Conectan Aplicaciones en un sistema de Integración

¢  Proveen una solución de integración rápida sin desarrollo

Adaptadores de Aplicación

¢  Integran aplicaciones de negocio

¢  Utilizan API

Adaptadores de Tecnología

¢  Integran aplicaciones a nivel de plataforma

¢  Se utilizan cuando el destino es un sistema, no una aplicación, o Para aplicaciones que no publican una interfaz

Servicios de Mensajería vs flujos de trabajo

Servicios de mensajería:

¢  Enfocado en los detalles del envío y recepción de mensajes; es decir la conexión de puntos entre aplicaciones

servicio_mensajeria

Flujos de trabajo:

¢  Enfocado en la coordinación de procesos de negocio, control de transacciones, manejo de errores, etc.

¢  Se basa en la capa de mensajería para el intercambio de mensajes necesario para la ejecución de los procesos de negocio

Orchestration

Development

Métodos Anónimos y Predicados en C# – Parte II

¿Y qué es un predicado?

Si utilizaron listas genéricas se habrán encontrado con que algunos método, como Find por ejemplo, toman como parámetro un predicado, bien, esto no es más que un delegado pero con una firma diferente, vamos a ver la definición:

       public delegate bool Predicate<T>(T obj);

Está claro que es un delegado que define un método que acepte un tipo T (cualquiera) y que retorne bool. Esto es para indicar que el objeto que pasa como parámetro cumple con el criterio de búsqueda, vamos a ver el método Find de la lista genérica. Echamos mano del Reflector para variar y vemos esto:

   1:  public T Find(Predicate match)

   2:  {

   3:      if (match == null)

   4:      {

   5:        ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);

   6:      }

   7:      for (int i = 0; i < this._size; i++)

   8:      {

   9:          if (match(this._items[i]))

  10:          {

  11:              return this._items[i];

  12:          }

  13:      }

  14:      return default(T);

  15:  }


Vemos que el truco está en la línea 9, ahí llama al predicado y le pregunta si el item actual (dentro de la iteración) cumple con alguna condición que estará en el predicado.
Vamos a ver una aplicación práctica

 

Ejemplo :

    class EndsWith

    {

        private string m_Suffix;

 

        // Initializes with suffix we want to match.

        public EndsWith(string Suffix)

        {

            m_Suffix = Suffix;

        }

 

        // Sets a different suffix to match.

        public string Suffix

        {

            get { return m_Suffix; }

            set { m_Suffix = value; }

        }

 

        // Gets the predicate.  Now it’s possible to re-use this predicate with various suffixes.

        public Predicate<string> Match

        {

            get { return IsMatch; }

        }

 

        private bool IsMatch(string s)

        {

            if ((s.Length >= m_Suffix.Length) &&

                (s.Substring(s.Length – m_Suffix.Length).ToLower()

                                                     == m_Suffix.ToLower()))

            {

                return true;

            }

            else

            {

                return false;

            }

        }

    }

 

    public class DinoClassification

    {

        public void Classify()

        {

            List<string> dinosaurs = new List<string>(new string[] {

            "Compsognathus", "Amargasaurus", "Oviraptor", "Velociraptor",

            "Deinonychus", "Dilophosaurus", "Gallimimus", "Triceratops"});

 

            Console.WriteLine("\nFind(EndsWith): {0}",

                dinosaurs.Find(new EndsWith("saurus").Match));

 

            EndsWith predicate = new EndsWith("tor");

 

            Console.WriteLine("\nFind(EndsWith): {0}",

                dinosaurs.Find(predicate.Match));

 

            predicate.Suffix = "hus";

 

            Console.WriteLine("\nFind(EndsWith): {0}",

                dinosaurs.Find(predicate.Match));

        }

    }

 

    public class Example

    {

        public static void Main()

        {

            DinoClassification dcl = new DinoClassification();

            dcl.Classify();

        }

    }

 lo corremos y vemos que funciona.

 

Ejemplo Predicados

 

Aquí esta URL para leer algo más sobre el tema:

http://www.mediacenter.vb-mundo.com/index.php?option=com_content&task=view&id=37

 

Development

Métodos Anónimos y Predicados en C# – Parte I

Los métodos anónimos fueron una novedad en la versión de C# .NET 2.0. Están pensados para simplificar la definición de manejadores de eventos cuando las tareas a realizar son simples.  

Pues usted se preguntará ¿y que és un método anónimo?  Un método anónimo es justamente eso, aquel método que no tiene un nombre específico. Y ahora usted se preguntará ¿y cómo invoco los método anónimos?, pues buena pregunta, la respuesta es usando Delegados.

Los delegados son una característica muy interesante del NetFramework que nos permiten pasar métodos como parámetros de otros métodos, extraño, puede ser, pero es menos complicado de lo que parece. En el NetFramework 2.0 nos podemos encontrar con los delegados por todas partes, en diferentes formas, como delegados, como predicados, como acciones.

¿Qué es un delegado?

Como dije antes un delegado nos permite pasar un método como parámetro de otro método, ok, sabemos cómo hacer para pasar tipos de datos como parámetros, simplemente declaramos en tipo y el nombre, detengámonos un momento, si yo quisiera indicar que en cierto lugar espero un método para utilizarlo qué cosas tengo que establecer. La respuesta es clara, el tipo de retorno del método y los parámetros que acepta, bueno, esto es justamente un delegado, una firma que nos permite establecer cómo deberá ser el método que esperamos.

Ejemplo :

Vamos a ver la declaración de un delegado para utlizarlo en un método nuestro como parámetro
.

     public delegate void MiDelegado(string mensaje);

Es muy claro que si quitamos la palabra delegate de esta declaración es idéntica a una declaración de un método cualquiera. Ahora vamos a crear un método que espere un delegado del tipo MiDelegado para invocar el método dentro.

 

     public void TestDelegado(MiDelegado delegado)

   {

          delegado("\r\n Vamos a MJ \r\n http://jonnathandeveloper2008.spaces.live.com/ \r\n Jonnathan!!!");

    }

Ok, este método va a tomar como parámetro un delegado del tipo MiDelegado (o sea un método que devuelva void y tome un string como parámetro) y luego lo va a invocar. Veamos la llamada al método.
Primero creamos el método que utlizaremos como parámetro del tipo MiDelegado.

    public void MetodoDelegado(string mensaje)

   {

      Console.WriteLine(mensaje);

    }

Sencillo, el método recibe un string lo escribe en la consola y no devuelve nada. Ahora vamos a ver cómo se invoca.

Más sencillo aún, lo corremos y vemos que funciona.

Ejemplo Delegados

Vemos declaramos el delegado y le pasamos como parámetro el método que cumple con el delegado. esto lo podríamos haber resumido así

       TestDelegado(new MiDelegado(delegate(string message)

       {

           Console.WriteLine(message);

       }));

Lo que hacemos aquí es definir en la misma línea el delegado y la implementación, esto es lo que se conoce como método anónimo. Es un método anónimo justamente porque no tiene nombre, si bien a simple vista puede parecer que el código se pone confuso, en muchas ocasiones es más práctico utilizar un método anónimo.

El detalle es que siempre hemos estado acostumbrados a nombrar las métodos, tanto aquellos que devuelven valores nulos o los que devuelven un cierto valor para su posterior uso.

Lo importante es que los métodos anónimos,  reduce la sobrecarga de codificación al crear instancias de delegados sin tener que crear un método independiente. Un método anónimo es declarado con la palabra clave delegate seguido de una lista de parámetros. Las líneas de código para el método están dentro del par de llaves {}. Todo esto debe ser referenciado por un tipo delegate que tenga la misma firma que el método anónimo, es así que, la invocación de los métodos anónimos se realiza usando esta referencia

Imaginemos que queremos asociar una única línea de código (o dos) como acción a realizar cuando se produzca un evento. Por ejemplo, que cuando se pulse un botón se muestre un mensaje de saludo. Lo que debíamos hacer hasta ahora era declarar una función del tipo adecuado y asociarla con un nuevo delegado al evento. Por ejemplo:

      private void button1_Click(object sender, System.EventArgs e)

      {

          MessageBox.Show("Hola");

      }

      button1.Click += new System.EventHandler(button1_Click);

Esto hace que al pulsar el botón se vea el saludo "Hola". Sin embargo es un poco engorroso para tan poca acción tener que crear una función como esta. Para evitarlo se han incluido en C# 2.0 los métodos anónimos.

Un método anónimo nos permite definir una función de manera implícita, sin necesidad de declararla. En el ejemplo anterior un método anónimo sustitutivo sería el siguiente:

     button1.Click += delegate { MessageBox.Show("Hola"); };

La única diferencia es que ahora no nos hace falta definir una función, lo hace automáticamente por nosotros el compilador a la hora de crear el ejecutable.

Dependiendo del tipo de evento que estemos asignando el compilador ya deriva de forma automática los parámetros que necesita el método anónimo así como el tipo de delegado que se debe crear (en este caso System.EventHandler).

En algunos tipos de eventos, como la pulsación del ratón y otros, necesitaremos acceder a los parámetros de éste para conocer cierta información. En este caso lo único que debemos hacer es declarar los argumentos tras la palabra delegate, así:

      button1.Click += delegate(object sender, EventArgs e) { MessageBox.Show(e.ToString()); };

Como se puede apreciar al declarar el método anónimo indicando en el delegado qué tipos de parámetro se necesitan y otorgándoles un nombre es posible hacer uso de ellos sin problemas desde el método anónimo.

 Métodos anónimos (Guía de programación de C#)

En versiones de C# anteriores a la versión 2.0, la única manera de declarar un delegado era utilizar métodos con nombre. C# 2.0 presenta los métodos anónimos, mientras que, en C# 3.0 y versiones posteriores, las expresiones lambda reemplazan a los métodos anónimos como la manera preferente de escribir código insertado. No obstante, la información sobre los métodos anónimos de este tema también se aplica a las expresiones lambda. Hay un caso en el que un método anónimo proporciona una funcionalidad que no se encuentra en las expresiones lambda. Los métodos anónimos permiten omitir la lista de parámetros, y esto significa que un método anónimo se puede convertir en delegados con diversas firmas. Esto no es posible con expresiones lambda

La creación de métodos anónimos es básicamente una forma de pasar un bloque de código como parámetro de delegado. Por ejemplo:

         button1.Click += delegate(System.Object o, System.EventArgs e)

            { System.Windows.Forms.MessageBox.Show("Click!"); };

O bien,

        // Create a delegate instance

        delegate void Del(int x);

 

        // Instantiate the delegate using an anonymous method

        Del d = delegate(int k) { /* … */ };

Mediante los métodos anónimos, se reduce la sobrecarga de codificación al crear instancias de delegados sin tener que crear un método independiente.

Por ejemplo, especificar un bloque de código en vez de un delegado puede ser útil en el caso de que la creación de un método parezca una sobrecarga innecesaria. Un buen ejemplo es cuando se inicia un nuevo subproceso. Esta clase crea un subproceso y también contiene el código que el subproceso ejecuta, sin necesidad de crear un método adicional para el delegado.

        void StartThread()

        {

            System.Threading.Thread t1 = new System.Threading.Thread

              (delegate()

              {

                  System.Console.Write("Hello, ");

                  System.Console.WriteLine("World!");

              });

            t1.Start();

        }

Nota:

El ámbito de los parámetros de un método anónimo es anonymous-method-block.

Es un error utilizar una instrucción de salto, como goto, break o continue, en un bloque de método anónimo cuyo destino está fuera del bloque. También es un error utilizar una instrucción de salto, como goto, break o continue, fuera de un bloque de método anónimo cuyo destino está dentro del bloque.

Las variables locales y los parámetros cuyo ámbito contiene una declaración de método anónimo se denominan variables externas o capturadas del método anónimo. Por ejemplo, en el segmento de código siguiente, n es una variable externa:

     int n = 0;

     Del d = delegate() { System.Console.WriteLine("Copy #:{0}", ++n); };

A diferencia de las variables locales, el período de duración de la variable externa se extiende hasta que los delegados que hacen referencia a los métodos anónimos cumplan con los requisitos para la recolección de elementos no utilizados. En el momento en que se crea el delegado, se captura el valor de n.

Un método anónimo no puede tener acceso a los parámetros ref u out de un ámbito externo.

No se puede tener acceso a ningún código no seguro dentro de anonymous-method-block.

El ejemplo siguiente muestra las dos maneras de crear instancias de un delegado:

·         Asociar el delegado a un método anónimo.

·         Asociar el delegado a un método con nombre (DoWork).

En cada uno de los casos, se muestra un mensaje cuando se invoca al delegado.

        // Declare a delegate

        delegate void Printer(string s);

 

        class TestClass

        {

            static void Main()

            {

                // Instatiate the delegate type using an anonymous method:

                Printer p = delegate(string j)

                {

                    System.Console.WriteLine(j);

                };

 

                // Results from the anonymous delegate call:

                p("The delegate using the anonymous method is called.");

 

                // The delegate instantiation using a named method "DoWork":

                p = new Printer(TestClass.DoWork);

 

                // Results from the old style delegate call:

                p("The delegate using the named method is called.");

            }

 

            // The method associated with the named delegate:

            static void DoWork(string k)

            {

                System.Console.WriteLine(k)

            }
      }

 

Development

SQL Server 2005 – Features

Mejoras del Sistema

SQL Server 2005 introduce un numero de perfeccionamientos que impactan en la manera en que el sistema de SQL Server puede ser administrado. Las mejoras incluyen:

ü  Soporte de memoria de Dynamic Address Windowing Extensions (AWE)

ü  Memoria Hot-add

ü  Afinidad Dinámica de CPU

Memoria Dinámica AWE

Se puede configurar SQL Server 2005 para usar AWE, usando la opción de configuración  awe enabled. Después podes setear las opciones min server memory y max server memory para que el SQL Server use memoria AWE dinámicamente según lo requerido. El siguiente ejemplo, muestra como usar la memoria AWE: 

 

**************************************************

sp_configure ‘show advanced options’, 1

RECONFIGURE

GO

 

sp_configure ‘awe enabled’, 1

RECONFIGURE

GO

*************************************************

Memoria Hot-add

Cuando se usa la memoria AWE, el SQL Server 2005 también puede sacar provecho del soporte de Windows Server 2003 para memoria hot-add. Si el hardware del Server soporta memoria hot-add, los administradores pueden agregar memoria física sin reiniciar el servicio SQL Server. El SQL Server usará memoria física adicional si es requerido.

Para aprovechar las memorias hot-add, el SQL Server debe estar ejecutándose en Windows Server 2003 Enterprise o la edición Datacenter con la opción configurada awe habilitada.  

Afinidad Dinámica de CPU

En SQL Server 2005, puedes reconfigurar la opción affinity mask sin tener que reiniciar el servicio. El SQL Server automáticamente ajusta el numero de CPUs schedulers usadas para juntar las conversaciones.

Perfeccionamiento del Almacenamiento de Datos

SQL Server 2005 introduce un numero de perfeccionamientos de almacenamiento de datos, incluyendo nuevos y perfeccionados tipos de datos y un tamaño de fila de una tabla mayor. Estas mejoras hacen el almacenamiento de datos más eficiente y flexible.

 

Nuevos y mejorados tipos de datos

varchar, nvarchar, and varbinary:
El máximo de Keyword que pude ser usado para extender el largo de alguno de estos tipos de datos es hasta 2^31 bytes (aproximadamente 2 GB).
xml:
Los valores para los datos xml pueden ser opcionalmente asociados con un  XML schema.

Mayor tamaño de Row

 

En las ediciones previas de SQL Server, el máximo de una fila de una tabla era 8 KB. Mientras que este es aun el máximo físico de una pagina, el SQL Server 2005 puede mover el reflujo de datos varchar, nvarchar, varbinary, o sql_variant a otra pagina manteniendo 24  byte puntero en la pagina original, haciendo posible almacenar una row que contenga mas de 8 KB de datos. Para acomodar el reflujo de esta manera, cada columna en la fila de la tabla debe tener un máximo de 8 KB. Cuando la combinación de todas las columnas es mayor a 8 KB, SQL Server va automáticamente a mover la columna más larga a una página de reflujo.

 

Nota Importante:

El limite 8 KB aplica solo para las columnas varchar, nvarchar, o varbinary definidos sin el max keyword. Cuando el max keyword es usado, los datos son implementados como un gran objeto usando un puntero a las páginas donde los datos están físicamente almacenados.

Mejoras de Tablas e Índices Particionados

Esto permite a una tabla ser esparcida a través de un número de Grupos de Archivos físicos, mejorando la performance y haciendo más fácil administrar los procesos archivados range-based.

 

partitioning

 

Esparcimiento de Tablas de Datos a través de Grupos de Archivos

Se puede particionar una tabla horizontalmente, así las filas son expandidas a través de múltiples Grupos de Archivos.  Implementando esta partición se obtienen los siguientes resultados:

 

ü  Mejorar la performance en sistemas de multiprocesadores. Las tablas particionadas puede aumentar la performance cuando están consultando grandes tablas en un sistema con 8 o más procesadores. El optimizador de consultas de SQL Server 2005 puede ejecutar consultas sobre múltiples particiones en paralelo, reduciendo el tiempo requerido del proceso.

 

ü  Administrar más fácil tablas grandes. Una tabla particionada hace la administración de data subsets mas fácil, las cuales se pueden agrupar lógicamente por un rango de datos. por ejemplo: Un requerimiento común de datos es trabajar solo con los datos del mes en curso. Se puede especificar la columna particionada, numero de particiones y el rango de valores de las columnas particionadas para cada partición. Un beneficio de particionar es que se pueden mover datos entre las tablas particionadas muy rápido con relación a tener que hacer un INSERT INTO SELECT FROM statement. Esto es porque los datos no están siendo movidos físicamente; solo la metadata concerniente al lugar de almacenamiento es lo que se mueve.

 

Snapshot Isolation Level

El SQL Server 2005 incluye una nueva transacción de isolation level llamada snapshot. Snapshot isolation permite a los usuarios leer previamente valores de datos usando una vista consistente transaccionalmente de la base de datos. En este isolation level, los lectores no bloquean otros lectores y escritores que están accediendo al mismo dato. Similarmente, los escritores no bloquean a los lectores. La operación de escritura en el snapshot isolation level esta basada en un mecanismo de bloqueo con detector de conflicto automático. El mecanismo de detección de conflictos evita que un usuario haga cambios basados en datos que otro usuario haya cambiado.

 

SnapShot

 

Como Trabaja Snapshot Isolation?

Snapshot isolation esta basado en row versioning, el cual da consistencia de lectura siguiendo una cadena de versiones que contienen las rows comprometidas de datos. Esta cadena está situada en una versión separada de almacenamiento alojada en tempdb. Varias versiones comprometidas de rows individuales de datos son creados durante la ejecución del UPDATE statement y recuperados por la operación SELECT a través de las consultas del snapshot. Las consultas Snapshot son consultas que se ejecutan bajo el snapshot isolation que lee los datos de snapshot.

Administración de snapshot isolation

Los Administradores pueden habilitar o no la snapshot isolation en una base de datos poniendo la opción ALLOW_SNAPSHOT_ISOLATION en ON u OFF en una statement CREATE DATABASE o ALTER DATABASE. El siguiente ejemplo muestra como habilitar la snapshot isolation:

 

ALTER DATABASE AdventureWorks

SET ALLOW_SNAPSHOT_ISOLATION ON

 

Cuando la snapshot isolation esta habilitada, las aplicaciones que quieran usarla deben setear el isolation level transaccional a SNAPSHOT para conectarse, según se indica en el siguiente ejemplo:

 

SET TRANSACTION ISOLATION LEVEL SNAPSHOT

 

Statements ejecutados en transacciones luego usarán snapshot isolation.

 

SQLiMail

SQLiMail es un nuevo sistema en SQL Server 2005.  Usa el Standard Simple Mail Transfer Protocol (SMTP) para enviar un e-mail desde una instancia de SQL Server 2005. Usando SQLiMail, las aplicaciones de base de datos pueden enviar e-mails que contengan resultados de consultas y archivos. SQLiMail esta diseñado para ser un sistema confiable, escalable y seguro para SQL Server.

 

Característica

Descripción

No Extended MAPI requirement

SQLiMail usa SMTP, no Extended MAPI.

Process isolation

El componente que envía e-mails se ejecuta en un proceso separado para minimizar el impacto en el SQL Server.

Failover accounts

Se puede especificar más de un servidor SMTP por perfil, así si el servidor SMTP no esta disponible, los mails aun pueden ser enviados.

Envío Desincronizado

SQLiMail usa Service Broker para enviar mensajes para evitar el bloqueo de un proceso almacenado.

Perfil de Seguridad

SQL Server ayuda a mejorar la seguridad dando la posibilidad de especificar que usuarios en una base de datos pueden acceder al perfil de SQLiMail.

Configuración Integrada

 

SQLiMail almacena la información de perfiles dentro del SQL Server. No es necesario administrar el perfil en una aplicación externa.

Instalar y configurar SQLiMail

Se puede usar el SQLiMail Configuratión Wizard para instalar y configurar SQLiMail en una base de datos. Se inicia el asistente desde el SQLiMail en la Management folder del Object Explorer. El asistente reúne la información, Incluyendo la base de datos a instalar y la información del usuario para crear un perfil SQLiMail.