Running C# libraries with the SQL CLR

You can run your dlls from inside SQL - but it is a bit limited

Sometimes you need your SQL server to run a little bit of one of your programs, this is not a common case, but I have found it does happen. It is quite possible and not too complicated, but you are limited in what you can use. For example, even in SQL 2008, the maximum framework you can run is 3.5 (really 2.0), so anything with 4.0 is off limits due to the CLR. Also, many dlls are also off limits such as System.Data.Linq and System.Data.Entity so kiss most of your ORM solutions goodbye if you plan on doing this.

For this example, I am going to use a simple table in my SQL which will follow after this. For the example, I am going to write a C# method that writes in a new Widget to the Widgets table in the 'SqlClrTest' database at the current time - nothing fancy or useful, but it is easy to understand.
CREATE TABLE Widget(
	Id INT NOT NULL IDENTITY PRIMARY KEY,
	Name NVARCHAR(100) NOT NULL,
	Created DATETIME NOT NULL
);

Now you need to set up your environment to handle the CLR:
--allow you to use it
ALTER DATABASE SqlClrTest SET TRUSTWORTHY ON;

--and turn it on
sp_configure 'clr enabled', 1
GO
reconfigure
GO

Now in a new library, I will make a simple class with older ADO that inserts a new entry. Yes, I know this isn't written well, but it is very simple to understand...
using System;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;

namespace SqlClr
{
    public class Widget
    {
        public Widget() { }

        [SqlProcedure]
        public static void Insert(SqlString name)
        {
            string connectionString = 
                "Data Source=.\\sqlexpress;
                 Initial Catalog=SqlClrTest;
                 Integrated Security=True";
            string date = SqlDateTime
                .Parse(DateTime.Now.ToString())
            SqlConnection conn = new 
                SqlConnection(connectionString);

            SqlCommand sqlComm = new 
                SqlCommand("INSERT INTO Widget 
                (Name, Created) VALUES 
                ('" + name.ToString() + "', '" + 
                date + "')", conn);

            conn.Open();
            sqlComm.ExecuteNonQuery();
            conn.Close();
        }
    }
}

Notice that the inputs are defined in System.Data.SqlType, also, the method is painted with a [SqlProcedure] attribute. Now compile the dll and take down the path to it. Go back into SQL and enter the following to compile the assembly into SQL:
CREATE ASSEMBLY Sql_Clr
AUTHORIZATION dbo
FROM 'C:\path-to-assembly\SqlClr.dll'
WITH PERMISSION_SET = UNSAFE;

Now you will notice it shows up under your table > programmability > assemblies directory if it worked correctly. I gave it a name with an underscore so you can see where that comes into play later. Next you will need to make a stored procedure that calls the method:
CREATE PROCEDURE WidgetInsert 
	@name nvarchar(100)
AS EXTERNAL 
	NAME Sql_Clr.[SqlClr.Widget].Insert;
GO

You can see that you call it in this format: SqlDllName[C#DllName].Method. Now all that is left is to call the method in SQL:
EXEC WidgetInsert 'NEW WIDGET'

And you have successfully (in the most round-about way possible) used a SQL stored procedure to call a .Net dll to run a method to update the database.
Comments are closed