programming4us
           
 
 
SQL Server

Implementing SQL Server Objects Using Managed Code (part 2)

- Free product key for windows 10
- Free Product Key for Microsoft office 365
- Malwarebytes Premium 3.7.1 Serial Keys (LifeTime) 2019
11/14/2010 4:07:32 PM
Registering CLR Aggregates

Similarly to CLR functions, you must register your CLR aggregates with a SQL Server database. First register the assembly containing the aggregate using CREATE ASSEMBLY. Then, use the CREATE AGGREGATE statement with the EXTERNAL NAME parameter to register the aggregate. You must specify input parameter information and return type.

In Examples 8 and 9 we will register the SayHello function we have created earlier in this chapter. The SayHello function takes no parameters, and returns a value of type SqlString. The SqlString type is equivalent of the nvarchar SQL Server data type.

Example 8. Registering a Simple CLR Function
CREATE AGGREGATE ListWithSeparator
(@value nvarchar(200))
RETURNS nvarchar(max)
EXTERNAL NAME MyAwesomeFunctions.ListWithSeparator

Example 9. Calling a CLR Aggregate
USE AdventureWorks;
SELECT dbo.ListWithSeparator(Person.Contact.EmailAddress)
FROM Person.Contact
WHERE Person.Contact.FirstName like 'Val%'
--RESULTS (Truncated for brevity):
-----------------------------------------------------------------------------
valerie0@adventure-works.com; mailto:valerie1@adventure-works.com; valerie2@ad...
(1 row(s) affected)


Creating CLR Stored Procedures

Stored procedures are similar to functions, except they are not used in single-valued expressions. Stored procedures can return multiple result sets, return error messages to the caller, and execute Data Manipulation Language (DML) and Data Definition Language (DDL) statements. In summary, stored procedures are designed to store compiled logic that may manipulate data. Stored procedures can be implemented using Transact-SQL and the CLR.

Creating a CLR stored procedure is very similar to creating a CLR function. Create a class, create a static/shared method, and mark it with the SqlProcedure attribute. The difference is that a CLR stored procedure must be either a void (in other words, return nothing) or return an integer value that represents the success or failure code.

You can also return tabular results and messages by using the SqlContext.Pipe object. This object represents the output to the SQL Server caller, and has the methods of Send and Execute. Use Send to send text, and Execute to send a query that will be executed by the SQL Server caller.

CLR stored procedures are registered with the database using the CREATE PROCEDURE statement with the EXTERNAL NAME clause. As with function and aggregate registration, you must specify the parameter definitions and return value, if any.

Examples 10 through 12 demonstrate how to create, register, and call a CLR stored procedure. In this stored procedure, we will write all scrap reasons from the Production.ScrapReason table to a text file. The stored procedure will accept the path to the text file as a parameter. We will call this stored procedure—ExportComplaints.

Example 10. Implementing the ExportComplaints Stored Procedure — C#
using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.IO;

