viernes, 23 de julio de 2010

[Tutorial] CLR Stored Procedures (Sql Server)

CLR Stored Procedures

El CLR está integrado a SqlServer, y gracias a eso podemos crear objetos de base de datos usando cualquier lenguaje de .Net como C#, VB.Net, F# entre otros. Entre las mejores prácticas de uso en para acciones que no conlleven acceso a datos, como string parsing, comunicación TCP/IP, Webservices, leer o escribir archivos, etc, es recomendable utilizar objetos CLR.


Crear el Proyecto
Ahora veremos como crear un proyecto sql server desde visual studio:

1.- Hacemos click en New Project o Nuevo Proyecto, y selecionamos DataBase > Sql Server > Visual C# SQL CLR Database Proyect. Le damos un nombre al proyecto y aceptamos.
2.- Se nos abre una ventana para configurar la conexión a la base de datos, si no aparece o la cerraron, pueden sacarla de nuevo en las propiedades del proyecto y luego en la pestaña Database.
3.- Seguimos los pasos del asistente y llenamos los datos de conexión en la ventana que nos apare y hacemos click en OK, con ésto enlazamos el proyecto con la base de datos.
4.- Por último, de hacemos click derecho en el Proyecto > Añadir > Procedimiento Almacenado (Stored Procedure), Le damos un nombre y Aceptar.



Con eso tenemos la clase lista para desarrollar los Stored Procedures que queramos.


DEMO:

Le damos doble click al archivo de clase que creamos y vemos que está de esta manera:

Código
using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
 
 
public partial class StoredProcedures
{
   [Microsoft.SqlServer.Server.SqlProcedure]
   public static void ProcedureDemo()
   {
       // Put your code here
   }
};
 

En esa clase van a ir todos los Stored procedures que querramos crear, puede ir uno por clase, o una clase con varios métodos, en donde cada método es un SP.

Supongamos que necesito hacer un SP que me liste los archivos de determinado directorio del servidor y los pueda filtrar. La manera correcta y más fácil de hacer esto es con un CLR SP, ya que podemos usar las clases que nos da .Net.

El Stored Procedure quedaría de esta manera:

Código
using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.IO;
 
 
public partial class StoredProcedures
{
   //este es el atributo que marca el método como SP, los parámetros del método
   //serán los parámetros del SP, Noten que el valor de retorno es VOID.
   [Microsoft.SqlServer.Server.SqlProcedure]
   public static void ProcedureDemo(string path, string filter)
   {
       // Crea el record y especifica la metadata para las columnas
       SqlDataRecord record = new SqlDataRecord(
           new SqlMetaData("FileName", SqlDbType.NVarChar, 500),
           new SqlMetaData("Size", SqlDbType.Int));
 
 
       //SqlContext es nuestra vía de comunicación con Sql Server
       //Si quieren validar si el ensamblado está corriendo en Sql Server
       // Y existe una conexión disponible pueden validarlo con la propiedad
       // IsAvailable de SqlContext que devuelve true o false dependiendo del caso.
 
       // Marca el inicio de la incorporación de registros
       SqlContext.Pipe.SendResultsStart(record);
 
       DirectoryInfo dInfo = new DirectoryInfo(path);
       foreach (FileInfo file in dInfo.GetFiles(filter))
       {
           //Le damos valor a las columnas
           record.SetString(0, file.FullName);
           // y enviamos el registro
           SqlContext.Pipe.SendResultsRow(record);
       }
 
       // Marca el fin y envia los resultados
       SqlContext.Pipe.SendResultsEnd();
   }
};

Cuando ya terminemos el SP, Simplemente click derecho sobre el proyecto y click en Deploy y se va directo a Sql Server y se crea el SP donde se podrá usar sin problema alguno.  

Otro paso importante es habilitar el CLR dentro de Sql Server, lo podemos hacer de la siguiente manera:

Código
sp_configure 'clr enabled', 1;
RECONFIGURE;
GO
 

Aunque hay casos en donde el assembly requiere privilegios elevados, cuando éste sea el caso necesitan marcar el assembly como UNSAFE, es decir sin restricciones. Click derecho en el proyecto > Propiedades > En la pestaña Database seleccionamos el Permission Level como Unsafe.

