ACCESSSQL Server2005(Yukon) CLR体系布局

转自<Csdn> 
   [概述] 随着SQL Server “Yukon” Beta1(也许也有人说:SQL
Server2005)的产,人们发现微软于Yukon中并了怪多之初成效,其中最为引人瞩目的凡在数据库引擎中合拢了针对Windows
.NET Framework Common Language Runtime (CLR
公用语言运行环境)的支持。在2000年7月之正规化开发者大会(PDC)上,微软首先浅向世界展示了这个新特点。
    作为SQL Server
2000之开发人员,编写数据库的应用程序往往就局限为T-SQL,而宿主了CLR的Yukon,引入了众雄的初特色,我们得以就此Visual
Basic.NET, C#
等面向对象的言语就以前T-SQL难被完成的天职。比如,以前俺们若如调用一些体系函数(WIN32API或COM组件),我们须写扩展存储过程,通过ODS(Open
Data
Services)开放式数据服务层及数据库引擎交互,而今日我们通过CLR提供的托管对象可以十分便于的调用Windows
.NET Framework Class Library (FCL).NET框架类库。这些托管对象包括:
• 托管存储过程
• 托管函数
• 托管触发器
• 自定义复杂数据库类型
• 自定义复杂类型索引
• 自定义集合函数
   
首先,我们如果询问数据库引擎集成CLR的优势以及CLR可以提供的一些重要特性。
   
CLR是一个托管的运行条件,所谓“托管”的意思是累累任务过去得程序员负责之(比如内存管理)现在可委托CLR来拍卖。作为托管代码的均等有些,CLR控制代码执行过程被的各个一个有,同时CLR是基于项目安全(CLR扮演了代码验证的角色)和平安批准的环境――彻底地编译为本地代码(Native
Code)。CLR可以“辨识”出运行的代码是否企图直接处理内存还是调用非.NET的代码。
   
.NET的而是实施代码在CLR中被载为顺序集(assemblies)的形式。程序集中包括中语言代码(IL指令),描述代码的排头数据(Metadata)和外资源(比如:引用其它文件列表),源代码并无是一直保存在程序集中,而是编译为同一种植CLR可以读懂的中等语言(IL),在程序执行之前CLR通过就经常编译(JIT)将代码转换为本地代码(通常是X86代码)。如果代码在地方运行,这个地面代码会吃加载到同一截有生命周期的缓存,这就是说.NET的代码是非解释型的――它以运作时最后会受编译成本地代码。
   
CLR拥有自己管理内存的计:如果一个目标要平等组对象没于别运行的代码引用,从理论及说得回收所有不再使用的内存,但是于CLR,内存只是于运转资源贫乏时才见面让回收,CLR于用格外的内存资源时才调用垃圾收集器,这种内存管理机制使程序员不用担心内存泄漏。
    所有的代码都运作于投机之应用程序域(Application
Domain)。在CLR环境面临,应用程序域的企图是以单个进程被宿主不同的应用程序域,用来隔断不同之推行代码
――
换句话说,在一个应用程序域中之周转失常的代码不见面影响外应用程序域中运作的代码。
每个过程面临还存在至少一个具备CLR的应用程序域, 当然,
也足以产生多只――这是由于寄宿进程同运作的托管代码决定的。当一个主次集被CLR加载时,是凭被加载(即经常编译(JIT))到一个指定的应用程序域中,同时这次集为足以于加载到跟一个历程遭到不同之应用程序域中。也堪加载一个中立的次序集――在这种情形下,一个主次集的独自备份可以啊一个经过遭到具有的用户提供服务。
    寄宿 
   
宿主了CLR的Yukon数据库引擎来一些非同寻常需要。数据库引擎对于资源管理是甚谨慎之――比如:通过直观推断数据库使用的资源变,在不同之缓存中走内存。因此,应该在数据库引擎和CLR的资源管理措施保障某种默契关系。
    在CLR的1.0跟1.1的本子中,
