Before wading into a hip-deep discussion of CLR stored procedures, we need to take a short side trip to acquaint you with ADO.NET and how it's used (or abused) in a CLR executable. Yes, there are times when your CLR Executable code needs to access data from the local SQL Server or perhaps from an external source like another SQL Server instance or data in another format, in another database, or in Cleveland. The engineers at Microsoft experimented with this interface for quite some time during the beta cycle, and we all saw a number of implementations come and go. You'll see evidence of these tried-and-abandoned approaches in a number of magazine articles and stale Google content. Using the Context ConnectionTo simplify your job, when it comes time to connect to a data source, you have two fundamental choices, as illustrated in Figure 13.31:
Figure 13.31. Connecting to SQL Server via a "context" or "normal" connection.A context connection is created when you specify "context connection=true" in the ConnectionStringyou won't be permitted to add any other keywords. Just a few caveats when using a context connection:
There are also a couple of restrictions on using a "normal" connection from within a CLR stored procedureno asynchronous operations, and the SqlDependency object is not supported. You'll also want to stay away from Integrated Security (SSPI) authentication, as the "identity" used for the connection will be the identity of the SQL Server servicenot yours. I'll show some examples of using a context connection later in this chapterseveral of the CLR executables use it. Sure, you can use a "normal" connection to connect to other data sourceseven Oracle and JET. Yes, these connections will limit the performance of your SQL Server, as it has to wait for the source database engine to be instantiated, accessed, and queried. When you access an external database, you'll have to mark your CLR executable Permission Level to "EXTERNAL_ACCESS". The implications of this setting are discussed later in this chapterit's set via the Project Properties, shown in Figure 13.32. A context connection can run with the default setting"Safe". Figure 13.32. Setting the Permission Level with the Project Settings dialog.Managing TransactionsCLR Executables have been integrated with the 2.0 Framework's System.Transactions. You'll have to manually add a reference to System.Transactions.DLL in your CLR executable References list to get access to this functionality in your code. To get a better idea of how the CLR works with SQL Server to implement transaction support, I suggest reading Pablo Castro's article[10] "Managed Data Access Inside SQL Server with ADO.NET and SQLCLR," posted on MSDN. Generally, it's recommended that you create your own transaction scope within the context of your CLR executable. The CLR and SQL Server work together to coordinate your transaction scope with the transaction context used to execute the executable.
Querying DataOnce the ADO.NET Connection is open (yes, you still have to open and close the Connectioneven a context connection), you use it as you would any normal connection to SQL Server. You still use the SqlClient namespace classes to create SqlCommand instances, populate their Parameters collection, and execute them. You can create SqlDataAdapter instances or simply create a SqlDataReader to return single or multiple resultsets. The next section has plenty of examples of executing SqlCommand objects and working with the resultsets. Returning Data and MessagesUnlike a "normal" Windows application, a CLR stored procedure or other executable often has to return special structures like Tables (in a Table-value function), one or more resultsets (that might contain one or more rowsets), messages, and exceptions. The following example illustrates how to use the SqlContext.Pipe to create these resultsets that are sent directly back to SQL Server. All data returned is sent to the local SQL Server instance hosting the CLR executable through this context pipe.
When implementing a CLR User-Defined type (UDT) or aggregate, there are special interfaces used to expose the data you build to SQL Server. These are also explained in great detail later in this chapter. |