public class StoredProcedures
{
[Microsoft.SqlServer.Server.SqlProcedure()]
public static void ExportComplaints(SqlString PathToLetter)
{
using (StreamWriter writer = new StreamWriter(PathToLetter.
ToString())){
using (SqlConnection connection = new SqlConnection("context
connection=true"))
{
connection.Open();
SqlCommand command = new SqlCommand("Select Name from Production.
ScrapReason", connection);
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
writer.WriteLine(reader[0].ToString());
}
}
}
}
SqlContext.Pipe.Send("Message from ExportComplaints CLR Stored Proc: Letter
created successfully!");
}
}


Example 11. Implementing the Export Complaints Stored Procedure—Visual Basic .NET
Imports System
Imports System.Data
Imports System.Data.SqlClient
Imports System.Data.SqlTypes
Imports Microsoft.SqlServer.Server
Imports System.IO
Public Class StoredProcedures
<Microsoft.SqlServer.Server.SqlProcedure(DataAccess:=DataAccessKind.Read)> _
Public Shared Sub ExportComplaints(ByVal PathToLetter As SqlString)
Using writer As StreamWriter = New StreamWriter(PathToLetter.
ToString())
Using connection As SqlConnection = New SqlConnection("context
connection=true")
connection.Open()
Dim command As SqlCommand = New SqlCommand("Select Name from
Production.ScrapReason", connection)
Using reader As SqlDataReader = command.ExecuteReader()
Do While reader.Read()
writer.WriteLine(reader(0).ToString())
Loop
End Using
End Using
End Using
SqlContext.Pipe.Send("Message from ExportComplaints CLR Stored Proc:
Letter created successfully!")
End Sub
End Class


Example 12. Registering the Export Complaints Stored Procedure with SQL Server
CREATE ASSEMBLY MyAwesomeFunctions
AUTHORIZATION [dbo]
FROM 'C:\Documents and Settings\Valentine\My Documents\MyAwesomeFunctions\bin\
MyAwesomeFunctions.dll'
WITH PERMISSION_SET = EXTERNAL_ACCESS;
Go
CREATE PROCEDURE dbo.ExportComplaints(@PathToLetter as nvarchar(1000))
AS EXTERNAL NAME MyAwesomeFunctions.StoredProcedures.ExportComplaints;
Go


Note that this time we had to register the assembly with the EXTERNAL_ACCESS permission set; otherwise, we would not be able to write to the text file.

Example 13 shows the syntax for executing the ExportComplaints stored procedure.

Example 13. Executing the ExportComplaints Stored Procedure
EXECUTE dbo.ExportComplaints 'C:\Documents and Settings\Valentine\
My Documents\Complaint.txt'

After executing the stored procedure, a text file Complaint.txt will appear in My Documents. If you have time, try performing this example yourself—you will feel more comfortable with CLR integration and .NET Framework development as a whole.

Tip

You should understand what happens when an assembly that is registered with the SAFE permission set attempts to access external resources. The assembly code will receive an error. If we used the SAFE permission set with the preceding ExportComplaints example, we would receive an error that looks like this:

A .NET Framework error occurred during execution of user-defined routine
or aggregate "ExportComplaints": System.Security.SecurityException:
Request for the permission of type 'System.Security.Permissions.
FileIOPermission, mscorlib, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089' failed.


Creating CLR Triggers

A trigger is a statement that runs every time table data or the structure of a database is modified. Data Manipulation Language (DML) triggers run when someone runs an INSERT, UPDATE, or DELETE statement against a particular table. These triggers can be used to perform complex validation and roll back the operation if necessary. Data Definition Language (DDL) triggers run when someone modifies the structure of a database, usually by executing CREATE, ALTER, and DROP statements. These triggers can be used to audit modifications to the structure of the database.

CLR triggers have the same capabilities as Transact-SQL triggers. Specifically, CLR triggers can perform the following tasks:

  • Determine which columns in a table have been updated

  • Query the INSERTED and DELETED tables to find out what data is about to be inserted, deleted, or modified

  • Determine which database objects were affected by a DDL statement

Most of these capabilities are accessed by using the SqlContext. TriggerContext object. Using this object is outside the scope of this exam. However, when you need to create a CLR trigger in real life, see SQL Server Books Online.

CLR triggers need to be registered with the specific table, just like regular Transact-SQL triggers. To do this, first register the assembly containing the trigger using CREATE ASSEMBLY, as explained earlier in this chapter. Then, use the CREATE TRIGGER statement to bind the trigger to the specific table, as shown in Example 14.

Example 14. Binding a CLR Trigger
CREATE TRIGGER dbo.ValidateCustomerEMailAddress
ON Customers
FOR INSERT, UPDATE
AS
EXTERNAL NAME MyAwesomeFunctions. Triggers.ValidateCustomerEMailAddress


Creating User-Defined Data Types Using the CLR

Ever since SQL Server 2005, we have had the ability to create custom data types and register them with SQL Server. These are known as User-Defined Types, or UDTs. UDTs are often used to represent complex data, such as spatial coordinates or currencies. Note that you should not use UDTs to represent logical structures like customers or orders. Complex structures are better implemented using traditional columns, rows, and relationships. Don’t use UDTs just because you have the ability. Always consider traditional ways to store your data as this will deliver better performance. UDTs are created using managed code and can be used in place of any SQL Server data type—for example, to define columns in a table, to declare variables, and so on.

Creating a UDT in managed code is similar to creating a user-defined aggregate. Specifically, you create a class or a structure and mark it with the SqlUserDefinedType custom attribute. You must then implement a user-defined type contract, again, similar to creating a user-defined aggregate. Defining a CLR UDT is outside the scope of this exam. However, when you need to create a CLR UDT in real life, see SQL Server Books Online.

CLR user-defined data types need to be registered before they can be used. As with all CLR objects, you should first register the assembly with SQL Server using the CREATE ASSEMBLY statement. You can then use the CREATE TYPE statement to register the type with your database. The type is registered with a single database, not with the entire instance of SQL Server. This is another reason why you should consider alternatives to CLR UDTs—cross-database and cross-server operations may be difficult or even impossible. Similar to declaring a trigger, you should use the EXTERNAL NAME keywords to bind your UDT to the CLR object, as shown in Example 4.16.

Example 15. Registering a CLR User-Defined Data Type
CREATE TYPE dbo.RGBColor
EXTERNAL NAME MyAwesomeFunctions.[RGBColor];


Exercise 1. Start to Finish: Implementing a CLR Function in SQL Server

In this exercise, we will create a simple CLR function to read data from the Windows registry. The function will accept a registry key name and a value name. The function will return the data held in the registry value. We will then register the function and call it from the SQL Server Management Studio.

Before you begin, you must have the following software installed on your computer:

  • SQL Server 2008 (a free trial is available for download).

  • Visual Studio 2005 or Visual Studio 2008.

  • If you don’t have Visual Studio, download and install the .NET Framework 2.0 SDK.

  • AdventureWorks sample database.

First we will create the CLR function. To do this, use the following procedure:

  1. If you have Visual Studio installed, open Visual Studio. To do this click Start | All Programs | Microsoft Visual Studio 2005 | Microsoft Visual Studio 2005.

  2. In Visual Studio, on the menu bar, click File | New | Project.

  3. In the New Project dialog, in the left pane, expand either C# or Visual Basic (choose which language you wish to use). Under your language of choice click Database.

  4. In the Templates pane on the right, click SQL Server Project.

  5. In the Name box type MySQLLibrary, and choose to save the project to an easy-to-remember location. In this example we will use C:\Exercises. Click OK.

  6. In the Add Database Reference dialog, click Cancel.

  7. In the Solution Explorer window on the left-hand side, right-click MySQLLibrary, then click Add | User-Defined Function.

  8. In the Name box, type ReadRegistryData, then click OK.

The large code window in the middle of the screen shows a template for a user-defined function. You are ready to write the code for the function. Copy the code shown in Examples 16 and 17 into your template, according to the language you have chosen. If you do not use Visual Studio, simply open Notepad and copy the code into the blank text file.

Example 16. Exercise Code—C#
using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using Microsoft.Win32;
public partial class UserDefinedFunctions
{
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlString ReadRegistryData(SqlString Key, SqlString Value)
{
string hive = Key.ToString().ToUpper();
hive = hive.Substring(0, hive.IndexOf('\\'));
string subKey = Key.ToString().Remove(0, hive.Length + 1);
if (hive == "HKEY_LOCAL_MACHINE")
{
RegistryKey registryKey = Registry.LocalMachine.
OpenSubKey(subKey, false);
return (string)registryKey.GetValue(Value.ToString());
}
else if (hive == "HKEY_CURRENT_USER")
{
RegistryKey registryKey = Registry.CurrentUser.OpenSubKey(subKey,
false);
return (string)registryKey.GetValue(Value.ToString());
}
return "Reading this key is not supported.";
}
}


Example 17. Exercise Code—Visual Basic
Imports System
Imports System.Data
Imports System.Data.SqlClient
Imports System.Data.SqlTypes
Imports Microsoft.SqlServer.Server
Imports Microsoft.Win32

Partial Public Class UserDefinedFunctions
<Microsoft.SqlServer.Server.SqlFunction()> _
Public Shared Function ReadRegistryData(ByVal Key As SqlString, _
ByVal Value As SqlString) AsSqlString
Dim hive As String = Key.ToString().ToUpper()
hive = hive.Substring(0, hive.IndexOf("\"))
Dim subKey As String = Key.ToString().Remove(0, hive.Length + 1)
If hive = "HKEY_LOCAL_MACHINE" Then
Dim keyToRead As RegistryKey = Registry.LocalMachine.
OpenSubKey(subKey, False)
Return CType(keyToRead.GetValue(Value.ToString()), String)
ElseIf hive = "HKEY_CURRENT_USER" Then
Dim keyToRead As RegistryKey = Registry.CurrentUser.
OpenSubKey(subKey, False)
Return CType(keyToRead.GetValue(Value.ToString()), String)
End If
Return "Reading this key is not supported."
End Function
End Class


If you are not using Visual Studio and have entered the code into Notepad, save the file to the C:\Exercises\MySQLLibrary\ folder. Name the file ReadRegistryData.vb if you are using Visual Basic, or ReadRegistryData.cs if you are using C#. You can choose any other folder, but be consistent throughout the exercise.

Now we are ready to compile our code into an assembly. To do this, use the following procedure:

  1. If you are using Visual Studio, on the menu bar click Build | Build Solution. The assembly called MySQLLibrary.dll will be output to C:\Exercises\MySQLLibrary\MySQLLibrary\bin\Debug\MySQLLibrary.dll.

  2. If you are not using Visual Studio, open the command prompt and navigate to the installation directory for .NET Framework (usually C:\WINDOWS\Microsoft.NET\Framework\v2.0.xxxxx). Execute the following command:

Compile—C#

csc /target:library /out:C:\Exercises\MySQLLibrary\MySQLLibrary.dll /debug
C:\Exercises\MySQLLibrary\ReadRegistryData.cs

Compile—Visual Basic .NET

vbc /target:library /out:C:\Exercises\MySQLLibrary\MySQLLibrary.dll /debug
C:\Exercises\MySQLLibrary\ReadRegistryData.vb

Now that our code has been compiled to an assembly, we can register it with SQL Server. Open SQL Management Studio, and execute the query shown in Example 18 against the AdventureWorks database.

Example 18. Creating the Assembly and Registering the ReadRegistryData Function in SQL Server
-- COMMENT: ENABLE CLR ON THE SERVER
sp_configure 'show advanced options', 1;
GO
RECONFIGURE;
GO
sp_configure 'clr enabled', 1;
GO
RECONFIGURE;
GO
-- COMMENT: SET THE TRUSTWORTHY PROPERTY
ALTER DATABASE AdventureWorks
SET TRUSTWORTHY ON
GO
-- COMMENT: REGISTER THE ASSEMBLY
CREATE ASSEMBLY MySQLLibrary
AUTHORIZATION [dbo]
FROM 'C:\Exercises\MySQLLibrary\MySQLLibrary.dll'
WITH PERMISSION_SET = EXTERNAL_ACCESS;
GO
-- COMMENT: REGISTER THE FUNCTION
CREATE FUNCTION dbo.ReadRegistryData(@Key as nvarchar(1000), @Value as
nvarchar(200))
RETURNS nvarchar(max)
AS EXTERNAL NAME MySQLLibrary.UserDefinedFunctions.ReadRegistryData;
go


Finally, we are ready to test the function execution. Run the following statements and observe the results:

SELECT dbo.ReadRegistryData(
'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion',
'ProgramFilesDir')
SELECT dbo.ReadRegistryData(
'HKEY_CURRENT_USER\Control Panel\Desktop', 'Wallpaper')
SELECT dbo.ReadRegistryData(
'HKEY_CURRENT_USER\Control Panel\Current', 'Color Schemes')
Other -----------------
- Encryption Catalog Views
- Built-In Cryptographic Functions
- SQL server 2008 : Managing Security - Permissions
- SQL server 2008 : Managing Security - Schemas
- SQL server 2008 : Managing Security - Users
- SQL server 2008 : Managing Security - Roles
- SQL Server 2008 : Managing Remote Servers
- Linked Servers
- Adding, Dropping, and Configuring Linked Servers
- Mapping Local Logins to Logins on Linked Servers
- Obtaining General Information About Linked Servers
- Executing a Stored Procedure via a Linked Server
- Setting Up Linked Servers Using SQL Server Management Studio
- Encryption basics for SQL Server : Cryptographic Keys
- Encryption basics for SQL Server : Key Maintenance
- Encryption basics for SQL Server : Key Algorithms
- SQL Server 2005 : Performing Database Backups
- SQL Server 2005 : Restoring Data from a Backup
- SQL Server 2005 : Using Database Snapshots
- SQL Server 2005 : Automating Maintenance with Job Scheduling
 
 
 
Top 10
 
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 2) - Wireframes,Legends
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 1) - Swimlanes
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Formatting and sizing lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Adding shapes to lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Sizing containers
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 3) - The Other Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 2) - The Data Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 1) - The Format Properties of a Control
- Microsoft Access 2010 : Form Properties and Why Should You Use Them - Working with the Properties Window
- Microsoft Visio 2013 : Using the Organization Chart Wizard with new data
- First look: Apple Watch

- 3 Tips for Maintaining Your Cell Phone Battery (part 1)

- 3 Tips for Maintaining Your Cell Phone Battery (part 2)
programming4us programming4us