« June 2010 | Main | October 2010 »

Adding External References to SQL CLR Projects

A common need when working with SQL CLR assemblies (or projects) is to add a reference to a third-party (or external) assembly. Interestingly enough though (at least as far as I can tell), the steps for doing this are hardly ever documented.

So this blog post will fix that – by documenting just how you go about adding External References in Visual Studio to SQL Server CLR projects or assemblies.

Danger

In my recent webcast: Introduction to SQL CLR Extensibility, I was hoping to cover exactly how to do this. I was also going to (and partially did) throw out a few caveats when doing this.

Specifically: don’t go crazy adding external references. Good code IS reusable code – so good developers may occasionally run into the need to drop of ‘core’ logic into their CLR assemblies. On the other hand, lots of complex business logic just isn’t going to find a good home in your SQL Server’s memory-space; bundling up tons of business rules and the likes into SQL CLR assemblies (or as referenced assemblies) is a great way to bloat your CLR memory usage and, more importantly, will make versioning your code PAINFUL if you start to abuse this power.

Setting the Stage

For this tutorial, I’m going to assume that you’ve already GOT a CLR project/assembly that you’ve already deployed successfully to SQL Server – and that you’ve got it running as needed (minus the external references). If you don’t have that, then watch the webcast from the link provided up above, and it will show you how to get to this ‘assumed’ point.

To that end, if you’re an experience .NET Developer, your first instinct is to right-click on the References folder in Solution Explorer within your solution, and click on the Add Reference option. That in turn brings up the following:

AddCLRReference

The only problem, of course, is that it doesn’t have any ‘browse’ options or tabs. It does let you reference other projects – but even that has some serious limitations too – to the point where even if you were to add your existing ‘solutions’ as projects and try to build them and reference them, you won’t be able to do so.

What’s Going On?

The key to adding external references to a SQL CLR project is understanding that the ‘Add References’ dialog isn’t showing for what’s on YOUR development machine. Instead, it’s polling the SQL Server you’ve CONNECTED TO as part of your project. So, if you’re a developer you’re used to Visual Studio letting you add references to projects and DLLs that exist on YOUR workstation. Then, when you deploy or publish your code, those references are bundled along with your code and copied out to the destination.

SQL CLR projects DO NOT work that way. Instead, they ONLY let you reference assemblies that are already located on the server and which have already been REFERENCED with the server.

Once you know that, the rest is easy.

Adding Reference Assemblies to Your SQL Server

So, since you can only add ‘registered’ assemblies to your projects, the next question is how do you do that?

In this tutorial, I’m going to start with a brand NEW assembly. To do that I’m going to do the following:

Open Up a Brand New Instance of Visual Studio (I’ve already got my existing Solution open).

Create a New Project.

I’m going to Specify the Visual C# Type, and specify that I want to create a Class Library:

NewClassLibrary

I’m going to name this Class Library ‘CoreLogic’:

CoreLogic

Then, in that Class Library, I’m just going to add in some ‘core’ logic that I want to be able to ‘consume’ from my referencing assembly.

In this case, I’m just going to use some patently lame logic – which flips a string around (i.e. it turns ‘string’ into ‘gnirts’):

Then, at that point, I’m going to BUILD my ‘CoreLogic’ project, and then copy the CoreLogic.dll that came from the \bin\Debug\CoreLogic.dll folder within my project out to a location on my server.

From here I can then register the ‘CoreLogic.dll’ on my server – and it will then be available as a potential reference from within my other solution.

To register my assembly, I just need to use CREATE ASSEMBLY as follows:

 CreateAssembly

And note that I’m creating this assembly in the DATABASE that I’ve connected to in my SQL CLR project (i.e., the project where I want to be able to add the external reference).

Full Circle – Adding the Reference to your CLR Project

Now that I’ve created the assembly up on my SQL Server, if I go back to the original SQL CLR project where I want to be able to add a reference to my ‘Core Logic’:

AddReference

I’ll see the reference to CoreLogic show up if I again right click on the References node and select Add Reference:

added

From here I’m able to then add a using statement and so on – just as you would expect with a ‘normal’ .NET project.

Troubleshooting

Depending upon how you’re deploying your SQL Server CLR Assembly or Project, you may run into some ugly issues when you now try to push up your new assembly – and it has references to external resources.