CLR提供一个API来增长进程的操纵――比如判断CLR线程池的轻重。当然,这个API并非强大到可以代表CLR在Yukon中之意向,
比如:考虑以下几栽状态:
内存管理
    Yukon
数据库引擎完全控制就被分配的内存空间,在不同之缓存中切换,比如:存储过程缓存和数量缓存。在这种气象下,Yukon
数据库引擎需要来逾灵敏的办法来运转CLR的污染源收集器,同时针对CLR垃圾收集器发生的规则,分配还是放多少内存有震慑。
线程管理
   
CLR通过线程技术完成异步任务及多元化的面世操作。CLR拥有自己的托管线程池,用来计划执行线程池中之职责。然而,
SQL Server使用更细的纤程机制(mechanism of
fibres)来应本着可能的巨量并发请求,因此,SQL
Server需要接管CLR的线程管理。
    并且,由于存在CLR的运行机制和SQL
Server的得之间的神妙关系,我们发现及及时亟需对CLR的夜宿接口进行扩展。因此趁Whidbey(是微软Visual
Studio .NET
的子弟版本)的发布.NET会提供再多与重复有力的寄宿API(Yukon发布之.NET版本及Yukon支持的.NET版本用保持一致)
Whidbey
    寄宿 API 的特性于Whidbey中,有7处寄宿API的首要部分得到了扩大:
内存管理
   
现在CLR允许宿主机(Yukon)取代WINDOWS和C运行库分配常规内存,因此今宿主机可以控制及判断内存的分配要放多少。同时,宿主机可以用好之内存通知机制取代标准的内存通知机制,从而可以触发发垃圾收集器。宿主机也得不开展内存分配,这时CLR会警告宿主机内存分配失败的结果,这样宿主机可以行使相应的国策。
   
Yukon通过这种方针施加对内存分配的震慑,这样来支配缓存的大小与防潜在地或致内存分页的操作。
线程
   
现在,CLR于线程中架空出一个初的概念叫任务(Task)。宿主机可以决定任务的分红与存储,包括任务之开头,结束和协办等等。同时CLR和宿主机相互告知显著的波(比如当任务由不过实施及不足实践之状态改变,反之亦然,宿主机也使通知CLR)。宿主机可以供配置CLR线程池工具。这样的购并级别允许Yukon延续温馨的轨道又同意CLR运行2个异步任务。
I/O实现
   
寄宿API现在可以为CLR的好处配置宿主机I/O同步,在I/O操作完后通知CLR。这样Yukon可以了了解进程内装有I/O的操作。
同步
   
如果CLR放弃对任务之控制,就必运许宿主机提供合不同任务的招。因此,宿主机必须提供一个智来建立:临界区(critical
section),互斥体(mutexes),事件(events),读写锁(reader/writer
locks)和监控器(monitors)。
宿主机通过这些决定方法,就了可以检测死锁操作。这样Yukon就足以是的处理CLR请求的计划任务从而增强整体运行的可靠性,解决并过程遭到的死锁。
托管和非托管
   
宿主机托管代码完成P/Invoke调用,转换为本土机械码时可能会见有题目,因为脚下还未曾以代码运行时检测何种锁给废除的道。新的宿主API中允许任务在脱离CLR控制时通报宿主机。比如:当代码运行在CLR表面时,Yukon会调整任务到non-fibre
scheduled
任务。同样这些非托管的代码块对数据库引擎是晶莹剔透底-例如:数据看的API,这些与其它的非托管代码是分对待的。
应用程序域中性代码
   
应用程序域中性允许加载一个主次集(assembly)时所部分应用程序域共享一个单独的便编译的顺序集镜像代码。在Whidbey以前版本,CLR有3单选项:加载所有程序集的应用程序域中性;不加载程序集的应用程序域中性;只加载强称程序集的应用程序域中性。
   
