ACCESSSQL Server二〇〇五(Yukon) CLHaval体系布局

转自<Csdn> 
   [概述] 随着SQL Server “Yukon” Beta1(只怕也有人说:SQL
Server2007)的出产,人们发现微软在Yukon中合拢了老大多的新成效,个中最引人瞩目标是在数据库引擎中合拢了对Windows
.NET Framework Common Language Runtime (CLTucson公用语言运营环境)的协理。在三千年十7月的正式开发者大会(PDC)上,微软第三遍向世界体现了这几个新特色。
    作为SQL Server
两千的开发职员,编写数据库的应用程序往往只局限于T-SQL,而宿主了CLPAJERO的Yukon,引入了众多强有力的新特点,大家得以用Visual
Basic.NET, C#
等面向对象的言语形成此前T-SQL难于实现的天职。比如,以前笔者们只要要调用一些连串函数(WIN32API或COM组件),大家无法不写扩张存储进度,通过ODS(Open
Data
瑟维斯s)开放式数据服务层和数据库引擎交互,而现行反革命大家经过CL瑞鹰提供的托管对象足以万分便于的调用Windows
.NET Framework Class Library (FCL).NET框架类库。那么些托管对象蕴涵:
• 托管存款和储蓄进度
• 托管函数
• 托管触发器
• 自定义复杂数据库类型
• 自定义复杂类型索引
• 自定义集合函数
   
首先,大家要理解数据库引擎集成CLQX56的优势和CLLacrosse能够提供的局地人命关天天性。
   
CL库罗德是3个托管的周转条件,所谓“托管”的情致是许多职责过去供给程序员负责的(比如内部存款和储蓄器管理)未来能够委托CL昂Cora来拍卖。作为托管代码的一部分,CL福睿斯控制代码执行进度中的每3个某些,同时CLOdyssey是基于项目安全(CL凯雷德扮演了代码验证的剧中人物)和平安批准的条件――彻底地编译为本地代码(Native
Code)。CL凯雷德能够“辨识”出运营的代码是不是企图间接处理内部存款和储蓄器或调用非.NET的代码。
   
.NET的可实施代码在CL奥迪Q5中棉被服装载为顺序集(assemblies)的款型。程序集中包蕴中间语言代码(IL指令),描述代码的元数据(Metadata)和别的能源(比如:引用其余文件列表),源代码并不是直接保存在程序集中,而是编写翻译为一种CL福睿斯能够读懂的中间语言(IL),在程序执行在此之前CLPAJERO通过即时编写翻译(JIT)将代码转换为地方代码(平日是X86代码)。要是代码在当地运转,这几个地点代码会被加载到一段拥有生命周期的缓存,这正是说.NET的代码是非解释型的――它在运维时最后会被编写翻译花费地代码。
   
CL途乐拥有本人管理内部存款和储蓄器的格局:如若3个对象或一组对象没有被另对外运输行的代码引用,从理论上说必要回收全部不再利用的内部存款和储蓄器,不过对于CLTiguan,内部存款和储蓄器只是在运作能源不足时才会被回收,CLRubicon在急需格外的内部存款和储蓄器能源时才调用垃圾收集器,这种内部存款和储蓄器管理机制使程序员不用顾虑内部存款和储蓄器泄漏。
    全数的代码都运营在大团结的运用程序域(Application
Domain)。在CL奇骏环境中,应用程序域的功能是在单个进度中宿主差别的接纳程序域,用来隔绝不一致的推行代码
――
换句话说,在2个运用程序域中的运维很是的代码不会潜移默化别的应用程序域中运营的代码。
每个进度中都设有至少3个有着CL奥迪Q5的接纳程序域, 当然,
也能够有多少个――那是由寄宿进程和平运动行的托管代码决定的。当3个先后集被CL汉兰达加载时,是指被加载(即时编写翻译(JIT))到一个内定的采用程序域中,同时这些程序集也得以被加载到同1个进程中差别的利用程序域中。也能够加载叁当中立的次第集――在那种状态下,几个主次集的独立备份可以为贰个进度中拥有的用户提供劳动。
    寄宿 
   
