CLR Integration

You might also like

Download as doc, pdf, or txt
Download as doc, pdf, or txt
You are on page 1of 16

CLR Integration

In
SQL Server 2005

Page 1 of 16 Clarion Technologies Pvt. Ltd, Pune Version 1.0


Table of Contents
INTRODUCTION...............................................................................................3
OVERVIEW OF CLR INTEGRATION....................................................................5
CLR AND ITS ALTERNATIVES...........................................................................7
WRITING MANAGED CODE.............................................................................11
DEFAULT SUPPORTED .NET FRAMEWORK LIBRARIES ....................................14
ENABLING CLR INTEGRATION........................................................................14
USEFUL LINKS................................................................................................15
QUESTIONS AND ANSWERS ..........................................................................16
6

Page 2 of 16 Clarion Technologies Pvt. Ltd, Pune Version 1.0


Introduction

The common language runtime (CLR) is the heart of the Microsoft .NET
Framework and provides the execution environment for all .NET Framework code. Code
that runs within the CLR is referred to as managed code. The CLR provides various
functions and services required for program execution, including just-in-time (JIT)
compilation, allocating and managing memory, enforcing type safety, exception
handling, thread management, and security.

With the CLR hosted in Microsoft SQL Server (called CLR integration), you can author
stored procedures, triggers, user-defined functions, user-defined types, and user-
defined aggregates in managed code. Because managed code compiles to native code
prior to execution, you can achieve significant performance increases in some
scenarios.

Managed code uses Code Access Security (CAS), code links, and application domains
to prevent assemblies from performing certain operations. SQL Server 2005 uses CAS
to help secure the managed code and prevent compromise of the operating system or
database server.

Advantages of CLR Integration:

Transact-SQL is specifically designed for direct data access and manipulation in


the database. While Transact-SQL excels at data access and management, it does not
have programming constructs that make data manipulation and computation easy. For
example, Transact-SQL does not support arrays, collections, for-each loops, bit
shifting, or classes. While some of these constructs can be simulated in Transact-SQL,
managed code has integrated support for these constructs. Depending on the scenario,
these features can provide a compelling reason to implement certain database
functionality in managed code.
Microsoft Visual Basic .NET and Microsoft Visual C# offer object-oriented
capabilities such as encapsulation, inheritance, and polymorphism. Related code can
now be easily organized into classes and namespaces. When you are working with
large amounts of server code, this allows you to more easily organize and maintain
your code.
Managed code is better suited than Transact-SQL for calculations and
complicated execution logic, and features extensive support for many complex tasks,
including string handling and regular expressions. With the functionality found in the
.NET Framework Library, you have access to thousands of pre-built classes and
routines. These can be easily accessed from any stored procedure, trigger or user
defined function. The Base Class Library (BCL) includes classes that provide
functionality for string manipulation, advanced math operations, file access,
cryptography, and more.

Choosing Between Transact-SQL and Managed Code

When writing stored procedures, triggers, and user-defined functions, one


decision you must make is whether to use traditional Transact-SQL, or a .NET
Framework language such as Visual Basic .NET or Visual C#. Use Transact-SQL for
data access with little or no procedural logic. Use managed code for CPU-intensive
functions and procedures that feature complex logic, or when you want to make use of
the BCL of the .NET Framework.

Choosing Between Execution in the Server and Execution in the Client

Another factor in your decision about whether to use Transact-SQL or managed


code is where you would like your code to reside, the server computer or the client
computer. Both Transact-SQL and managed code can be run on the server. This places
code and data close together, and allows you to take advantage of the processing
power of the server. On the other hand, you may wish to avoid placing processor
intensive tasks on your database server. Most client computers today are very
powerful, and you may wish to take advantage of this processing power by placing as
much code as possible on the client. Managed code can run on a client computer, while
Transact-SQL cannot.

Choosing Between Extended Stored Procedures and Managed Code

Extended stored procedures can be built to perform functionality not possible


with Transact-SQL stored procedures. Extended stored procedures can, however,
compromise the integrity of the SQL Server process, while managed code that is
verified to be type-safe cannot. Further, memory management, scheduling of threads
and fibers, and synchronization services are more deeply integrated between the
managed code of the CLR and SQL Server. With CLR integration, you have a more
secure, scalable way than extended stored procedures to write the stored procedures
you need to perform tasks not possible in Transact-SQL.
Overview of CLR Integration

What follows is a brief overview of the SQL Server functionality that is enabled
by CLR integration and how Visual Studio 2005 supports these features.