人们既意识及立刻并不曾为宿主机提供足够好之操纵粒度。一个和谐有一致模仿系统先后集的宿主机也或需要加载应用程序域中性,而富有用户之程序集,不论是大称的还是弱名称的,可以于分级加载到每个应用程序域。这样以一个应用程序域关闭时可以卸载用户之次序集而保留系统的次第集。
   
Yukon在加载所有的用户程序集至数据库的应用程序域,正是通过此特性加载进程内提供者程序集和任何应用程序域中性的系统程序集。
程序集查解(Assembly Resolution)
   
对于一个宿主机可以通过挂接应用程序域加载失败来定制程序集查解。这样做,宿主机就能够以次第集加载到一个托管的字节数组并且传递者数组到程序集分解器。这种机制对于Yukon来说还不够灵活,因为多数之先后集是经投机定制的办法加载。允许正常程序集查解失败而还要传递字节数组,这些内存复制的操作需要吃大量的属性开销。因此,寄宿API必须允许再多与顺序集分解器的并行。
   
目前,寄宿API允许宿主机决定是否用CLR执行顺序集分解或者用自己管加载,这样可以将顺序集返回非托管缓存来预防需要额外的内存复制。
   
Yukon不是以文件系统中保存用户的次序集而是在数据库中,因此Yukon不是运用专业的程序集查解而是下自己机制自动加载用户之次序集。
    Yukon使用的C
LR版本是一心紧密集成在Whidbey,而休行使机器及风行的本子,例如:尽管Yukon可以履以前版本的CLR编译的代码,但如果Whidbey兼容该代码就可了。幸运地是CLR已经竭尽全力保持对眼前版本的匹配,尽可能的以店铺于Yukon下运作的大方托管代码在Whidbey平台下不欲更编译。
先后集管理
   
下面我们来关怀一下CLR是怎么当Yukon中运作的?我们用了解Yukon如何保管及保存程序集代码。Yukon不负标准的次集控制过程(当一个主次集而加载时,CLR接管定位是次集的经过)而是用需之次序集保存及好的数据库被。这样可以建立完整的程序集的数据库备份,而毋庸引用在数据库备份和死灰复燃时可能改变的文件系统程序集。
    使用CREATE ASSEMBLY命令可以拿先后集加到数据库被,例如:
CREATE ASSEMBLY <assembly identifier>
FROM <path to assembly on file system>
   
这个命令不仅用拖欠次集加载到数据库,而且还包该程序集调用的旁非系统先后集。比如来一个顺序集Customer需要调用另外一个次集Util:
CREATE ASSEMBLY Customer
FROM ‘C:\build\customer\customer.dll’
   
这个命令将Customer程序集和Util程序集都保存至数据库中。任何Customer同Util调用的体系程序集还未待进入到数据库,因为Yukon已经了解这些体系程序集。系统先后集列表是不足配置的。对于Yukon来说是分别对待用户程序集和网程序集,系统先后集是从文件系统加载的规范程序集。
   
程序集标识符(在这个实例中凡是:Customer)在数据库被务必是绝无仅有的,Yukon根据此标识符代替原来的4段次集名称,原始之次集名称被贮存而且Yukon保证程序集在一个数据库被只有同意保留一差。
    程序集保存在数据库中,以通过sys.assemblies
系统视图查看(如表1),程序集的字节流可以经过sys.assembly_files系统视图查看(如表2)。

字段名 数据类型 描述
name sysname 程序集的名称 (在一个模式中是唯一的)
principal_id int 模式的拥有者编号
assembly_id int 程序集的编号(数据库中是唯一的)
permission_set tinyint 程序集的CAS配置
Explicitly_registered bit 程序集是否显示地加入到数据库或者依赖另外的程序集加入数据库
create_date datetime 程序集的加入时间
version_major int 程序集的主版本号
version_minor int 程序集的次版本号
version_build int 程序集组件的编译号和版本号
version_revision int 程序集组件的修订版本号
culture_info nvarchar(30) 程序集的修饰 (null 表示中性)
public_key varbinary(8000) 程序集的公钥 (null 表示弱名称)

