CLR Integration. Af Torsten Holtse, pbs Indhold

Relaterede dokumenter
Database for udviklere. Jan Lund Madsen PBS10107

Hvorfor skal vi bruge objekt orienteret databaser?

MapBasic &.NET interaktion. MapBasic.NET. Jakob Lanstorp IT konsulent COWI. Odense 23. Juni jun 2011 MapBasic &.

METODER ARV KLASSER. Grundlæggende programmering Lektion 5

FESD-standardiseringsgruppen Att: Palle Aagaard IT- og Telestyrelsen IT-strategisk kontor Holsteinsgade København Ø

Abstrakte datatyper C#-version

Introduktion til SQL

Object-Relational Mapping

Version Dato Beskrivelse /11/2012 Initial version /03/2013 Tilføjet eksempel med Template Agent, generelt udvidet dokumentet.

Installation og Drift. Aplanner for Windows Systemer Version

Databaseadgang fra Java

Introduktion til OPC Access

Ugeseddel 4 1. marts - 8. marts

Singleton pattern i Java

Arkitektur for begyndere

EG Data Inform. Byggebasen. WCF og webservices. Jens Karsø

TimePlan version Installationsvejledning

DM507 Algoritmer og datastrukturer

Grundlæggende OOA - OOD

educasoft - en professionel samarbejdspartner med speciale i uddannelse!

DM507 Algoritmer og datastrukturer

SWC eksamens-spørgsmål. Oversigt

DAVAR Omdøbt til SagDokumentFormat. Attention er skilt ud i et selvstændigt format, AttentionFormat.

Listen over reserverede ord er meget lang, men de væsentligste vil jeg beskrive her i denne artikel:

Databasesystemer. Databaser, efterår Troels Andreasen. Efterår 2002

AAU, Programmering i Java Intern skriftlig prøve 18. maj 2007

Kursusarbejde 3 Grundlæggende Programmering

Installation og Drift. Aplanner for Windows Systemer Version 8.15

Data load og udtræk. 2. iteration: implmentation (test af backend) PHP mysql. Loade og parse XML (SimpleXML, Xpath) Filhåndtering i PHP JSON

Videregående Programmering Obligatorisk opgave - 3. semester, efterår 2004

MsSQL: Basal performance tuning, part 1

Vejledning til Teknisk opsætning

Web CMS kontra Collaboration

.NET Component Overview

Database tips. Den forudsætter lidt kendskab til SQL men er for mindre erfarne. Denne guide er oprindeligt udgivet på Eksperten.dk

EasyIQ Opdatering > 5.4.0

Studieordning del

DANMARKS TEKNISKE UNIVERSITET

Skriftlig eksamen i Datalogi

Dygtig.NET / C# udvikler med stor erfaring fra både offentlige organisationer og private virksomheder.

Delphi og Databaser for begyndere

Indholdsfortegnelse. Systembeskrivelse kapitel 8 Administrationsdatabase

Program Dokumentation PC Software Skrevet af. Gruppen. Version 1.0

Introduktion til funktioner, moduler og scopes i Python

Hvad er Objekter - Programmering

Kapitel 4 Løkker i C#

Educasoft 2010 Side 1. Søgemaskineoptimering

Test af It-komponent

PID2000 Archive Service

Septimas høringssvar vedrørende dokumenteterne FKG datamodellen - Version Fysisk implementering.pdf og FKG_2_3_1_mssql.sql

Database programmerings tips

A Profile for Safety Critical Java

Objektorientering. Programkvalitet

Sammenligning af Objekt-orienteret databaser og Relationelle databaser.

Data Warehouse Knowledge is Power - Sir Francis Bacon -

Nintex Workflow UK/DK

Database "opbygning"

Tietgenskolen - Nørrehus. Data warehouse. Database for udviklere. Thor Harloff Lynggaard DM08125

Kursusarbejde 2 Grundlæggende Programmering

DM507 Algoritmer og datastrukturer

RMI introduktion. Denne artikel beskriver Java RMI (Remtote Method Invocation).

PHP 3 UGERS FORLØB PHP, MYSQL & SQL