Manual Deployment
Registering and executing managed code in the database consists of the following
steps:
1. The developer writes a managed program as a set of class definitions. SQL
Server routines—stored procedures, functions, or triggers—are written as static
(or Shared in Microsoft Visual Basic .NET) methods of a class. User-defined
types and aggregates are written as entire classes. The developer compiles the
code and creates an assembly.
2. The assembly is uploaded into a SQL Server database, where it is stored in the
system catalogs using the CREATE ASSEMBLY data definition language (DDL)
statement.
3. Transact-SQL (T-SQL) objects, such as routines, types, and aggregates are
then created and bound to entry points (methods in the case of routines and
classes for types and aggregates) in the assembly that has been already
uploaded. This is accomplished using the CREATE
PROCEDURE/FUNCTION/TRIGGER/TYPE/AGGREGATE statements.
4. After routines are created, they can be used like T-SQL routines by applications.
For example, CLR functions can be called from T-SQL queries and CLR
procedures can be called from a client application or from a T-SQL batch as if
they were T-SQL procedures.

Building, Deploying, and Debugging Using Visual Studio


Visual Studio 2005 supports development, deployment, and debugging of managed
code in SQL Server 2005. A new SQL Server Project provides code templates that
make it easy for developers to get started writing code for CLR-based database
routines, types and aggregates. This project also allows developers to add references
to other assemblies in the database.
When a SQL Server Project is built, it is compiled into an assembly. Deploying the
project uploads the assembly binary into the SQL Server database that is associated
with the project. The deploy operation also automatically creates the routines, types,
and aggregates defined in the assembly in the database based on the custom
attributes (SqlProcedure, SqlFunction, SqlTrigger, etc.) in the code. Deploying also
uploads the source code and debugging symbols (the .pdb file) associated with the
assembly.
As debugging is a fundamental part of the developer experience for any platform, SQL
Server 2005 and Visual Studio 2005 provide database programmers with such
capabilities. A key feature in debugging SQL Server 2005 objects is the ease of setup
and use. Connections to the computer running SQL Server may be debugged in much
the same way as processes running under a traditional operating system. Functionality
of the debugger is not affected by the type of connection to the server that the client
has: both Tabular Data Stream (TDS) and HTTP connections can be debugged. In
addition, debugging works seamlessly across languages, allowing the user to step from
T-SQL into CLR methods and vice versa.
CLR and Its alternatives

In evaluating the use of CLR integration a developer needs to compare it to the other
available options. Here we aim to provide a base for that comparison, positioning it
against existing programming techniques: Transact-SQL, extended stored procedures,
and code in the middle-tier. In this section we will concentrate on user defined
routines.
CLR vs. Transact-SQL
Transact-SQL (T-SQL) is the native programming language supported by SQL Server.
Like most versions of SQL, it contains data manipulation features and data definition
features. The data manipulation features can be broadly categorized into two parts: a
declarative query language (composed of SELECT/INSERT/UPDATE/DELETE
statements) and a procedural language (WHILE, assignment, triggers, cursors, etc.)
Broadly speaking, CLR support in SQL Server provides an alternative to the procedural
portion of T-SQL.
Even without CLR support, it is important to recognize that database applications
should use the declarative query language as much as possible. This portion of the
language is able to leverage the power of the query processor, which is best able to
optimize and perform bulk operations. Database applications should only resort to
procedural programming to express logic that cannot be expressed within the query
language.
All of this remains true with CLR support in SQL Server: the CLR should not be used to
write procedural code that can be expressed using the declarative features of the T-
SQL language. Developers should be aware that there are a number of significant
enhancements to the T-SQL query language in SQL Server 2005 that augment the
expressive power of the T-SQL query language, and should ensure that they are taking
full advantage of them before writing procedural code, whether in the CLR or not.
Some of these added features include:
• The ability to write recursive queries to traverse recursive hierarchies in
a table
• New analytical functions such as RANK and ROW_NUMBER that allow
ranking rows in a result set
• New relational operators such as EXCEPT, INTERSECT, APPLY, PIVOT and
UNPIVOT

T-SQL versus CLR: a performance comparison


When it comes to core performance, remember three cardinal rules when choosing
between T-SQL and CLR:

1. Set-based operations tend to work better in T-SQL.


This is because Microsoft has tweaked T-SQL and the query engine in
general over many years to use advanced algorithms for processing and
caching set-based result sets effectively inside the database. In comparison,
CLR tends to use an object-based data manipulation and access strategy
unless CLR is using T-SQL underneath.
2. Procedural and recursive code works much better in CLR.
Historically, CLR code and higher-level programming languages such as C#
and VB .NET have offered better support for procedural and recursive code.
This is because such languages are designed from the ground up to support
per method call-based stack frames and activation records, and they do not
suffer from limits such as a maximum call depth of 32 in recursive
operations. In other words, if you tried to calculate a factorial using
recursion in T-SQL, you could not calculate the factorial of 33 because T-
SQL cannot call deeper than 32 stored procedures, but CLR wouldn't have
any problem doing such an operation. Also, because stack frames are not
shared, you would also get much better concurrent performance.