申1 sys.assemblies 系统视图

字段名 数据类型 描述
assembly_id int 程序集文件的编号 (数据库中是唯一的)
name nvarchar(260) 文件名
file_id int 文件的编号 (在一个程序集中是唯一的)
content Image 文件的字节流

表 2 sys.assembly_files系统视图

   
有一个问题待指出,存储一个程序集到数据库需要拜访文件系统,因此先后集只能通过Windows的用户帐号来加载(不可以用纯SQL
Server用户帐号)或sa用户.这是坐Windows(控制文件系统的拜会)无法辨识SQL
Server的登陆用户.使用sa帐户是因Windows默认将欠帐户对许为系统管理员帐户.

   
在去一个序集时有成千上万摘取,你只能去指定的程序集,包括这顺序集及所涉的文本或者其一程序集和持有的附属程序集。

代码访问安全(CAS)

   
当一个程序集加载到数据库后,程序集代码是否足以开任意想做的事情?数据库引擎整合CLR其中有一个关键目的就是抽对扩大存储过程的指与风险。因此可以图景下我好尽量限制Yukon内在程序集以为安全的操作-这样至少对数据库的安静是好的。

   
CLR在传统的安康机制上还有一个根据用户权限的安全层,首先实施代码会检讨及时段代码可以发什么?这同一层称作代码安全访问CAS(Code
Access
Security),CAS使用于因原代码的特许要不只是哪位好尽其。过去CAS习惯用于允许打不同的位置加载有不同之履许可代码。可是,在Yukon中持有CLR基本代码都由数据库加载,这是盖,在本来程序集代码中产生不同的CAS定义。Yukon定义了3只“桶”(Bucket)来加载不同的程序集,每一个“桶”有差之一律组权限,代码可以做呀?根据程序集代码被加载到哪个“桶”来决定。

   
这3个CAS“桶”是:安全(SAFE),外部看(EXTERNAL_ACCESS)和未安全(UNSAFE),有关“桶”的详细安全信息,请圈表3

CAS 安全性 操作许可
SAFE 允许访问数据和使用CLR类。但不可以访问外部资源(比如系统文件和网络),多线程和单线程同步,非只读静态, 不安全代码和内部操作是禁止的。这个桶的代码必须是CLR验证类型安全的。
EXTERNAL_ACCESS 和内置SAFE桶的操作许可一样,但增加了可以访问外部资源比如文件系统,网络和事件日志,只要可以通过CLR的类库访问。使用内部操作来获得外部资源是禁止的。在这个单元中的代码必须是CLR验证安全的。
UNSAFE 在CAS子系统没有限制执行代码,在这个桶的代码是不需要类型安全。

申3 CAS桶的安概念

   
在UNSAFE桶内的代码和壮大存储过程一样产生安全问题。换句话说,直接内存操作及锁争用(包括死锁),这些都可能造成进程不安定。

    在Yukon中,默认所有的次集都是加载到SAFE“桶”,但这也可通过CREATE
ASSEMBLY命令加WITH PERISSION_SET子句来改变,比如:

CREATE ASSEMBLY Utilities
FROM ‘C:\assemblies\utilities.dll’
WITH PERMISSION_SET=EXTERNAL_ACCESS

   
将次第集在到数据库可通过权来决定,这些权限根据程序集让加载到到啊一个CAS“桶”。表4列有了用顺序集加入到不同CAS“桶”的权信息:

CAS 安全性 权限 注释
SAFE CREATE ASSEMBLY; REFERENCES 这个权限分配给服务器角色dbowner
EXTERNAL_ACCESS CREATE ASSEMBLY; REFERENCES; EXTERNAL ACCESS 外部访问的权限必须赋予master数据库
UNSAFE CONTROL SERVER 控制服务器分配给服务器角色 sysadmin

发明4 加入程序集至不同CAS桶的权限表