SYSTEMDOKUMENTATION AF POC

Bypassing the. Brian Marick

Bemærk! Et PHP script har kun brug for at forbinde én gang til databaseserveren. Det kan så sagtens udføre flere kommandoer vha. denne forbindelse.

Specifikation Abstrakt OO OS-API Rev Specifikation. Abstrakt, objektorienteret operativsystem-api

Klasser og Objekter i Python. Uge 46 Learning Python: kap 15-16,

Erfaringer med CPR-replikering

Eksempel: et ordresystem note 5 Lagdeling s. 1

Data repository løsningsbeskrivelse

Anvendelse af metoder - Programmering

Datatekniker med programmering som speciale

2. Systemarkitektur... 2

Datatekniker med programmering som speciale

Software Construction 1 semester (SWC) Spørgsmål 1

Skriftlig opgave. Designtanker i database-nære systemer

Programmering I Java/C#

Database. lv/

Transkript:

CLR Integration Af Torsten Holtse, pbs10104 Indhold Opgavebeskrivelse... 2 Introduktion... 2 CLR Integrations muligheder... 2 Stored Procedures, Functions og Triggers... 2 Aggregates og User-defined Types... 3 Aggregate... 3 User-defined Type... 4 Intern adgang til databasen... 4 Registrering af assembly og funktionaliteter... 4 Registering af assembly... 4 Registering af funktionaliteter... 4 Fordele... 5 Flere funktionaliteter... 5 Objekt orienterede elementer... 5 Performance... 6 Kode-genbrug... 6 Ulemper... 6 Normalisering... 6 Performance... 6 Metadata-optimering... 7 Overvejelser... 7 1

Opgavebeskrivelse Denne opgave omhandler integrationen af CLR 1 i MSSQL 2. Udover den praktiske anvendelse vil opgave også se på de fordele og ulemper, der er forbundet med brugen af CLR integration. Disse fordele og ulemper vil berøre funktionaliteter og performance. Introduktion Som så mange andre databaser benytter Microsoft sig af et SQL-baseret sprog til programmering af deres SQL Server, T-SQL. T-SQL giver, som mange andre varianter af SQL, mulighed for at udvikle mere generelle programmeringsopgaver, der håndteres af databasen. Det er dog ikke SQL-baserede sprogs primære formål hvilket f.eks. kommer til udtryk ved mangler på områder som datatyper og iterationsmuligheder. Siden udgivelsen af SQL Server 2005 har der været en alternativ mulighed for programmering af funktionaliteter i databasen. Fra den version af blev det muligt at udarbejde de mere generelle funktionaliteter i et.net-sprog for derefter at lade SQL Serveren eksekvere denne.net-kode via en integrering af.net s motor, CLR. Denne funktionalitet i SQL Server betegnes af Microsoft som CLR Integration. CLR Integrations muligheder Programmeringen af en databasefunktionalitet med CLR integration foregår ved, at man programmerer et assembly i et.net-sprog, hvorefter assembly, og de deri liggende funktionaliteter, registreres i den pågældende SQL Server. CLR Integration giver mulighed for programmering af fem forskellige typer funktionaliteter: Stored Procedure User-defined Function User-defined Trigger User-defined Aggregate User-defined Type Fælles for disse funktionaliteter er, at de bygger på helt almindelig.net-kode, der grundlæggende ikke er bundet til CLR Integration. Implementeringen foregår i almindelige statiske metoder eller klasser alt afhængig af hvilken type funktionalitet der er tale om. Hver funktionalitet identificeres ved sin registrering i SQL Serven ud fra metadata tilføjet under implementeringen i form af en specifik attribute afhængigt af typen af funktionalitet. Stored Procedures, Functions og Triggers Stored Procedures, Function og Triggers er fælles om at blive implementeret via statiske metoder. Eksemplet nedenfor viser konstruktionen af User-defined Function i C#. 1 Common Lanugage Runtime 22 Microsoft SQL SERVER 2