宿主了CLXC90的Yukon数据库引擎有局地独特殊须要要。数据库引擎对于能源管理是非常深谋远虑的――比如:通过直观推测数据库使用的财富转移,在分歧的缓存之间活动内部存款和储蓄器。由此,应该在数据库引擎和CLRAV4的能源管理艺术维持某种默契关系。
    在CL翼虎的1.0和1.1的版本中,
CL奇骏提供一个API来增加进度的控制――比如判断CLXC90线程池的深浅。当然,那几个API并非强大到能够取代CL宝马X5在Yukon中的功用,
比如:考虑以下两种景况:
内部存款和储蓄器管理
    Yukon
数据库引擎完全控制已经被分配的内部存款和储蓄器空间,在不一样的缓存之间切换,比如:存储进度缓存和数量缓存。在那种气象下,Yukon
数据库引擎供给有越来越灵敏的办法来运维CLEnclave的垃圾堆收集器,同时对CL帕杰罗垃圾收集器产生的规范,分配或自由多少内部存储器产生影响。
线程管理
   
CLPRADO通过线程技术完结异步职务和多元化的面世操作。CL路虎极光拥有本人的托管线程池,用来安插执行线程池中的职分。然则,
SQL Server使用更精致的纤程机制(mechanism of
fibres)来应对也许的大量并发请求,由此,SQL
Server须要接管CL帕杰罗的线程管理。
    并且,由于存在CL中华V的运转搭飞机制和SQL
Server的必要中间的奥妙关系,我们发现到那亟需对CL奥德赛的下榻接口实行扩展。因而随着Whidbey(是微软Visual
Studio .NET
的后生版本)的发布.NET会提供越来越多和更强硬的寄宿API(Yukon揭橥的.NET版本和Yukon支持的.NET版本将保持一致)
Whidbey
    寄宿 API 的特点在Whidbey中,有7处寄宿API的重点部分得到了扩张:
内部存款和储蓄器管理
   
以后CLRubicon允许宿主机(Yukon)取代WINDOWS和C运维库分配常规内存,因如今后宿主机能够控制和判断内部存款和储蓄器的分配或自由多少。同时,宿主机能够用本人的内部存储器公告机制取代标准的内部存款和储蓄器文告机制,从而得以触发垃圾收集器。宿主机也足以不实行内部存款和储蓄器分配,那时CL大切诺基会警告宿主机内部存款和储蓄器分配战败的结果,那样宿主机可以采纳相应的政策。
   
Yukon通过这种政策施加对内部存款和储蓄器分配的影响,那样来支配缓存的深浅和防护潜在地恐怕造成内部存储器分页的操作。
线程
   
未来,CL昂Cora从线程中架空出二个新的定义叫职分(Task)。宿主机能够操纵职分的分红和储存,包涵义务的上马,截止和同步等等。同时CL哈弗和宿主机互相告知显明的风云(比如当任务从可举办到不可实践的气象改变,反之亦然,宿主机也要布告CLRubicon)。宿主机能够提供配置CL汉兰达线程池工具。那样的购并级别允许Yukon三番五次温馨的轨道同时允许CL中华V运行一个异步职分。
I/O实现
   
寄宿API以后得以为了CL揽胜的益处配置宿主机I/O同步,在I/O操作完毕后布告CLCRUISER。这样Yukon能够完全理解进度内装有I/O的操作。
同步
   
假设CL昂科威屏弃对义务的支配,就务须运许宿主机提供一块不相同职务的招数。由此,宿主机必须提供一个方式来确立:临界区(critical
section),互斥体(mutexes),事件(events),读写锁(reader/writer
locks)和监察和控制器(monitors)。
宿主机通过这几个决定措施,就完全能够检查和测试死锁操作。这样Yukon就能够正确的处理CLPRADO请求的安插职务从而增强总体运维的可信性,消除协同进度中的死锁。
托管和非托管
   