静态成员与应用程序域

    应用程序域的定义被射到这条件受到,决定了当寄宿CLR的Yukon代码中
CLR类型的静态成员具有一些奇特之职能让咱快回顾一下什么是应用程序域?它于CLR中凡是什么使的?所有的代码都以CLR控制下实施,也在一个应用程序域中。应用程序域相当给一个进程,让代码在一个切断单元中运行。不同应用程序域中之代码必须进行大量的音信置换(它们都调用
.NET架构类库).
如果一个应用程序域中之代码来严重问题(比如一个没有处理的良),
只来欠应用程序域于影响, 其它域不会见为影响延续做事。

    在这种隔离机制下:

  1. 每个程序集将受加载到独的应用程序域,
    除非它们叫出示地加载到应用程序域中性-这意味每一个应用程序域拥有一致段子独立的就算经常编译执行之代码拷贝。
  2. 一个种的静态成员对每个应用程序域都是专有的.
    除非该次集让加载到应用程序域中性。

    在目前Yukon的测试版本中,
我们决定于每个数据库有一个独立的应用程序域.
这代表当跟一个数据库里而发生个别截代码, 即使她于不同工作中运行,
CLR也无能够管它们隔离开来. 换句话说, 即便首先单事情都于交付,
在其中运行的代码仍然能改变另一个政工之平稳状态.
这打破了有关业务的平修黄金法则——隔离性 。

    因此, 在SAFE或EXTERNAL_ACCESS
CAS“桶”里运行的代码不克被安装为非就念属性,
在UNSAFE桶里运行的代码则没该限量。

    那么, 问题解决了为? 不幸的凡, 这样只是解决了问题之相同管辖分.
撇开UNSAFE“桶”不讲话(它原先就足以推行有秘的安危操作),
允许单独念静态字段有啊问题为? 问题在于在CLR类型的网遭到,
只念属性使得值类型和援类型不能够连存. 对于值类型来说,
字段就是数码本身(当字段被声称时内存即被分配)。
这意味着一个特读的值类型一旦被立就会维持无变. 然而,
一个引用类型字段只是简单的针对性分配给垃圾收集堆的内存块的引用.
只读之援类型字段只是保证该引用保持不移,
它所指向的靶子的所有状态不见面遭受其他影响. 因此,
在一个作业中运作的代码仍然可以看任何一个事务之状态,
即使它们加载在SAFE“桶”。

    因此, 任何引用类型字段一旦受构建后必须静态和只读的,
也就是说这种状态是免能够给改之.
这是咱保证一个事情中之更动真实地切断于其他一个出现事务的绝无仅有办法。

   
因此我们可用先后集在到数据库,只是整个故事的一半。我们常常说之及时是一个公共类的公用方法,但一个次集中之代码不会见自动可以于另外的先后集看。我们亟须当众调用一个主次集的艺术和类型,这样,这个顺序集才好叫别数据库代码和客户端程序引用。

托管存储过程

   
存储过程是广大数据库应用程序的面包与黄油,这是盖存储过程天生有这个优势。既然我们得以于数据库引擎中整合CLR,我们便得经托管存储过程的款式拜访这些CLR对象。可以于托管存储过程加载的对象要满足一些必需之准:

  • 所包含的接近必须是集体的
  • 艺术必须是公用的
  • 方式要是静态的

    我们来探望下面的代码
Foo.Method1办法是勿克顾的,因为Foo类不是公共类。Bar.Method2也未能够访问,尽管Bar类是公共类但是它的Method2法无是公用的。Baz.Method3呢非能够访问,尽管此类似以及法都是公有的,但它的方式不是静态的-因此数据库引擎不了解哪建一个Baz的实例来调用Method3方式。因此只有公用方法才可以叫托管存储过程看(或暴露于CLR的任何构造函数),在Quux
类中,方法及相近都是公用的。

class Foo
{
    public static void Method1()
    {
    }
}