Y luego pueden ejecutar el siguiente query, el cual debería habilitar la ejecución de Ensamblados UNSAFE.

Código
ALTER DATABASE TESTING
 
SET TRUSTWORTHY ON

Resultado



Espero les sea de ayuda,

Un saludo!

14 comentarios:

  1. Gracias por existir en primer lugar, en segundo lugar, tengo un problema, me dice Deploy failed y no me aparece el sp en la bd, no se q estoy haciendo mal =(

    ResponderEliminar
  2. Claro, si sale Deploy failed, entonces significa que hay un error, dime que otro errores te aparecen. Hay que hacer troubleshooting

    ResponderEliminar
  3. Muchas gracias por tu pronta respuesta y nuevamente gracias por existir. tube problemas habilitando el clr en SQl server, despues me pedía configurar el firewall, luego me di cuenta q el target framework es 4.0 (en las propiedades del proyecto) y en la pagina de msdn dice q es compatible con las versiones 2.0, 3.0 y 3.5. muchas gracias, ya puedo crear los SP.

    Ahora el problema que veo, es hacer los select de tablas y eso, ultimamente he usado linq pero no se si es compatible, este es el primer proyecto de este tipo que he creado.


    otra cosa el SP me sale en el SQL Server con un candado, así como bloqueado y no lo puedo editar, sabes como podría modificar esto?

    ResponderEliminar
  4. Ah ok, qué versión de Sql Server estás usando?

    Si vale, no hay problemas en que uses LINQ.

    Hasta donde se, tienes que modificarlo desde Visual Studio siempre. Lo único que puedes hacer es borrar la referencia al assembly o borrar el SP.

    Un saludo!

    ResponderEliminar
  5. SQL server 2008, tengo todas las referencias a la bd en otro proyecto, ya que trabajo en MVC, vamos a ver si el linq se porta como siempre =D

    ResponderEliminar
  6. no tengo la minima idea de como hacer un select de alguna table =(, y no me deja agregar referencias de otros proyectos, que no sean del mismo tipo, estoy viendo el msdn

    ResponderEliminar
  7. Hola! gracias por el articulo, una pregunta:
    como puedo instalar dicho stored procedure que se genero en VS sin tener instalado el VS en la compu donde tengo la DB??

    ResponderEliminar
  8. Hola,

    Bueno, una vez que tengas el Assembly compilado:

    CREATE ASSEMBLY MiProc FROM 'C:\MiProc.dll'
    CREATE PROCEDURE NombreDelSP
    AS EXTERNAL NAME MiProc.Clase.Metodo
    EXEC HelloWorld

    Recuerda asegurarte que la ruta al método sea correcta.

    Si tienes algun namespace de por medio, recuerda ponerlo bien cuando apuntes al método en AS EXTERNAL NAME. La mayoría de los errores pasan ahí..

    Un saludo!

    ResponderEliminar
  9. Hola. A mi proyecto del tipo [SQL Server Project] no puedo añadirle una referencia a [System.Data.Linq]. Esto es porque no aparece en la lista de referencias del cuadro de diálogo "Add References". Tampoco hay opción "Browse". Esto hace que no pueda escribir mis consultas en LinQ (que es lo que quiero) en vez de Transact-SQL (como todos ejemplos que veo en Internet). ¿Cómo hago?. Gracias y un saludo

    ResponderEliminar
  10. Disculpa Jorge, pero no vi la notificación de que habías escrito un comentario.

    Qué versión del Framework estás usando?

    ResponderEliminar
  11. Mira este enlace:

    http://luke.breuer.com/time/item/SQL2005_using_LINQ_in_SQLCLR/213.aspx

    ResponderEliminar
  12. me lo anoto para verlo dentro de poco ... muchas gracias.

    ResponderEliminar
  13. Αs а result of the horrific inсіdent, the 23-year-old bride will have
    to ρay foг a ԁress with a ѕhοrt јaсket in
    nеt oг lacе. Ϲarefullу chοose yοur nеcκline as it
    can become vеry ѕtгessful if the finаl fitting іs lеft to thе last-minute particularly
    if yοu arе getting marrіed anԁ friеnds
    аnd family lеavеs little roоm to exercisе.



    Feel frеe to vіsit my ωeb-sіte - ao cuoi

    ResponderEliminar