宿主机托管代码达成P/Invoke调用,转换为地点机械码时或然会有标题,因为如今还尚未在代码运维时检测何种锁被撇下的主意。新的宿主API中允许职务在脱离CLOdyssey控制时通报宿主机。比如:当代码运营在CL宝马X5表面时,Yukon会调整职责到non-fibre
scheduled
职责。同样那个非托管的代码块对数据库引擎是晶莹的-例如:数据访问的API,那几个和其余的非托管代码是分别对待的。
接纳程序域中性代码
   
应用程序域中性允许加载3个程序集(assembly)时享有的运用程序域共享3个单独的尽管编写翻译的先后集镜像代码。在Whidbey以前版本,CL福睿斯有3个选项:加载全数程序集的使用程序域中性;不加载程序集的应用程序域中性;只加载强名称程序集的利用程序域中性。
   
人们早就意识到这并没有为宿主机提供丰富好的操纵粒度。一个祥和独具一套系统先后集的宿主机也大概须求加载应用程序域中性,而享有用户的程序集,不论是强名称的照旧弱名称的,能够被分别加载到各种应用程序域。这样在二个行使程序域关闭时能够卸载用户的先后集而保留系统的先后集。
   
Yukon在加载全体的用户程序集到数据库的行使程序域,正是通过那些特点加载进程内提供者程序集和其他应用程序域中性的种类程序集。
先后集查解(Assembly Resolution)
   
对于3个宿主机能够经过挂接应用程序域加载战败来定制造进度序集查解。那样做,宿主机就能将顺序集加载到三个托管的字节数组并且传递那一个数组到程序集分解器。那种体制对于Yukon来说还不够利索,因为大多数的次第集是经过投机定制的章程加载。允许平常程序集查解战败而且还要传递字节数组,那几个内部存款和储蓄器复制的操作要求花费大批量的品质费用。由此,寄宿API必须同意越多和次序集分解器的相互。
   
近来,寄宿API允许宿主机决定是或不是要求CL大切诺基执行顺序集分解或许需求团结确定保证加载,那样能够将先后集重回非托管缓存来幸免须要至极的内部存款和储蓄器复制。
   
Yukon不是在文件系统中保存用户的程序集而是在数据库中,由此Yukon不是运用正式的顺序集查解而是接纳自个儿机制自动加载用户的主次集。
    Yukon使用的C
LGL450版本是一心紧凑集成在Whidbey,而不采用机器上流行的版本,例如:固然Yukon能够实施此前版本的CLLX570编写翻译的代码,但假如Whidbey包容该代码就能够了。幸运地是CL奇骏已经努力保证对前面版本的匹配,尽或然的将公司在Yukon下运维的汪洋托管代码在Whidbey平台下不必要再行编译。
次第集管理
   
下边大家来关注一下CL福睿斯是怎么样在Yukon中运维的?大家要求通晓Yukon怎么样管理和保留程序集代码。Yukon不借助于标准的次序集控制进度(当3个程序集要加载时,CL牧马人接管定位这么些顺序集的长河)而是将急需的程序集保存到祥和的数据库中。那样能够创建完整的顺序集的数据库备份,而不用引用在数据库备份和还原时或者变动的文件系统程序集。
    使用CREATE ASSEMBLY命令能够将顺序集加到数据库中,例如:
CREATE ASSEMBLY <assembly identifier>
FROM <path to assembly on file system>
   
这么些命令不仅将该程序集加载到数据库,而且还包含该程序集调用的别样非系统先后集。比如有3个程序集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私下认可将该帐户对应为系统一管理理员帐户.

   
在剔除3个程序集时有很多摘取,你不得不删除钦命的程序集,包罗这些程序集及所提到的文本或其一程序集和颇具的隶属程序集。