public class Bar
{
    static void Method2() { }
}

public class Baz
{
    public void Method3() { }
}

public class Quux
{
    public static void Method4() { }
}

实例1 CLR函数之走访

   
当一个程序集被加载到数据库,这些公共类的公用方法并无是粗略的变成托管存储过程;每个方法的进口必须依据需求显得的展露出来。具体的语法如下:

CREATE PROCEDURE <Procedure Name>
AS EXTERNAL NAME <Assembly Identifier>:<Type
Name>::<Method Name>

    存储过程名<Procedure
Name>在数据库被得是唯一的,程序集编号<Assembly
Identifier>匹配已经被加载到数据库的程序集,类型名<Type Name>
是以章程被定义的种类名称,方法名<Method Name>
是程序集中之道名称。注意:存储过程名<Procedure
Name>和道名<Method Name>是未需要般配的。

    因此,根据实例1的Quux.Method4
类,我们建一个托管存储过程,名称为:MyMethod4,假要这个代码包含在一个程序集已经通过标识符Utils加载到数据库:

CREATE PROCEDURE MyMethod4
AS EXTERNAL NAME Utils:Quux::Method4

参数传递

   
在实质上用中异常少来囤积过程没有参数,在常规状态下,需要操作的数据会传递参数为存储过程-至少是概括这些多少的重要信息。因此我们用有一个为托管存储过程传递参数的不二法门。

    大家看看实例
3-1的C#的代码,这段代码中我们来一个类有3单办法,每个方法传递参数的点子略有不同。

  • Method1 通过值x传递,在这个点子吃参数值的改变对调用者是匪透明底。
  • Method2
    透过输出参数x传递,在C#编译器中,x的值只有经过输出参数的艺术才可得,x的新值对于调用者是晶莹的。
  • Method2
    通过引用型参数x传递,这个引用型参数x的价对于措施是可用之又参数值的改变对调用者是透明的。

public class Params
{
    public static void Method1( int x )
    {
    }

    public static void Method2( out int x )
    {
        x = 42;
    }

    public static void Method3( ref int x )
    {
        x = x + 2;
    }
}

实例2 C# 传递参数的主意

   
下面我们演示如何当一个托管存储过程中调用一个术(假设这些代码都深受加载为标识符为parameters的程序集):

    Method1 凡一直调用,代码如下:

CREATE PROCEDURE Method1
    @x int
AS EXTERNAL NAME parameters:Params::Method1

    我们得这样调用存储过程Method1:

EXEC Method1 5

   
Method2设聊复杂一些,但是TSQL有只OUTPUT输出参数的语法,因此这啊还算是简单。

CREATE PROCEDURE Method2
    @x int OUTPUT
AS EXTERNAL NAME parameters:Params::Method2

    我们好以下的主意调用存储过程Method2:

DECLARE @x int
SET @x = 0
EXEC Method2 @x OUTPUT
SELECT @x

    这个SELECT的结果为42。

   
最后,Method3较新看的假设复杂一些,因为虽然.NET有传递参数的定义就比如in/out,但TSQL没有区分output
和in/out
参数.OUTPUT子句简单地声称是价值在回去时或许会见改变,它并未针对法被的价好产生要可能无进展判定。因此Method3的语法和Method2的凡相同的。但是C#编译器语法分析会预防这些代码作同样的业务。

CREATE PROCEDURE Method3
    @x int OUTPUT
AS EXTERNAL NAME parameters:Params::Method3

然咱们就得如下调用存储过程Method3:

DECLARE @x int
SET @x = 3
EXEC Method3 @x OUTPUT
SELECT @x

    这段代码的返回值是5。

    还待留意一点-以Method2 和
Method3,我们相应当托管存储过程调用这个序集之前设定变量@x为某个一个规定的价值,这样保证传递的参数值是非空的。如果我们漏这无异实践,会导致一个老NullReferenceException。这个呢说明还来其他因素隐藏于换中-SQL
Server的数据类型和.NET的数据类型是免平等的,当我们的代码从一个条件迁移至另外一个,会发类型转换。我们这个实例表明SQL
Server中有些得以为空的类而当.NET对应的类是勿克也空。