namespace CLRIntegration { public partial class UDF { const string EMAIL_REGEX = @"^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}$"; [SqlFunction(IsPrecise = true, IsDeterministic = true)] public static bool IsValidEmail(SqlString str) { Regex emailregex = new Regex(EMAIL_REGEX); return (str.isnull? false : emailregex.ismatch(str.value)); } } } Eksempel 1 - IsValidEmail Det er kun selve metode-definitionen, der er interessant i dette tilfælde, men namespace og klasse skal dog også kendes i registreringsprocessen. SqlFunction-attributen er den afgørende forskel på en almindelig statisk metode og en metode, der skal bruges som user-defined function. Stored Procedures og Triggers har en tilsvarende attribute henholdsvis SqlProcedure og SqlTrigger. Udover at give CLR Integration mulighed for at identificere om en metode er beregnet til brug i SQL Server, indeholder SqlFunction også nogle properties, der benyttes som yderligere information for SQL Server til brugen af metoden. I eksemplet er metoden f.eks. specificeret som værende Precise, dvs. at metoden altid giver et præcist resultat. En funktion vil ikke være præcis hvis der f.eks. indgår beregninger med floating-points. Der findes flere af denne type metadata-properties, men disse vil ikke blive gennemgået nærmere. Aggregates og User-defined Types Aggregates og User-defined Types (UDT) konstrueres via en serialiserbar struct. Ligesom Stored Procedures, Functions og Triggers, defineres metadata i form af en attribute, henholdvis SqlUserDefinedAggregate og SqlUserDefinedType. Da der skal foretages en serialisering er det nødvendigt for SQL Serveren at vide hvordan dette skal foretages. Som udgangspunkt bruger SQL Serveren sin egen metode, kaldet Native, men i visse tilfælde kan det være nødvendigt, eller ønskværdigt, selv at bestemme hvordan serialiseringen foregår. I et sådan tilfælde betegnes serialiseringen som UserDefined og skal specificeres via en implementering af IBinarySerialize-interfacet. Nedenstående eksempel viser definitionen af UDT. [Serializable] [SqlUserDefinedType(Format.UserDefined, ValidationMethodName = "ValidateEmail", MaxByteSize = 256, IsByteOrdered = true)] public struct EmailType : INullable, IBinarySerialize Eksempel 2 - User-defined Type Aggregate En aggregate i CLR Integration udfører sine handlinger ved at splitte arbejdet op i mindre dele. Delen samles igen efterhånden som de bliver færdige for til sidst at kunne levere ét samlet resultat. CLR Integrationen håndterer dette ved en struct med fire specifikke metoder, Init, Accumulate, Merge og Terminate. Init kaldes ved opstarten af en ny del af aggregaten. Dernæst løber den enkelte del sine egne værdier igennem og aggregerer dem i Accumulate. Når en del er færdig laver den en Merge med en anden 3