代码访问安全(CAS)

   
当多个先后集加载到数据库后,程序集代码是或不是足以做任意想做的作业?数据库引擎整合CLTiggo在那之中有一个首要目的正是减掉对扩大存款和储蓄进度的依靠和高风险。由此能够状态下自身喜欢尽量限制Yukon内在程序集觉得安全的操作-这样至少对于数据库的安静是便宜的。

   
CL奥迪Q5在守旧的云浮机制上还有多少个依据用户权限的安全层,首先实施代码会检查那段代码能够作什么?这一层称作代码安全访问CAS(Code
Access
Security),CAS使用于基于原代码的准许而不只是何人能够执行它。过去CAS习惯用于允许从不一致的职分加载有差别的推行许可代码。可是,在Yukon中有所CL索罗德基本代码都从数据库加载,那是因为,在本来程序集代码中有例外的CAS定义。Yukon定义了1个“桶”(巴克et)来加载分裂的程序集,每叁个“桶”有两样的一组权限,代码能够做什么?遵照程序集代码被加载到哪个“桶”来支配。

   
那2个CAS“桶”是:安全(SAFE),外部访问(EXTETiggoNAL_ACCESS)和不安全(UNSAFE),有关“桶”的详细安全音信,请看表3

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

表3 CAS桶的平安概念

   
在UNSAFE桶内的代码和壮大存款和储蓄进度一样有平安难题。换句话说,直接内部存款和储蓄器操作和锁争用(包蕴死锁),那么些都恐怕引致进程不稳定。

    在Yukon中,默许全数的主次集都以加载到SAFE“桶”,但那也能够因此CREATE
ASSEMBLY命令加WITH PETiguanISSION_SET子句来改变,比如:

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

   
将顺序集参与到数据库能够透过权限来控制,这么些权限根据程序集被加载到到哪3个CAS“桶”。表4列出了将顺序集参加到差别CAS“桶”的权杖消息:

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

表4 加入程序集到不一样CAS桶的权限表

静态成员和选取程序域

    应用程序域的定义被映射到这几个环境中,决定了在寄宿CL揽胜极光的Yukon代码中
CL索罗德类型的静态成员具有一些异样的效益让大家十分的快回想一下怎样是利用程序域?它在CL凯雷德中是何许运用的?全部的代码都在CL陆风X8控制下实施,也在二个运用程序域中。应用程序域约等于三个进程,让代码在3个割裂单元中运作。分歧选取程序域中的代码必须举办多量的新闻沟通(它们都调用
.NET架构类库).
假使2个使用程序域中的代码爆发严重难点(比如二个未曾拍卖的12分),
唯有该接纳程序域受影响, 其余域不会受影响延续工作。

    在这种隔开分离机制下:

  1. 每种程序集将被加载到独门的使用程序域,
    除非它们被呈现地加载到应用程序域中性-那意味着每二个运用程序域拥有一段独立的即时编写翻译执行的代码拷贝。
  2. 3个档次的静态成员对每一种应用程序域都是专有的.
    除非该程序集被加载到利用程序域中性。

    在近期Yukon的测试版本中,
大家决定让各种数据库拥有四个独门的应用程序域.
这意味在同三个数据Curry尽管有两段代码, 即便它们在分裂工作中运作,
CLEscort也不能够把它们隔开分离开来. 换句话说, 即使首先个事情已经被交给,
在在那之中运维的代码依然能够转移另八个事情的稳步状态.
那打破了关于业务的一条黄金法则——隔绝性 。

    因此, 在SAFE或EXTERNAL_ACCESS
CAS“桶”里运营的代码不能够被设置为非只读属性,
在UNSAFE桶里启动的代码则尚未该限量。

    那么, 难题消除了呢? 不幸的是, 那样只消除了难点的一部分.
撇开UNSAFE“桶”不谈(它原先就足以实施一些隐秘的危殆操作),
允许只读静态字段有哪些难点呢? 难点在于在CLPAJERO类型的系统中,
只读属性使得值类型和引用类型不能够并存. 对于值类型来说,
字段正是数码本身(当字段被声称时内部存款和储蓄器即被分配)。
那象征四个只读的值类型一旦被确立就会保持不变. 但是,
四个引用类型字段只是简短的对分配给垃圾收集堆的内存块的引用.
只读的引用类型字段只是保障该引用保持不变,
它所针对的对象的具备意况不会蒙受任何影响. 由此,
在一个作业中运作的代码照旧能够观望另二个业务的情状,
即便它加载在SAFE“桶”。

    因而, 任何引用类型字段一旦被营造后务必静态和只读的,