返回值

   
托管存储过程得返回.NET函数的回到值。然而,当声明一个托管存储过程不时,你切莫需指定返回的门类(这个跟从定义函数不同,自定义函数是亟需声明返回值的品种)。因此,这需要以.NET的法中声明

public class RetVals
{
    public static int GetUltimateAnswer()
    {
        return 42;
    }
}

实例3 拥有返回值的计

   
我们在数据库被得这样调用(假设含这段代码的程序集已经深受加载到数据库,标识符为ReturnValues):

CREATE PROCEDURE GetUltimateAnswer
AS EXTERNAL NAME ReturnValues:RetVals::GetUltimateAnswer

    我们不怕可以这么获得.NET函数的返回值:

DECLARE @x int
EXEC @x = GetUltimateAnswer
SELECT @x

    这个案例被之返回值是42。

用户从定义函数(UDF)

   
自定义函数,非常简单,和存储过程异常相像。然而,在概念,声明和运用从定义函数时,还有一部分外加要素我们要厚。

    下面是用户从定义函数调用一个.NET函数的语法:

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

    函数名<Function Name>在数据库中必是绝无仅有的,
参数列表<Parameter List>
是参数叫以及参数类型列表,返回路<Return Type>
是函数的返回值的花色。程序集编号<Assembly Identifier>
是既加载的次第集的标识符,类型名<Type Name>
是CLR的宣示方法时之数据类型名称, 方法名<Method Name>
是CLR方法的称谓。此外,函数名<Function Name> 和 方法名<Method
Name>不需要配合。

    因此,可以参考下的语法声明一个.NET的方法:

public class Calc
{
    public static int Add( int x, int y )
    {
        return x + y;
    }
}

   
我们得以下的代码在托管自定义函数调用上面.NET代码声明的主意(假设是程序集已经深受加载到数据库并且标识符为:Calculator)

CREATE Function MyAdd
(
    @x int,
    @y int
)
RETURNS int
AS EXTERNAL NAME Calculator:Calc::[Add]

    注释:要留意脱离调用Add的法,因为当TSQL中已经发一个被Add的函数。

    这个函数可以如此调用:

SELECT dbo.MyAdd(5, 10)

    这个SELECT 的返回值为15。

    注意在函数中而切莫可知以OUTPUT参数。

   
到目前为止,我们看了极端简单易行的用户从定义函数,但是这里还躲藏了用户从定义函数的纷繁,用户从定义函数有诸多概念存储过程是无干的。

· ACCESS数据访问

   
这个概念是凭借函数是否访问过程内托管提供者。如果函数没有看过程内托管提供者,优化器就无见面为经过内托管提供者初始化。假如存储过程要数据访问CLR架构会自动初始化进程内托管提供者。

· 系统数据访问

   
如果函数访问的是用户数据而不是系统数据,优化器可以当组织WAITFOR查询时转。在此实例中,执行函数可以于一个通知事件平复如休需向网数据一致要参加额外资源。

· 精度

    如果一个函数是纯粹返回的,它不会见以浮点指针算法并且不见面有扬弃入错。

· 确定性

   
一个明了的函数返回值和输入参数是千篇一律的-不考虑变量因素,比如当前多年来及日。比如一个函数返回的是2单数字的相加是显而易见,一个函数返回时之岁月是无显。

· 外部看

    函数是否访问数据库的表资源,比如系统的文件系统或注册表。

   
因为优化器这个概念是很重要的,而且当目中能运用函数也是冲这些概念。可以用于索引的函数必须是:

  1. 大庭广众-在不同之时间点,一个特定行的目录应该是常量,这是必的-否则索引页的物理结构是行不通的。
  2. 精确性-如果一个函数的归来值是舍入错误,这个函数不容许是强烈的。
  3. 甭管多少访问-函数的输入参数不是绝无仅有决定输出的,因此这不确定函数。
  4. 无论标看-同数据访问同,其它因素呢会潜移默化函数的引人注目。

   