del. Når der til sidst kun er en del tilbage vil denne have opsamlet delresultaterne fra en andre dele og kører til sidst Terminate, der returnerer det endelige resultat. User-defined Type Udover de forudgående beskrevne krav kræves det også at en UDT er Nullable ved at implementere INullable. Dette bliver et krav da SQL Serverens normale typehåndtering som udgangspunkt tillader null. Intern adgang til databasen Mange funktionaliteter i SQL Server skal ikke bare foretage nogle beregninger baseret på input, de skal også kommunikere internt med databasen. I.NET håndteres denne interne kommunikation som den normalt gøres i ADO.NET. Da koden imidlertid kører internt i SQL Serveren skal der dog ikke oprettes en almindelig forbindelse til databasen. Der benyttes en speciel connectionstring, context connection = true. Denne connectionstring får et kald fra.net-metoden til at benytte samme forbindelse som den i forvejen kører på fordi den køres fra SQL Serveren selv, på samme måde som et databasekald i en funktionalitet skrevet i T-SQL ville gøre. Yderligere har giver.net adgang til en speciel kontekst-klasse, SqlContext, der også kan kommunikere internt i SQL Serveren eller identificere om der overhovedet er tale om CLR Integration. Registrering af assembly og funktionaliteter Når man har programmeret færdig i.net skal koden distribueres videre til SQL Serveren. Dette er en ret enkel proces, der deler store ligheder med konstruktionen af diverse almindelige funktionaliteter i SQL Server. Registering af assembly CREATE ASSEMBLY [CLRIntegration] FROM 'C:\Users\Annxii\Documents\CLRIntegrationLib.dll' WITH PERMISSION_SET = SAFE; Script eksempel 1 - Create Assembly Assembly et får her navnet CLRIntegration og den refererede DLL kopieres til databasen. Ved senere registrering eller eksekvering af metoder i CLRIntegration er det kopien i databasen, der benyttes. Der ud over sætte hvilken permission det pågældende assembly har, i dette tilfælde SAFE. Der er tre forskellige grader af assembly permissions, SAFE, EXTERNAL_ACCESS og UNSAFE. SAFE giver lov til at eksekvere koden og kommunikere internt i databasen. EXTERNAL_ACCESS giver lidt flere muligheder f.eks. adgang til filsystemet og netværkskommunikation. UNSAFE giver mulighed for at lade CLR kalde unmanaged code. UNSAFE benyttes af Microsoft til registrering af det grundlæggende.net Framework i SQL Server, men det anbefales ikke at almindelige udviklere benytter mere end EXTERNAL_ACCESS. Registering af funktionaliteter Efter registreringen af et assembly skal hver af de ønskede funktionaliteter tilføjes med hver deres registering. Nedenstående eksempel viser registreringen af metoden fra Eksempel 1. CREATE FUNCTION [IsValidEmail](@email nvarchar(max)) RETURNS bit AS EXTERNAL NAME CLRIntegration.[CLRIntegration.UDF].IsValidEmail Script eksempel 2- Create Function 4

De første to linjer ligner starten på en almindelig definition af en Function. Det er dog vigtigt at funktionens parametre og retur type stemmer overens med dem i den pågældende metode i assembly et. Navngivningen er her irrelevant i forhold til assembly ets indhold. Derimod er navnene vigtige i sidste linje. Normalt vil implementeringen af funktionen begynde her, men da denne jo allerede er foretaget i. NET skal der refereres til hvor i assembly et den ønskede metode befinder sig. Det ovenstående eksempel finder sin metode i assembly et fra Script Eksempel 1 og derefter metoden fra Eksempel 1 baseret på hvilket namespace og hvilken klasse den pågældende metode har. Eksemplet er vist med en Function, men fremgangsmåde er den samme for de andre funktionaliteter. Fordele Som jeg startede med at skrive så er CLR Integration et alternativ til de tillempninger, som er foretaget i T- SQL for at gøre det muligt at udføre handlinger, der strækker sig ud over den grundlæggende forespørgselsfunktionalitet i SQL. Det grundlæggende argument for at benytte CLR Integration bør derfor være, at man benytter et sprog til det det er beregnet til. Sprogene i.net-familien er tiltænkt beregninger og kompleks logik, hvilket også gør dem optimerede til disse formål. Flere funktionaliteter Optimeringen af.net handlinger ikke kun om processorkraft, men også om de ekstra funktionaliteter, der følger med.net. I eksempel 1 er der f.eks. benyttet regular expressions til validering af en input streng, hvilket ikke er en funktionalitet i T-SQL. Nogle funktionaliteter, der allerede er i T-SQL, kan også forbedres af.net, hvor f.eks. arbejde med filsystemet eller XML lettere kan håndteres..net giver også flere kodemæssige elementer at arbejde med i forhold til T-SQL. Der er flere forskellige datatyper at arbejde med og større udvalg af code-flow. Udover de ekstra mere generelle funktionaliteter, der er i.net giver CLR Integration også nogle direkte database orienterede funktionaliteter. Det er kun muligt at lave sine egne aggregates via CLR Integration, alt hvad T-SQL kan bidrage med i den henseende er registreringen af funktionaliteten. Objekt orienterede elementer SQL Server udelukkende en relationel database, men brugen af UDT via CLR Integration kan give nogle objekt orienterede elementer. UDT i ren T-SQL kan kun være en indsnævring af en eksisterende type i SQL, eller bare benyttet som alias, eller det kan være en tabel. En UDT i CLR Integration bedre betegnes som et decideret objekt. Udover at det rent teknisk reelt set er et serialiseret.net-objekt, der ligger i en tabel, så kan Methods og Properties implementeres som ved en almindelig struct. Disse kan kaldes fra T-SQL, og bruges til at ændre dele af den data UDT en består af på samme måde som man kan i.net. Denne muligheder ses i ORDBMS, men manglen af andre vitale objekt orienterede dele som nedarvning, polymorfi og referencer gør at CLR Integration ikke kan gøre SQL Server til en ORDBMS. Fordelen ved disse tilnærmede objekt orienterede elementer kan tages fra ideen bag objekt orienterede databaser. Ved at bringe modellen fra programmeringen direkte ned i databasen undgås noget det overhead, og den kompleksitet, mapping mellem den relationelle og objekt orienterede verden giver. 5