Note: You can still do recursion in T-SQL using CTE (Common


Table Expressions), which are subject to a default (but configurable) call
depth of 100 in SQL Server 2005.

3. You cannot take the above two rules as gospel.


Too many other factors, such as compiled code versus interpreted code, the
overhead of loading the CLR inside SQL Server, access restriction
enforcement, library of helper functions, optimization logic that you may
build inside your code, and much more, may have an effect on performance.
The only definitive way to find out is to write the two objects, but the above
two rules can serve as a rough yardstick.

Here is a summary of some guidelines in choosing between CLR and T-SQL:

• Use declarative T-SQL SELECT, INSERT, UPDATE, and DELETE


statements whenever possible. Procedural and row-based processing
should be used only when the logic is not expressible using the
declarative language.
• If the procedure is simply a wrapper for declarative T-SQL commands it
should be written in T-SQL.
• If the procedure primarily involves forward-only, read-only row
navigation through a result set with some processing of each row, using
the CLR is likely more efficient.
• If the procedure involves both significant data access and computation,
consider separating the procedural code into a CLR portion that calls into
a T-SQL procedure to perform data access, or a T-SQL procedure that
calls into the CLR to perform computation. Another alternative is to use
a single T-SQL batch that includes a set of queries that are executed
once from managed code to reduce the number of round trips of
submitting T-SQL statements from managed.

CLR vs. XPs

In previous releases of SQL Server, extended stored procedures (XPs) were the only
alternative to T-SQL with which to write server-side code with logic that was difficult to
write in T-SQL. CLR integration provides a more robust alternative to XPs. In addition,
with CLR integration, many stored procedures can be better expressed as table-valued
functions, allowing them to be invoked and manipulated using the query language.

Some of the benefits of using CLR procedures over XPs are:

aa Granular control: SQL Server administrators have little control


over what XPs can or cannot do. Using the Code Access Security model, a
SQL Server administrator can assign one of three permission buckets—
SAFE, EXTERNAL_ACCESS, or UNSAFE—to exert varying degrees of control
over the operations that managed code is allowed to perform.

aa Reliability: Managed code, especially in the SAFE and


EXTERNAL_ACCESS permission sets, provides a more reliable programming
model than XPs do. Verifiable managed code ensures that all access to
objects is performed through strongly typed interfaces, reducing the
likelihood that the program accesses or corrupts memory buffers belonging
to SQL Server.

aa Data access: With XPs, an explicit connection back to the


database—a loop-back connection—must be made in order to access the
local SQL Server database. In addition, this loop-back connection must be
explicitly bound to the transaction context of the original session to ensure
that the XP participates in the transaction in which it is invoked. Managed
CLR code can access local data using a more natural and efficient
programming model that takes advantage of the current connection and
transaction context.

aa Additional Data Types: The managed APIs support new data


types (such as XML, (n)varchar(max), and varbinary(max)) introduced in
SQL Server 2005, while the ODS APIs have not been extended to support
these new types.

aa Scalability: The managed APIs that expose resources such as


memory, threads, and synchronization are implemented on top of the SQL
Server resource manager, allowing SQL Server to manage these resources
for CLR code. Conversely, SQL Server has no view or control over the
resource usage of an XP. If an XP consumes too much CPU time or memory,
there is no way to detect or control this from within SQL Server. With CLR
code, SQL Server can detect that a given thread has not yielded for a long
period of time and force the task to yield so that other work can be
scheduled. Consequently, using managed code provides for better scalability
and robustness.
Writing Managed Code

The easiest way to write managed code for SQL Server 2005 is to use Visual
Studio 2005. To write managed code for SQL Server, you must have at least the Team
Server edition of Visual Studio.
For each type of managed code that is supported, there are related attributes that are
used to decorate the code to help SQL Server know about specific behaviors about the
managed code. These attributes include SqlProcedure, SqlFunction,
SqlUserDefinedAggregate, SqlUserDefinedType and SqlMethod. Each of these
attributes is explained below.
Stored Procedures:
The most common — and useful — managed code in your own projects are probably
stored procedures. Creating managed stored procedures have the following three
requirements:
1. The containing class must be public.
2. The exposed method must be public.
3. The exposed method must be static.
4. That is all that is required. For example, to expose a simple stored
procedure:

public class SqlClr {


[SqlProcedure]
public static void MyProc() {
// Put your code here
}
}

Notice there is nothing especially different about this method from any other .NET
code. The SqlProcedure attribute marks this code as a stored procedure. The attribute
is not required, but is good form as documentation of what code is used where. It is
also used in Visual Studio to allow for the automatic deployment. The only parameter
that it accepts is the name parameter that will rename the automatically deployed
stored procedure:
public class SqlClr {
[SqlProcedure(Name="spMyProc")]
public static void MyProc() {
// Put your code here
}
}