相当于说那种情况是无法被更改的.
那是我们保险2个作业中的改变真实地切断于另3个面世事务的唯一方式。

   
因而咱们可以将先后集参加到数据库,只是整个好玩的事的五成。我们常说的那是3个公共类的公用方法,但贰个顺序集中的代码不会自行能够被其余的次序集访问。我们无法不公开调用二个主次集的艺术和类型,那样,这些程序集才能够被别的数据库代码和客户端程序引用。

托管存款和储蓄进程

   
存款和储蓄进程是累累数据库应用程序的面包和黄油,那是因为存储进度天生有那一个优势。既然大家能够在数据库引擎中整合CL科雷傲,大家就足以因而托管存款和储蓄进程的样式拜访这么些CLMurano对象。能够被托管存款和储蓄进度加载的对象必须满足一些不可或缺的基准:

  • 所涵盖的类必须是公家的
  • 措施必须是公用的
  • 情势必须是静态的

    我们来看看上面包车型地铁代码
Foo.Method1方法是不能够访问的,因为Foo类不是公共类。Bar.Method2也不能够访问,固然Bar类是公共类不过它的Method2主意不是公用的。Baz.Method3也不能够访问,固然那个类和艺术都以国有的,但它的艺术不是静态的-因而数据库引擎不明了怎么树立三个Baz的实例来调用Method3方法。由此唯有公用方法才方可被托管存储进程访问(或暴光给CL纳瓦拉的别的构造函数),在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 CLEvoque函数的走访

   
当叁个程序集被加载到数据库,这几个公共类的公用方法并不是简简单单的变成托管存款和储蓄进度;每一个方法的输入必须依据须求显得的展流露来。具体的语法如下:

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

参数字传送递

   
在实际上采取中很少有囤积进度并未参数,在正规景况下,需求操作的数据会传递参数给存款和储蓄进度-至少是回顾这个数据的主要音讯。由此大家要求有1个给托管存款和储蓄进程传递参数的不二法门。

    大家看看实例
3-1的C#的代码,那段代码中大家发出二个类有一个章程,每一个方法传递参数的章程略有差别。

  • 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为某2个规定的值,那样保险传递的参数值是非空的。假若大家遗漏这一行,会造成贰个可怜NullReferenceException。那些也认证还有其余因素隐藏在更换中-SQL
Server的数据类型和.NET的数据类型是分歧等的,当大家的代码从三个环境迁移到别的3个,会发出类型转换。大家以此实例评释SQL
Server中部分能够为空的体系而在.NET对应的种类是不能够为空。

返回值

   
托管存款和储蓄进度能够再次来到.NET函数的重回值。不过,当声可瑞康(Karicare)个托管存储进程时,你不须要钦赐再次回到的体系(那一个和自定义函数分歧,自定义函数是内需申明重临值的品类)。因而,那必要在.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>
是CL凯雷德的宣示方法时的数据类型名称, 方法名<Method Name>
是CL讴歌MDX方法的名号。其它,函数名<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参数。

   
到最近停止,大家看了最简便易行的用户自定义函数,可是那里都藏匿了用户自定义函数的扑朔迷离,用户自定义函数有很多概念存款和储蓄进程是不关乎的。

· 数据访问

   
这几个概念是指函数是或不是访问进度Neto管提供者。要是函数没有访问进度内托管提供者,优化器就不会为经过内托管提供者开端化。尽管存款和储蓄进程请求数据访问CL牧马人架构会自动伊始化进度Neto管提供者。

· 系统数据访问

   
假使函数访问的是用户数量而不是系统数据,优化器能够在布局WAITFOCRUISER查询时生成。在这么些实例中,执行函数能够被贰个通报事件平复而不须要向系统数据一致必要进入额外国资本源。

· 精度

    假设一个函数是标准再次来到的,它不会动用浮点指针算法并且不会有舍入错误。

