En este apartado vamos a ver una de las novedades más significativas de SQL Server a partir de 2005 que es la integración con el Common Language Runtime (CLR) de .NET.
Como ejemplo, vamos a crear un procedimiento almacenado muy sencillo y de paso a configurar nuestro SGBD para ello.
Primeramente creamos un Proyecto de Base de Datos SQL Server. Eso lo hacemos partiendo del lenguaje con el que queramos programar (por ejemplo, C#) y de ahí Database (Base de datos), Proyecto de SQL Server. A partir de este momento nos va a aparecer el cuadro de diálogo típico de conexión a un servidor SQL Server donde además elegiremos la base de datos a la que conectarnos. Normalmente nos aparecerá un aviso preguntándonos si deseamos habilitar la depuración SQL/CLR, le vamos a decir que sí.
Una vez creada la solución, vamos a añadir un Procedimiento Almacenado (en Agregar Nuevo Elemento). Le vamos a llamar (¡como no!) HolaMundo.cs. Nos aparecerá una plantilla de código similar a esta:
[Microsoft.SqlServer.Server.SqlProcedure]
public static void HolaMundo()
{
// Put your code here
}
Como podemos observar, tenemos un atributo llamado SqlProcedure al cual le vamos a añadir un atributo llamado Name con el nombre de nuestro procedimiento almacenado (HolaMundo). Este nombre será el que realmente usemos desde T-SQL y puede ser diferente a la función. Nos quedará algo como esto:
[Microsoft.SqlServer.Server.SqlProcedure(Name=“HolaMundo”)]
En el cuerpo de la función vamos a introducir la siguiente línea de código:
SqlContext.Pipe.Send(“Hola Mundo”);
SqlContext nos permite tener comunicación con SQL Server, en este caso, mediante un pipe. Esta línea nos permite enviar entre otras cosas, un mensaje al servidor, pero podemos enviar entre otras cosas, un DataReader.
A continuación compilamos con Generar Solución y después hacemos lo que sería la implementación en SQL Server (Implementar Solución). Una vez hecho esto, en nuestro IDE en el explorador de servidores en el item Ensamblados, podemos ver el generado por nuestra solución. Por otra parte, si abrimos Management Studio de SQL Server en el mismo apartado Ensamblados dentro de Programación, aparece también, y en el de Procedimientos Almacenados se muestra con el nombre que previamente le dimos en el atributo Name.
Si ahora intentamos ejecutar este procedimiento con EXEC HolaMundo, el Management Studio nos va a lanzar el error siguiente:
La ejecución de código de usuario en .NET Framework está deshabilitada. Habilite la opción de configuración “clr enabled”.
Esto se debe a que la integración CLR no está habilitada por defecto en SQL Sercer (por razones de seguridad). Para habilitarla no tenemos más que entrar en la aplicación de Configuración de Superficie de SQL Server y en Configuración de superficie para características. Dentro de este apartado en el árbol Motor de base de datos-> Integración CLR marcamos Habilitar integración CLR. Si ahora ejecutamos el procedimiento almacenado, funcionará perfectamente, aunque inicialmente tardará un poco debido a que se está compilando.
La verdadera novedad a nivel funcional de todo esto es que podemos llamar a clases externas .NET o webservices por ejemplo desde este tipo de procedimientos.
Ahora vamos a probar creando un archivo, para lo cual procedemos a importar el namespace System.IO. A partir de aquí, nuestro procedimiento ahora va a necesitar un argumento de entrada que consiste en el texto que vamos a grabar dentro del fichero. Veamos el código del ejemplo:
using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.IO;
public partial class StoredProcedures
{
[Microsoft.SqlServer.Server.SqlProcedure(Name=“HolaMundo”)]
public static void HolaMundo(SqlString valor)
{
using (StreamWriter escritor = File.CreateText(@”c:\test\holamundo.txt”))
{
escritor.Write(valor.ToString());
}
SqlContext.Pipe.Send(valor.ToString());
}
};
Como puede comprobarse, ahora definimos el procedimiento de forma que espere un SqlString valor y con un StreamWriter lo metemos en el archivo test en el directorio C:\
Volvemos a compilar e implementar y a ejecutar desde SQL Server 2005. Ahora, como podemos comprobar, nos vuelve a dar un error:
Mens 6522, Nivel 16, Estado 1, Procedimiento HolaMundo, Línea 0
Error de .NET Framework durante la ejecución de la rutina o agregado definido por el usuario “HolaMundo”:
System.Security.SecurityException: Request for the permission of type ‘System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089’ failed.
System.Security.SecurityException:
at System.Security.CodeAccessSecurityEngine.Check(Object demand, StackCrawlMark& stackMark, Boolean isPermSet)
at System.Security.CodeAccessPermission.Demand()
at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy)
at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options)
at System.IO.StreamWriter.CreateFile(String path, Boolean append)
at System.IO.StreamWriter..ctor(String path, Boolean append, Encoding encoding, Int32 bufferSize)
at System.IO.StreamWriter..ctor(String path, Boolean append)
at System.IO.File.CreateText(String path)
at StoredProcedures.HolaMundo(SqlString valor)
La explicación es que esta rutina intenta acceder a procedimientos externos a SQL Server y no tiene permiso para ello, a diferencia del procedimiento anterior que únicamente mostraba un texto sin necesidad de recurrir a, como en este caso, operaciones de escritura sobre un fichero.
Para solucionar esto, lo primero que hemos de hacer en nuestras propiedades de proyecto es, en el apartado Base de datos, ajustar el nivel de permisos a External (por defecto está en Safe), aunque con esto sólo no basta. También hemos de ajustar un parámetro de configuración de nuestra base de datos:
alter database MiBD
set trustworthy on
Volvemos a implementar nuestra solución y ejecutamos-. Ahora si vamos a la carpeta test en C:\ veremos como se ha creado el archivo con el texto que le dimos. De esta forma hemos accedido a un namespace de .NET desde SQL Server lo que demuestra que podemos interactuar de forma fácil con el CLR .NET.
* Transcrito de un screencast creado por Misael Monterroca.