You can specify in, out, in-out and return parameters as simple .NET parameters and
return types:

// Input Parameter
[SqlParameter]
public static void InputProcedure(int number) {
}
// Output Parameter
[SqlParameter]
public static void OutputProcedure(out int number) {
number = 5;
}

// In/Out Parameter
[SqlParameter]
public static void InOutProcedure(ref int number) {
number = 4;
}

// Return Parameter
[SqlParameter]
public static int ReturnProcedure() {
return 3;
}

Functions

Creating managed functions in SQL Server is just as simple as creating managed


stored procedures, except that they must return a value:

[SqlFunction]
public static int Subtraction(int x, int y) {
return x - y;
}

Some parameters that are useful to be in the SqlFunctionAttribute are as follows:


• DataAccess: Determines if the function needs to read data in the database.
If this is not specified, it is assumed that no data access is required.
• IsDeterministic: Used to declare that a function will always return the
same result, regardless of any other state in SQL Server.
• IsPrecise: Used to declare if the result that is being returned is
scientifically precise.
• Name: Used to annotate a function name to use, other than the managed
method name.

Managed Triggers

Much like T-SQL, SQL Server 2005 allows you to create triggers in managed code. You
must take special care to understand the performance implications in using managed
triggers, as their performance is likely to be lower than similarly written T-SQL
triggers.
Assuming you have taken the performance considerations into account, you would
write triggers by simply annotating them with the SqlTrigger attribute. The SqlTrigger
attribute requires two parameters:

• Event: The event to fire the trigger for. This syntax is identical to the T-SQL
syntax for the event name (e.g. FOR INSERT, INSTEAD OF DELETE, etc.). In
addition, you can specify event names for DDL triggers (a new SQL Server 2005
feature) by specifying a DDL event name (e.g. FOR CREATE TABLE, FOR DROP
USER, etc.).

• Target: The source of the event. Usually, this is a table or view name for DML
triggers or a database name for DDL triggers.

NOTE: Using the SqlTrigger attribute is broken in the Beta 2 version of Visual Studio.
You can write the triggers, but you must register them manually, and debugging is
impossible at the moment.

In writing a managed trigger, your code may look something like this:

[SqlTrigger(Event = "FOR INSERT",


Name = "Person.trgOnNewContact",
Target = "Person.Contact")]
public static void AddContact() {
SqlTriggerContext ctx = SqlContext.TriggerContext;

if (ctx.TriggerAction == TriggerAction.Insert) {
string msg = ";

// Get the data associated with Event


for (int x = 0; x < ctx.ColumnCount; ++x) {
msg += string.Format("Column {0} {1} been updated{2}",
x,
(ctx.IsUpdatedColumn(x) ? "has" : "has not"),
Environment.NewLine);
}

// Use the message to log it somewhere


}
}

Writing a trigger normally requires that you have some access to the data that was
affected (in this case, the row being inserted). To access that information, SQL Server
supports the SqlTriggerContext object that is used to get information about the trigger.
With the SqlTriggerContext object (which can be retrieved from the SqlContext object),
you can see what the trigger action was, and determine what columns were affected in
the statement that caused the trigger to fire.
Default Supported .Net Framework Libraries

These are the list of supported .NET Framework Libraries, which have been tested to
ensure that they meet reliability and security standards for interaction with SQL Server
2005 in any mode of assembly creation. Supported libraries do not need to be
explicitly registered on the server, but unsupported libraries must first be registered in
SQL Server database using CREATE ASSEMBLY before calling them in managed codes.

• CustomMarshalers
• Microsoft.VisualBasic
• Microsoft.VisualC
• Mscorlib
• System
• System.Configuration
• System.Data
• System.Data.OracleClient
• System.Data.SqlXml
• System.Deployment
• System.Security
• System.Transactions
• System.Web.Services
• System.Xml

Enabling CLR Integration

The common language runtime (CLR) integration feature is off by default in Microsoft
SQL Server, and must be enabled in order to use objects that are implemented using
CLR integration. To enable CLR integration, use the clr enabled option of the
sp_configure stored procedure as shown:

sp_configure 'clr enabled', 1


GO
RECONFIGURE
GO

You can disable CLR integration by setting the clr enabled option to 0. When you
disable CLR integration, SQL Server stops executing all CLR routines and unloads all
application domains.
USEFUL LINKS

http://msdn.microsoft.com/en-us/library/ms255336(VS.80).aspx

http://aspalliance.com/1081_CLR_Integration_in_SQL_Server_2005

http://www.developer.com/net/net/article.php/3548331

http://www.codeguru.com/cpp/data/mfc_database/sqlserver/article.php/c10453

http://www.devsource.com/c/a/Using-VS/Introducing-SQL-Server-2005s-CLR-
Integration/1/
QUESTIONS AND ANSWERS

You might also like