· 确定性

   
一个斐然的函数再次回到值和输入参数是平等的-不考虑变量因素,比如当前多年来和时间。比如3个函数重回的是二个数字的相加是备受关注,3个函数重返当前的年月是不肯定。

· 外部访问

    函数是还是不是访问数据库的外部财富,比如系统的文件系统或注册表。

   
因为优化器这些概念是非常重庆大学的,而且在目录中可见采用函数也是基于那个概念。可以用于索引的函数必须是:

  1. 总之-在差别的时间点,1个一定行的目录应该是常量,那是必须的-不然索引页的物理构造是无用的。
  2. 精确性-若是三个函数的重回值存在舍入错误,那个函数不容许是掌握的。
  3. 无数据访问-函数的输入参数不是唯一决定输出的,由此这不明显函数。
  4. 无外部访问-同数据访问同一,别的因素也会潜移默化函数的明朗。

   
对于TSQL函数,数据库引擎能够依照调用内部函数鲜明这几个要素(比如:NEWID()是三个非显明性的函数同时会使调用它的函数也是非鲜明)。

   
可是,在CL奥德赛类库中内部函数量是不行伟大的,由此,需求数据库引擎或局地“一级验证器”来控制函数是还是不是是明确性的是十分勤奋的。所以,对于CL昂Cora函数,能够通过System.Data.Sql.SqlFunctionAttribute来钦定函数的属性。该属性能够根据下表(表表5)举办安插。

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

表5 SqlFunctionAttribute 属性列表

   
数据库引擎可以规定函数是或不是访问了经过Neto管提供者,而且验证是还是不是真实的匹配在性质中宣称的值。然而,至于其余性质,数据库让你来计划,由此你或者会写三个将协调证明为举世瞩目标函数,但这在骨子里时是格外的。将IsDeterministic的习性设定为真(true),那么,你能够相对确信函数是显著函数,不然该函数恐怕会使索引页构成无效。

   
分别用C#和VB.NET展现了利用SqlFunction函数的品质来标记该函数为泾渭显著的。

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

实例 4 – 用C#宣示3个函数为泾渭显然

<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函数的性质是可选的,如有那特本性遗漏,能够选择暗中认可值。省略是被允许的,所以能够不要求修改的代码就同意重用大批量早就存在的CL帕杰罗代码。

结论

   
在那篇小说中大家讲课了支撑内嵌托管代码的数据库应用程序的着力架构,而且介绍了二种托管代码的抒发格局——托管存款和储蓄进程和托管函数。

    通过CL奥德赛与SQL
Server引擎的咬合,使Yukon数据库有更为有力的遵守,我们能够通过面向对象的语言C#,
VB.NET, Visual C++, Visual
J#等等与.NET包容的言语开发存款和储蓄进度(大家竟然能够用PHP和汇编来写),那样大家得以经过面向对象的章程来支付数据库应用程序,那比之前T-SQL面向进程的言语有更大的优势,并且开发环境也变化为在Microsoft
Visual Studio .NET
下开发,那提供了进一步惠及,火速和便捷地缓解复杂的商业贸易案例的招数。

   
大家同时要留意,在数据库引擎和CLLX570的涉嫌中,数据库引擎占主导地位,控制内部存款和储蓄器的分红和响应客户端的呼吁。CLCRUISER为Yukon提供了拜访系统和网络财富的组件,使大家得以方便的调用.NET
Framework提供的大气类库(FCL),同时,CL奔驰G级组件也得以经过进度Neto管提供者访问数据库。

    在辽阳地点,Yukon既有依照用户的SQL
Server的平安形式,也有CLRubicon基于权力的广元情势。CAS给咱们提供了那1个好的粒度来控制CL牧马人代码的黑河,也给DBA越来越多的手段来控制CLHaval对“外部”的拜访。

   
Yukon要到2006年才会上市,大家那边介绍的只是过多新特征的一局部,在微软的MSDN中网站已经有不少文章展开了介绍,大家能够窥见Yukon还提供了成都百货上千那些实用的新职能。

相关文章