Eftersom det ikke er en decideret objekt orienteret model der gemmes men kun isolerede objekter, vil man stadig have behov for data mapping i et vist omfang også selvom man benytter UDT. Performance De ekstra funktionaliteter er også dem, der kan give CLR Integration en fordel frem for rå T-SQL..NET er i langt højere grad optimeret til matematiske og logiske beregninger, og kan derfor give en fordel på disse områder. Foretages disse beregninger yderligere i loops er der endnu mere at vinde. En cursor er som udgangspunkt dyr i drift. Mulighederne i CLR Integration gør en i stand til at undgå cursor i flere tilfælde. I tilfælde hvor cursor funktionaliteten kan erstattes af egne aggregates vil dette være at foretrække rent performancemæssigt. Det samme gør sig gældende hvor en traverserende cursor kan erstattes af arbejde med et array. Kode-genbrug Ved at programmere funktionaliteter til CLR Integration har man også mulighed for at genbruge funktionaliteterne i en anden sammenhæng. Stored Procedures og Functions er dyest set stadig almindelige statiske metoder, og kan derfor kaldes fra andre.net-programmer. Eksempelvis kan funktionen fra Eksempel 1 bruges både i CLR Integration og i et hvilket som helst.net-program. Dette giver en fordel ved kun at skulle vedligeholde en funktionalitet også selvom denne bruges i flere forskellige sammenhæng. I Eksempel 1 skal der ikke foretages noget for at bruges koden andet sted end i SQL Server, men der kan i visse tilfælde være behov for, at foretage justeringer alt efter hvilken sammenhæng koden eksekveres i. Via SqlContext kan man identificere om der er tale om CLR Integration eller ej, og f.eks. ændre connectionstring i tilfælde hvor ADO.NET benyttes. Ulemper Hvis ikke der var nogle ulemper ved CLR Integration var der ikke nogen grund til, at SQL Server stadig benytter T-SQL som sit primære programmeringsprog. På trods af, at CLR Integration kan forbedre performance i visse situationer så kan det nemt også gøre det modsatte. Dertil kommer mulige problemer ved brug af UDT og kompleks finjustering. Normalisering Brugen af UDT kan give problemer for strukturen af databasen. En relationel database skal som oftest normaliseres, hvilket i første omgang indebærer atomare værdier. Om noget betegnes som en atomar værdi kan komme an situationen, men i og med at UDT grundlæggende er et serialiseret objekt vil det også være nærliggende, at UDTen kommer til at få objekt orienterede træk som gruppering af data. Dette stiller en i et dilemma ved brugen af UDT. Hvis man designer UDT til brug uden for databasen vil det ødelægge muligheden for normalisering, men hvis man tager højde for normaliseringen vil det ødelægge muligheden for den mapningsfri transition mellem database og applikation. Performance Som nævnt kan performance gå begge veje ved brugen af CLR Integration. Den negative indvirkning kommer i første omgang når arbejdet skal over i.net. SQL Server kører godt nok.net internt, men det er 6