对于TSQL函数,数据库引擎可以根据调用内函数确定这些要素(比如:NEWID()是一个非确定性的函数同时会使调用它的函数也是休阳)。

   
可是,在CLR类库中内部函数量是好了不起的,因此,要求数据库引擎或一些“超级验证器”来决定函数是否是明确的是深艰难的。所以,对于CLR函数,可以经过System.Data.Sql.SqlFunctionAttribute来指定函数的习性。该属性可以因下表(表表5)进行布置。

名称 类型 默认值 注释
IsDeterministic Boolean False 标记函数是确定性还是非确定性
IsPrecise Boolean False 标记函数是精确还是非精确
DataAccess DataAccessKind None 指定函数是否访问进程内托管提供者,默认值是不访问,如果是READ表示访问
SystemDataAccess SystemDataAccessKind None 指定函数是否访问系统数据,默认值是不访问,如果是READ表示访问

表5 SqlFunctionAttribute 属性列表

   
数据库引擎可以规定函数是否访问了经过内托管提供者,而且验证是否真实的配合在性能被宣示的值。可是,至于其他性质,数据库被你来安排,因此而恐怕会见刻画一个以协调声明也显著的函数,但迅即当实质上常常凡不行的。将IsDeterministic的性设定也真(true),那么,你可以绝对确信函数是规定函数,否则该函数可能会见要索引页构成无效。

   
分别用C#和VB.NET展示了采用SqlFunction函数的性能来号该函数为阳的。

[SqlFunction(IsDeterministic = true)]
public static int Add( int x, int y )
{
    return x + y;
}

实例 4 – 用C#声称一个函数为举世瞩目

<SqlFunction(IsDeterministic:=True)> _
Public Shared Function Add(ByVal x As Integer, ByVal y As Integer) As
Integer
    Return x + y
End Function

实例4 – 用VB.NET声明一个函数为显著

   
你恐怕注意到以SqlFunction函数的性是可选的,如发生此特性遗漏,可以使用默认值。省略是叫允许的,所以可以免欲修改的代码就允许用大量曾经是的CLR代码。

结论

   
在马上首文章被我们讲解了支撑内嵌托管代码的数据库应用程序的为主架构,而且介绍了第二种植托管代码的发挥方式——托管存储过程及托管函数。

    通过CLR与SQL
Server引擎的组合,使Yukon数据库来更强劲的效能,我们得经面向对象的语言C#,
VB.NET, Visual C++, Visual
J#等等与.NET兼容的语言开发存储过程(我们甚至足以据此PHP和汇编来写),这样我们好由此面向对象的方式来开数据库应用程序,这比以前T-SQL面向过程的言语来重复充分之优势,并且开发环境也转变也当Microsoft
Visual Studio .NET
下开,这提供了越来越方便,快捷和速地缓解复杂的买卖案例的招。

   
我们还要假设专注,在数据库引擎和CLR的干中,数据库引擎占主导地位,控制内存的分红和响应客户端的求。CLR为Yukon提供了看系统以及网资源的组件,使我们可以一本万利之调用.NET
Framework提供的大度类库(FCL),同时,CLR组件也堪经进程内托管提供者访问数据库。

    在安全者,Yukon既出根据用户之SQL
Server的安模式,也产生CLR基于权力的安全模式。CAS给咱提供了大好的粒度来控制CLR代码的安康,也给DBA更多的一手来控制CLR对“外部”的访。

   
Yukon要到2005年才见面上市,我们这边介绍的就是诸多新特性的一样有,在微软的MSDN中网站已有那么些篇进行了介绍,大家好窥见Yukon还提供了不少特别实用的初成效。

相关文章