The best way to deal with this in my experience is just to clean house (i.e., destroy your CLR assembly) and then re-register it.

To do this:

1) DROP any sprocs, udfs, triggers, types, etc that DEPEND upon YOUR CLR Assembly.

2) Issue a DROP ASSEMBLY MyAssemblyNameHere command – and you’ll now free up all the ‘references’ that this assembly thinks it has.

3) (With your external assembly already registered/loaded) Issue a CREATE ASSEMBLY MyAssemblyNameHere command – or push ‘Deploy’ from Visual Studio again – and it will push your CLR Assembly up to the server.

4) Recreate any of your sprocs, udfs, triggers, etc that you nuked in step 1.



Introduction to SQL CLR Extensibility

This blog post provides additional resources and links for my Introduction to SQL CLR Extensibility webinar.

Background / Overview

There are a number of decent resources out there that introduce SQL CLR.

Greg Low’s SQL Server CLR Integration book is a great, high-level, overview.

Bob Beauchemin’s A Developer’s Guide to SQL Server 2005 provides some fantastic, low-level, info. (And I wouldn’t worry much about it being for SQL Server 2005).

I’ve also found that Derek Comingore’s and Douglas Hinson’s Professional SQL Server 2005 CLR Programming does a nice job of covering details along with providing a ‘soft’ introduction.

Sadly, I haven’t found too many online articles that do a great job of introducing SQL Server CLR, but one from SQL Server Magazine from a while back does serve as a great overview/introduction to SQL Server CLR.

Performance

DBAs worry about the performance overhead of the CLR. The tricky news is that the CLR is already LOADED into your SQL Server. It’s sitting there, in memory, just waiting to run your code. So, in that regard, just as you can run ‘dumb’ queries through the ‘T-SQL’ engine, you can run ‘dumb’ queries through the ‘CLR’ as well.

Moreover, it’s important to point out that the CLR can hands-down outperform T-SQL in a LARGE number of cases. Knowing whether or not it’s faster or not really depends upon you doing a thorough job of testing performance. Using estimated and actual execution plans to profile your performance is a good start – but since those execution plans LIE, you’ll want to make sure that you’re testing ALL implementations through SQL Server Profiler – so that you get an accurate feel for what’s up. (And I cover this in a bit more detail within the presentation linked at the top of this post.)

And, when it comes to performance, one thing you may find is that when using the CLR you’ll need to do lots of ‘SCANNING’ functionality. Scanning, of course, is a LESS performant (sometimes HORRIBLE) option. But, in some cases you may NEED to scan with increased capabilities that the CLR offers (to parse out business rules, handle special formatting, and so on). In cases like this, don’t abandon the CLR if you find that it’s scanning. Instead, try to use SQL Server intelligently by forcing it to SLICE data with index seeks, and the ‘DICE’ data with the CLR. That way you can get the best of ‘both worlds’ – in the sense that you can balance SQL Server perf benefits with CLR extensibility/flexibility benefits.

I actually wrote about this a while back on DevProConnections – and the approach outlined there works for both CLR and T-SQL queries/approaches where you need to generate high-performance results:

Generating High-Performance SQL Server Query Results

For additional information about just how well the CLR can handle itself from a performance perspective, as well as in terms of things to watch out for (given the fact that strings in the CLR are immutable), make sure to check out a recent blog post from Aaron Bertrand (where he talks about realizing the benefits of SQL Server CLR performance).

His post, in turn, points to a post (which, in turn, points to another post) by Adam Machanic that goes very heavily into issues with optimizing SQL Server CLR performance as well:

SQLCLR String Splitting Part 2: Even Faster, Even More Scalable

Faster, More Scalable SQLCLR String Splitting

Demos

Finally, I’m including a link to the demos I showcased in this presentation.

Download: Introduction to SQL CLR Extensibility Demo (.zip)

The demos are available as a .zip file – which includes the slides for this presentation (as a .pdf), and a ‘Demos’ folder where I’ve got the scripts I used during the demos, and where I’ve also included both of the VS 2008 Projects that I used in this presentation. (Well, actually, I only got around to using the first project – but I’ve outlined the use of the second project in this blog post – where I show how to add external references in SQL CLR Assemblies.)