trods alt stadig et andet system, hvilket vil sige at SQL Server skal overdrage ansvaret til.net og vice versa. Dette indbefatter ikke noget stort overhead, men det sker hver gang der skal skiftes mellem SQL Server og.net. Hvis en funktion med input, der er skrevet i.net, bruges i forbindelse med en projektion af et udtræk vil dette skifte sker for hver række i udtrækket. Performance vundet ved den forbedrede beregning i.net skal derfor overstige det overhead, skiftet mellem SQL Server og.net forsager. Af samme grund er det også farligt for performance hvis man benytter kald tilbage til databasen i loops. Performance kan også komme til at lide under manglende query optimering. Ved brugen af stored procedures eller functions i forbindelse med en query vil SQL Server normalt forsøger at tage indholdet af disse med i sin optimering af queryen. Hvis den pågældende stored procedure eller functions imidlertid er lavet i.net er det straks sværere. SQL Serveren kan ikke læse.net kode og kan derfor ikke tage højde for indholdet i sin optimering. Eventuel rå SQL internt i den pågældende stored procedure eller function vil blive optimeret separat. Optimeringen vil potentielt blive splittet i forhold til hvad T-SQL ville resultere i og SQL Serveren kan derfor ikke foretage optimeringen optimalt(!). Metadata-optimering SQL Serverens manglende evne til at læse.net, og de ulemper der kommer heraf, kan delvist afhjælpes via metadata på implementationen af visse funktionaliteter. Det store problem ved denne metadata er, at man selv skal specificere den, hvilket også vil sige at man manuelt skal bestemme specifikationer som SQL Serveren normalt klarer for en. Det tidligere eksempel 1 bruger IsPrecise og IsDeterministic. I det lille eksempel er det ikke så svært at overskue disse tilstande, men det kan være betydelig sværere i mere komplekse sammenhænge. Udover at dette selvfølgelig er ekstra arbejde giver det også en større mulighed for fejl end en automatiseret analyse udarbejdet af eksperter vil. Overvejelser CLR Integration er helt klart en niche inden for SQL Serveren. Det er funktionaliteter, der skal bruges med betydelig omtanke til specielle situationer. Det er en løbende debat hvor meget funktionalitet, der skal lægges ned i databasen, og CLR Integration har uden tvivl sin plads hvor man lægger store mængder funktionalitet i databasen. Med undtagelse af user-defined aggregate vedrører udvidelserne via.net funktionaliteter, der ikke direkte må siges at være SQL Serverens kærneområder. Man kan undre sig over hvorfor der ikke er nogen mulighed for implementation af aggregates i T-SQL. UDT kan være et stærkt redskab i visse tilfælde. At gemme objekterne fra.net direkte i databasen går naturlig nok arbejdet med data i.net lettere, mens understøttelsen af properties gør det muligt at stadig at arbejde med objektet uden for.net. Det er dog stadig langt fra en OODBMS eller ORDBMS. Brugen af UDT bør derfor selv sørge for ikke at bryde normalisering eller benyttes i situationer hvor normalisering ikke er en nødvendighed. Brugen af CLR Integration kan også bringe ekstra kompleksitet ind i programmeringen af databasen. Man kan ikke erstatte al T-SQL, hvilket vil resultere i at man har arbejder med to forskellige programmeringssprog og paradigmer, den relationelle- og den objekt orienterede. Denne sammenblanding muliggør kode-genbrug, men kan kræve, at der tages højde for forskellene i programmeringssprogene. Det vil godt nok give færre kode-dele at vedligeholde, men disse vil blive hver især blive mere komplicerede. 7

Idéen bag CLR Integration er ikke en Microsoft-opfindelse. SQL2003-standarden indeholder specifikationer til en implementation af samme typer funktionaliteter i Java, SQL/JRT 3. Hvis en Java implementation af database funktionaliteter skal være en del af SQL-standarden bør der også være belæg for at standardisere CLR Integration. Denne underliggende CLR er, ligesom Java-motoren, et produkt med en åben standard, der primært vedligeholdes og implementeres af et kommercielt firma. På trods af at være en standardiseret funktionalitet er SQL/JRT også en meget lille niche. Den eneste store database, der implementerer SQL/JRT er IBMs DB2. 3 http://www.iso.org/iso/iso_catalogue/catalogue_tc/catalogue_detail.htm?csnumber=37102 8