sql server 2005: the clr integration what developers and dbas need to know

37
SQL Server 2005: The CLR Integration What Developers and DBAs need to know

Upload: britton-wiggins

Post on 02-Jan-2016

228 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: SQL Server 2005: The CLR Integration What Developers and DBAs need to know

SQL Server 2005: The CLR IntegrationSQL Server 2005:

The CLR Integration

What Developers and DBAs need to know

What Developers and DBAs need to know

Page 2: SQL Server 2005: The CLR Integration What Developers and DBAs need to know

Who I AmWho I Am

Shawn Wildermuth ([email protected]) Senior Consultant/Architect with Magenic

Technologies (http://www.magenic.com) C# MVP INETA Speaker Book Author – “Pragmatic ADO.NET”;

Editor of http://ONDotnet.com This Presentation can be found at:– http://adoguy.com/presentations

Shawn Wildermuth ([email protected]) Senior Consultant/Architect with Magenic

Technologies (http://www.magenic.com) C# MVP INETA Speaker Book Author – “Pragmatic ADO.NET”;

Editor of http://ONDotnet.com This Presentation can be found at:– http://adoguy.com/presentations

Page 3: SQL Server 2005: The CLR Integration What Developers and DBAs need to know

AgendaAgenda

CLR Hosting Environment Assembly Management Managed Stored Procedures and

Functions InProc Managed Provider Database connections? Table Valued Functions Managed Triggers Managed Datatypes Custom Aggregates

CLR Hosting Environment Assembly Management Managed Stored Procedures and

Functions InProc Managed Provider Database connections? Table Valued Functions Managed Triggers Managed Datatypes Custom Aggregates

Page 4: SQL Server 2005: The CLR Integration What Developers and DBAs need to know

CLR Hosting EnvironmentCLR Hosting Environment

In .NET 1.1– Designed for IIS– Processes could be killed– Freely creating memory and threads

In .NET 2.0– Designed for SQL Server 2005– Processes cannot be killed– Host can refuse memory or thread

creation– Security critical

In .NET 1.1– Designed for IIS– Processes could be killed– Freely creating memory and threads

In .NET 2.0– Designed for SQL Server 2005– Processes cannot be killed– Host can refuse memory or thread

creation– Security critical

Page 5: SQL Server 2005: The CLR Integration What Developers and DBAs need to know

Assembly ManagementAssembly Management

DML Command to add an Assembly– Can be from a file

But has to have permissions (NT Security)

– Alternatively, can be a bitstream

– No In-Engine Compilation

DML Command to add an Assembly– Can be from a file

But has to have permissions (NT Security)

– Alternatively, can be a bitstream

– No In-Engine Compilation

CREATE ASSEMBLY ExampleYukonFROM 'd:\ExampleYukon.dll'

CREATE ASSEMBLY ExampleYukonFROM 0x4D5A90000300000004000000FFFF0000B8000000000000...

Page 6: SQL Server 2005: The CLR Integration What Developers and DBAs need to know

Assembly Management (2)Assembly Management (2)

Code Access Security (CAS) for Assemblies– Three CAS Buckets

SAFE– Access to the CLR only– No access to external resources, thread management,

unsafe code or interop

EXTERNAL_ACCESS– Access to external systems through the .NET Framework– E.g. EventLog, FileSystem and Network– No access unsafe or interop

UNSAFE– No restrictions; similar to extended stored procedures

Code Access Security (CAS) for Assemblies– Three CAS Buckets

SAFE– Access to the CLR only– No access to external resources, thread management,

unsafe code or interop

EXTERNAL_ACCESS– Access to external systems through the .NET Framework– E.g. EventLog, FileSystem and Network– No access unsafe or interop

UNSAFE– No restrictions; similar to extended stored procedures

Page 7: SQL Server 2005: The CLR Integration What Developers and DBAs need to know

Assembly Management (3)Assembly Management (3)

Use DML Assembly Commands for CAS

Use DML Assembly Commands for CASCREATE ASSEMBLY ExampleYukonFROM 'd:\ExampleYukon.dll'WITH PERMISSION_SET=SAFE

CREATE ASSEMBLY ExampleYukonFROM 'd:\ExampleYukon.dll'WITH PERMISSION_SET=EXTERNAL_ACCESS

CREATE ASSEMBLY ExampleYukonFROM 'd:\ExampleYukon.dll'WITH PERMISSION_SET=UNSAFE

Page 8: SQL Server 2005: The CLR Integration What Developers and DBAs need to know

Managed CodeManaged Code

Code isn’t available by default– Must register functions, stored procs, etc.– Code is not available by default– Registration takes certain permissions to

allow

Code isn’t available by default– Must register functions, stored procs, etc.– Code is not available by default– Registration takes certain permissions to

allow

Page 9: SQL Server 2005: The CLR Integration What Developers and DBAs need to know

Managed Code (2)Managed Code (2)

Attributes– Hints to VS about how to Deploy

[SqlProcedure] [SqlFunction] [SqlUserDefinedType] [SqlUserDefinedAggregate] Etc.

– Also used at runtime for behaviors of objects E.g. SqlMethod(IsMutable=true)

Attributes– Hints to VS about how to Deploy

[SqlProcedure] [SqlFunction] [SqlUserDefinedType] [SqlUserDefinedAggregate] Etc.

– Also used at runtime for behaviors of objects E.g. SqlMethod(IsMutable=true)

Page 10: SQL Server 2005: The CLR Integration What Developers and DBAs need to know

Managed Stored ProceduresManaged Stored Procedures

To expose a Stored Procedure:– The containing class must be public– The exposed method must be public– The exposed method must be static

To expose a Stored Procedure:– The containing class must be public– The exposed method must be public– The exposed method must be static

public class SqlClr { public static void MyProc() { // Put your code here }}

Page 11: SQL Server 2005: The CLR Integration What Developers and DBAs need to know

Managed Stored Procedures (2)Managed Stored Procedures (2)

Managed Stored Procedure DML– Uses the CREATE PROCEDURE call– Adds AS EXTERNAL NAME to specify CLR

SP

Managed Stored Procedure DML– Uses the CREATE PROCEDURE call– Adds AS EXTERNAL NAME to specify CLR

SPCREATE PROCEDURE <Procedure Name>AS EXTERNAL NAME <Assembly Identifier>.<Type Name>.<Method Name>

CREATE PROCEDURE MyProcAS EXTERNAL NAME ExampleYukon.SqlClr.MyProc

Page 12: SQL Server 2005: The CLR Integration What Developers and DBAs need to know

Managed Stored Procedures (3)Managed Stored Procedures (3)

Parameters – Must match DML Command:

Parameters – Must match DML Command:

// Input Parameterpublic static void InputProcedure(int number) {}

// Output Parameterpublic static void OutputProcedure(out int number) { number = 42;}

// In/Out Parameterpublic static void InOutProcedure(ref int number) { number = 42;}

// Return Parameterpublic static int ReturnProcedure() { return 42;}

Page 13: SQL Server 2005: The CLR Integration What Developers and DBAs need to know

Managed Stored Procedures (4)Managed Stored Procedures (4)

Parameters (continued)– DML must match the parameters:

Parameters (continued)– DML must match the parameters:

CREATE PROCEDURE InputProcedure @number intAS EXTERNAL NAME ExampleYukon.SqlClr.InputProcedure

CREATE PROCEDURE OutputProcedure @number int OUTPUTAS EXTERNAL NAME ExampleYukon.SqlClr.OutputProcedure

CREATE PROCEDURE InOutProcedure @number int OUTPUTAS EXTERNAL NAME ExampleYukon.SqlClr.InOutProcedure

-- NOTE: You don’t specify ReturnParametersCREATE PROCEDURE ReturnProcedureAS EXTERNAL NAME ExampleYukon.SqlClr.ReturnProcedure

Page 14: SQL Server 2005: The CLR Integration What Developers and DBAs need to know

Managed FunctionsManaged Functions

Similar to Stored Procedures– Uses similar DML Syntax:

Similar to Stored Procedures– Uses similar DML Syntax:

CREATE FUNCTION <Function Name>(<Parameter List>) RETURNS <Return Type>AS EXTERNAL NAME <Assembly Identifier>.<Type Name>.<Method Name>

CREATE FUNCTION Addition( @x int, @y int)RETURNS intAS EXTERNAL NAME ExampleYukon.SqlClr.Addition

Page 15: SQL Server 2005: The CLR Integration What Developers and DBAs need to know

Managed Functions (2)Managed Functions (2)

Code is similar to Stored Procedures

– [SqlFunction] Parameters Helps SQL Server know what the function

does– IsDeterministic– IsPrecise– DataAccess– SystemDataAccess

Code is similar to Stored Procedures

– [SqlFunction] Parameters Helps SQL Server know what the function

does– IsDeterministic– IsPrecise– DataAccess– SystemDataAccess

[SqlFunction]public static int Addition(int x, int y) { return x + y;}

Page 16: SQL Server 2005: The CLR Integration What Developers and DBAs need to know

Managed TriggersManaged Triggers

Also like Stored Procedures– DML Triggers

– Also, DDL Triggers

Also like Stored Procedures– DML Triggers

– Also, DDL Triggers

CREATE TRIGGER <TriggerName>ON <Table or View> <FOR|INSTEAD OF> <INSERT|UPDATE|DELETE>AS EXTERNAL NAME <Assembly Identifier>.<Type Name>.<Method Name>

CREATE TRIGGER AddContactON author FOR INSERTAS EXTERNAL NAME ExampleYukon.SqlClr.AddContact

CREATE TRIGGER <TriggerName>ON <ALL_SERVER or DATABASE> <FOR or AFTER> <EventName>AS EXTERNAL NAME <Assembly Identifier>.<Type Name>.<Method Name>

CREATE TRIGGER AddUserON DATABASE FOR CreateUserAS EXTERNAL NAME ExampleYukon.SqlClr.AddUser

Page 17: SQL Server 2005: The CLR Integration What Developers and DBAs need to know

Managed Triggers (2)Managed Triggers (2)

TriggerContext for Trigger Info– ColumnsUpdates to see what columns

changed

TriggerContext for Trigger Info– ColumnsUpdates to see what columns

changedpublic static void AddAuthor() { 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.IsColumnsUpdated(x) ? "has" : "has not"), Environment.NewLine) } // Use the message to log it somewhere }}

Page 18: SQL Server 2005: The CLR Integration What Developers and DBAs need to know

Custom AggregatesCustom Aggregates

Write your own MIN, MAX, COUNT– Define a CLR Type that does the

aggregation Use DML command to register

Write your own MIN, MAX, COUNT– Define a CLR Type that does the

aggregation Use DML command to registerCREATE AGGREGATE <Aggregate Name>

( @param <SQL Type> )RETURNS <SQL Type>EXTERNAL NAME <assembly>.<CLR Type>

CREATE AGGREGATE CustomAverage( @value float )RETURNS floatEXTERNAL NAME ExampleYukon.CustomAverage

Page 19: SQL Server 2005: The CLR Integration What Developers and DBAs need to know

Custom Aggregates (2)Custom Aggregates (2)

CLR Class– Class is called during the aggregation– Not just passed a set of values, but one at a time– Must be serializable (for intermediate results)– Must implement known methods

Init– Called at the start of the aggregation of fields

Accumulate– Called once for each row being aggregated. It is passed

the value from the column being aggregated. Merge

– Called to merge a temporary result into the aggregate Terminate

– Called at the end of the aggregation process to retrieve the result of the aggregation.

CLR Class– Class is called during the aggregation– Not just passed a set of values, but one at a time– Must be serializable (for intermediate results)– Must implement known methods

Init– Called at the start of the aggregation of fields

Accumulate– Called once for each row being aggregated. It is passed

the value from the column being aggregated. Merge

– Called to merge a temporary result into the aggregate Terminate

– Called at the end of the aggregation process to retrieve the result of the aggregation.

Page 20: SQL Server 2005: The CLR Integration What Developers and DBAs need to know

Custom Aggregates (3)Custom Aggregates (3)

Custom Average Example: Custom Average Example:[Serializable][SqlUserDefinedAggregate(Format.UserDefined, MaxByteSize = 8000)]public class CustomAverage : IBinarySerialize {

SqlDouble _total = 0; ulong _totalCount = 0;

public void Init() { } public void Accumulate(SqlDouble Value) { ++_totalCount; if (_total.IsNull) _total = 0; _total += Value; } public void Merge(StdDev grp) {/*...*/ } public SqlDouble Terminate() { return _total/_totalCount; }

void IBinarySerialize.Read(BinaryReader r) { /*...*/ } void IBinarySerialize.Write(BinaryWriter w) { /*...*/ }}

Page 21: SQL Server 2005: The CLR Integration What Developers and DBAs need to know

InProc Managed ProviderInProc Managed Provider

Inside the Server, a new Provider– Very similar to SqlClient Provider– Follows Managed Provider Model– Supports

IDbConnection IDbCommand IDbDataReader Etc.

Inside the Server, a new Provider– Very similar to SqlClient Provider– Follows Managed Provider Model– Supports

IDbConnection IDbCommand IDbDataReader Etc.

Page 22: SQL Server 2005: The CLR Integration What Developers and DBAs need to know

InProc Managed Provider (2)InProc Managed Provider (2)

Dude, where’s my Connection?– In Out-of-proc ADO.NET:

Dude, where’s my Connection?– In Out-of-proc ADO.NET:

using (SqlConnection conn = new SqlConnection("..."))using (SqlCommand cmd = conn.CreateCommand()) { try { cmd.CommandText = "..."; conn.Open();

using (SqlDataReader rdr = cmd.ExecuteReader()) { while (rdr.Read()) { Console.WriteLine(rdr.GetString(0)); } } // Reader is disposed } finally { conn.Close() }} // using statements ensure Disposed is called

Page 23: SQL Server 2005: The CLR Integration What Developers and DBAs need to know

InProc Managed Provider (3)InProc Managed Provider (3)

InProc you can assume the connection InProc you can assume the connectionusing (SqlCommand cmd = new SqlCommand()) { cmd.CommandText = "...";

SqlContext.Pipe.ExecuteAndSend(cmd);}

Page 24: SQL Server 2005: The CLR Integration What Developers and DBAs need to know

InProc Managed Provider (4)InProc Managed Provider (4)

If you need a connection– Can create additional connections– Use “context connection=true” for

current

If you need a connection– Can create additional connections– Use “context connection=true” for

currentusing (SqlConnection conn = new SqlConnection("context connection=true"))using (SqlCommand cmd = conn.CreateCommand()) { cmd.CommandText = @"SELECT * FROM Sales.SalesOrderHeader";

try { conn.Open();

SqlDataReader rdr = cmd.ExecuteReader(); while (rdr.Read()) total += Convert.ToDecimal(rdr["TotalDue"]);

} finally { conn.Close(); }}

Page 25: SQL Server 2005: The CLR Integration What Developers and DBAs need to know

InProc Managed Provider (5)InProc Managed Provider (5)

SqlContext– Used to get active server objects

Pipe WindowsIdentity Etc.

SqlContext– Used to get active server objects

Pipe WindowsIdentity Etc.

Page 26: SQL Server 2005: The CLR Integration What Developers and DBAs need to know

InProc Managed Provider (6)InProc Managed Provider (6)

Returning Data– Use a Pipe to send data back to the client

Use the SqlContext’s Pipe Use Execute() to Fire a Command into the

pipe Use Send() to send results back from a

Reader

Returning Data– Use a Pipe to send data back to the client

Use the SqlContext’s Pipe Use Execute() to Fire a Command into the

pipe Use Send() to send results back from a

ReaderSqlCommand cmd = new SqlCommand();cmd.CommandText = "SELECT * FROM Customer";

// Send the results to the clientSqlPipe pip = SqlContext.Pipe.Execute(cmd);

SqlCommand cmd = new SqlCommand();cmd.CommandText = "SELECT * FROM Customer";SqlDataReader rdr = cmd.ExecuteReader();

// Send the results to the clientSqlContext.Pipe.Send(rdr);

Page 27: SQL Server 2005: The CLR Integration What Developers and DBAs need to know

InProc Managed Provider (7)InProc Managed Provider (7)

Returning Custom Results– Use SqlDataRecord

Must create SqlMetaData to describe the result

Returning Custom Results– Use SqlDataRecord

Must create SqlMetaData to describe the result

SqlMetaData[] columns = new SqlMetaData[3];columns[0] = new SqlMetaData("ID", SqlDbType.Int);columns[1] = new SqlMetaData("Name", SqlDbType.NVarChar, 50);columns[2] = new SqlMetaData("theDate", SqlDbType.DateTime);

SqlDataRecord record = new SqlDataRecord(columns);

record.SetInt32(0, 1);record.SetString(1, "Bob Higgins");record.SetDateTime(2, DateTime.Now);

SqlContext.Pipe.Send(record);

Page 28: SQL Server 2005: The CLR Integration What Developers and DBAs need to know

InProc Managed Provider (8)InProc Managed Provider (8)

Return Custom Results (Multiple Rows)– Use SendResultsStart to begin– Must send all rows with SendResultsRow– Must end with SendResultsEnd

Return Custom Results (Multiple Rows)– Use SendResultsStart to begin– Must send all rows with SendResultsRow– Must end with SendResultsEnd// Start it

SqlContext.Pipe.SendResultsStart(record); // Only primes pumpSqlContext.Pipe.SendResultsRow(record);

SqlDataRecord anotherRecord = new SqlDataRecord(columns);anotherRecord.SetInt32(0, 2);anotherRecord.SetString(1, "Mary Roberts");anotherRecord.SetDateTime(2, DateTime.Now.AddDays(1));SqlContext.Pipe.SendResultsRow(anotherRecord);

// Finish ResultSet SqlContext.Pipe.SendResultsEnd();

Page 29: SQL Server 2005: The CLR Integration What Developers and DBAs need to know

InProc Managed Provider (9)InProc Managed Provider (9)

SQL Server Datatypes– Use System.Data.SqlTypes namespace– Each SqlXXXXX type is INullable– Allows Stored Procs that allow DB Nulls

SQL Server Datatypes– Use System.Data.SqlTypes namespace– Each SqlXXXXX type is INullable– Allows Stored Procs that allow DB Nullspublic static void GetContact(SqlString email) { SqlCommand cmd = new SqlCommand(); cmd.CommandText = @"SELECT FirstName, LastName FROM Person.COntact WHERE EmailAddress = @email";

cmd.Parameters.Add("@email", SqlDbType.NVarChar, 50); cmd.Parameters["@email"].Value = email;

SqlContext.Pipe.ExecuteAndSend(cmd);}

Page 30: SQL Server 2005: The CLR Integration What Developers and DBAs need to know

InProc Managed Provider (7)InProc Managed Provider (7)

Updating Data– No Managed Cursor support in Whidbey– Must do Insert/Update/Delete as

necessary

Updating Data– No Managed Cursor support in Whidbey– Must do Insert/Update/Delete as

necessary

Page 31: SQL Server 2005: The CLR Integration What Developers and DBAs need to know

Managed User DatatypesManaged User Datatypes

Pre-SQL Server 2005– User Datatypes were aliases or restrictions

SQL Server 2005– Can store CLR Type as a Datatype– Rules are embedded in the CLR Type

Pre-SQL Server 2005– User Datatypes were aliases or restrictions

SQL Server 2005– Can store CLR Type as a Datatype– Rules are embedded in the CLR Type

EXEC sp_addtype N'age', N'tinyint', N'not null'GO

CREATE RULE age_rangeAS@age >= 0 AND @age <=140GO

EXEC sp_bindrule N'age_range', N'age'GO

Page 32: SQL Server 2005: The CLR Integration What Developers and DBAs need to know

Managed User Datatypes (2)Managed User Datatypes (2)

Requirements– Supports the concept of NULL (INullable)– Supports conversion to and from string– Supports serialization– Supports a default constructor– Type and member conform to naming

rules (128 character maximum)

Requirements– Supports the concept of NULL (INullable)– Supports conversion to and from string– Supports serialization– Supports a default constructor– Type and member conform to naming

rules (128 character maximum)

Page 33: SQL Server 2005: The CLR Integration What Developers and DBAs need to know

Managed User Datatypes (3)Managed User Datatypes (3)

Registering the UDT– Use CREATE TYPE DML Statement

Registering the UDT– Use CREATE TYPE DML Statement

CREATE TYPE <database type name>EXTERNAL NAME <assembly name>.<CLR type name>

CREATE TYPE PointEXTERNAL NAME ExampleYukon.Point

Page 34: SQL Server 2005: The CLR Integration What Developers and DBAs need to know

Managed User Datatypes (4)Managed User Datatypes (4)

Example: Example:[Serializable][SqlUserDefinedType(Format.UserDefined, MaxByteSize=8)]public class Point : INullable, IBinarySerialize { bool isNull = false; int x; int y;

// Required constructor public Point() : this(0, 0) { }

public Point(int x, int y) { this.x = x; this.y = y; } // ...}

Page 35: SQL Server 2005: The CLR Integration What Developers and DBAs need to know

Managed User Datatypes (5)Managed User Datatypes (5)

Using a UDT– Use CONVERT to switch from string to

type

Using a UDT– Use CONVERT to switch from string to

typeDECLARE @p as dbo.PointSET @p = Convert(dbo.Point, '3,8')SELECT @p

Page 36: SQL Server 2005: The CLR Integration What Developers and DBAs need to know

Managed User Datatypes (5)Managed User Datatypes (5)

Datatype methods– Marking it with SqlMethod can expose it

IsMutator shows SQL Server that it changes itself:

Can use with the point syntax:

Datatype methods– Marking it with SqlMethod can expose it

IsMutator shows SQL Server that it changes itself:

Can use with the point syntax:

[SqlMethod(IsMutator=true)]public void Swap() { int temp = x; x = y; y = temp;}

DECLARE @p as dbo.PointSET @p = Convert(dbo.Point, '3,8')SELECT @[email protected]()SELECT @p

Page 37: SQL Server 2005: The CLR Integration What Developers and DBAs need to know

Questions?Questions?