本发明要求下列专利申请的优先权:2003年10月24日提交的美国专利申请号10/693,574(代理案卷号MSFT-2847),标题为“SYSTEMS AND METHODS FOREXTENSIONS AND INHEITANCE FOR UNITS OF INFORMATIONMANAGEABLE BY A HARDWARE/SOFTWARE INTERFACE SYSTEM(用于可由硬件/软件接口***管理的信息单元的扩展和继承的***和方法)”;2003年8月21日提交的美国专利申请号10/646,580(代理案卷号MSFT-2735),标题为“SYSTEMSAND METHODS FOR DATA MODELING IN AN ITEM-BASED STORAGEPLATFORM(在基于项目的存储平台中用于数据建模的***和方法)”;以及2003年8月21日提交的国际申请号PCT/US 03/26144(代理案卷号MSFT-2779),标题为“SYSTEM AND METHODS FOR DATA MODELING IN AN ITEM-BASEDSTORAGE PLATFORM(在基于项目的存储平台中用于数据建模的***和方法)”;通过引用将它们的内容包括在此。
本申请在主题上与在下面一般指定的申请中所揭示的发明相关,通过引用将它们的内容整体包括在本发明中(并且为了方便部分地概述于此):2003年8月21日提交的美国专利申请号10/647,058(代理案卷号MSFT-1748),标题为“SYSTEMSAND METHODS FOR REPRESENTING UNITS OF INFORMATIONMANAGEABLE BY A HARDWARE/SOFTWARE INTERFACE SYSTEM BUTINDEPENDENT OF PHYSICAL REPRESENTATION(用于表示可由硬件/软件接口***管理的信息单元但独立于物理表示的***和方法)”;2003年8月21日提交的美国专利申请号10/646,941(代理案卷号MSFT-1749),标题为“SYSTEMS ANDMETHODS FOR SEPARATING UNITS OF INFORMATION MANAGEABLE BY AHARDWARE/SOFTWARE INTERFACE SYSTEM FROM THEIR PHYSICALORGANIZATION(用于按照它们的物理组织分离可由硬件/软件接口***管理的信息单元的***和方法)”;2003年8月21日提交的美国专利申请号10/646,940(代理案卷号MSFT-1750),标题为“SYSTEMS AND METHODS FOR THEIMPLEMENTATION OF A BASE SCHEMA FOR ORGANIZING FOR UNITS OFINFORMATION MANAGEABLE BY A HARDWARE/SOFTWARE INTERFACESYSTEM(用于实现组织可由硬件/软件接口***管理的信息单元的基模式的***和方法)”;2003年8月21日提交的美国专利申请号10/646,632(代理案卷号MSFT-1751),标题为“SYSTEMS AND METHODS FOR THE IMPLEMATION OF ACORE SCHEMA FOR PROVIDING A TOP-LEVEL STRUCTURE FORORGANIZING UNITS OF INFORMATION MANAGEABLE BY AHARDWARE/SOFTWARE INTERFACE SYSTEM(用于实现为组织可由硬件/软件接口***管理的信息单元提供顶层结构的核心模式的***和方法)”;2003年8月21日提交的美国专利申请号10/646,645(代理案卷号MSFT-1752),标题为“SYSTEMSAND METHODS FOR REPRESENTING RELATIONSHIPS BETWEEN UNITS OFINFORMATION MANAGEABLE BY A HARDWARE/SOFTWARE INTERFACESYSTEM(用于表示可由硬件/软件接口***管理的信息单元之间关系的***和方法)”;2003年8月21日提交的美国专利申请号10/646,575(代理案卷号MSFT-2733),标题为“SYSTEMS AND METHODS FOR INTERFACING APPLICATIONPROGRAMS WITH AN ITEM-BASED STORAGE PLATFORM(用于使应用程序接口基于项目的存储平台的***和方法)”;2003年8月21日提交的美国专利申请号10/646,646(代理案卷号MSFT-2734),标题为“STORAGE PLATFORM FORORGANIZING,SEARCHING,AND SHARING DATA(用于组织、搜索和共享数据的存储平台)”;2003年8月21日提交的美国专利申请号10/692,779(代理案卷号MSFT-2829),标题为“SYSTEMS AND METHODS FOR THE IMPLEMENTATIONOF A DIGITAL IMAGES SCHEMA FOR ORGANIZING UNITS OFINFORMATION MANAGEABLE BY A HARDWARE/SOFTWARE INTERFACESYSTEM(用于实现组织可由硬件/软件接口***管理的信息单元的数字图像模式的***和方法)”;2003年8月21日提交的美国专利申请号10/692,515(代理案卷号MSFT-2844),标题为“SYSTEMS AND METHODS FOR PROVIDINGSYNCHRONIZATION SERVICES FOR UNITS OF INFORMATIONMANAGEABLE BY A HARDWARE/SOFTWARE INTERFACE SYSTEM(用于为可由硬件/软件接口***管理的信息单元提供同步服务的***和方法)”;与本申请同一天提交的美国专利申请号10/692,508(代理案卷号MSFT-2845),标题为“SYSTEMS AND METHODS FOR PROVIDING RELATIONAL ANDHIERARCHICAL SYNCHRONIZATION SERVICES FOR UNITS OFINFORMATION MANAGEABLE BY A HARDWARE/SOFTWARE INTERFACESYSTEM(用于为可由硬件/软件接口***管理的信息单元提供有关系的和分层的同步服务的***和方法)”;以及2003年10月24日提交的美国专利申请号10/693,362(代理案卷号MSFT-2846),标题为“SYSTEMS AND METHODS FOR THEIMPLEMENTATION OF A SYNCHRONIZATION SCHEMAS FOR UNITS OFINFORMATION MANAGEABLE BY A HARDWARE/SOFTWARE INTERFACESYSTEM(用于实现可由硬件/软件接口***管理的信息单元的同步模式的***和方法)”。
详细描述
目录
I.引言…………………………………………………………………14
A.示例性计算环境…………………………………………………14
B.传统的基于文件的存储…………………………………………17
II.用于组织、搜索和共享数据的WINFS存储平台…………………18
C.词汇表……………………………………………………………18
D.存储平台综述……………………………………………………18
E.数据模型…………………………………………………………20
1.项目……………………………………………………………21
2.项目标识………………………………………………………23
3.项目文件夹和类别……………………………………………24
4.模式……………………………………………………………26
a)基础模式……………………………………………………26
b)核心模式……………………………………………………26
5.关系……………………………………………………………28
a)关系声明……………………………………………………28
b)持有关系……………………………………………………29
c)嵌入关系……………………………………………………30
d)引用关系……………………………………………………31
e)规则和约束…………………………………………………32
f)关系的排序…………………………………………………32
6.可扩展性………………………………………………………36
a)项目扩展……………………………………………………37
b)扩展NestedElement类型 …………………………………40
F.数据库引擎………………………………………………………41
1.使用UDT的数据存储实现 ……………………………………42
2.项目映射………………………………………………………42
3.扩展映射………………………………………………………43
4.嵌套元素映射…………………………………………………44
5.对象身份………………………………………………………44
6.SQL对象命名 …………………………………………………44
7.列命名…………………………………………………………45
8.搜索视图………………………………………………………45
a)项目…………………………………………………………46
(1)主项目搜索视图……………………………………………46
(2)分类型的项目搜索视图……………………………………46
b)项目扩展 ………………………………………………………47
(1)主扩展搜索视图……………………………………………47
(2)分类型的扩展搜索视图……………………………………47
c)嵌套的元素 ……………………………………………………48
d)关系 ……………………………………………………………48
(1)主关系搜索视图……………………………………………48
(2)关系实例搜索视图…………………………………………48
e) …………………………………………………………………49
9.更新 ………………………………………………………………49
10.改变跟踪及墓碑…………………………………………………50
a)改变跟踪 ………………………………………………………50
(1)“主”搜索视图中的改变跟踪……………………………50
(2)“分类型的”搜索视图中的改变跟踪……………………51
b)墓碑 ……………………………………………………………52
(1)项目墓碑 ……………………………………………………52
(2)扩展墓碑 ……………………………………………………52
(3)关系墓碑 ……………………………………………………53
(4)墓碑清除 ……………………………………………………53
11.助手API和函 ……………………………………………………54
a)函数[System.Storage].GetItem ……………………………54
b)函数[System.Storage].GetExtension………………………54
c)函数[System.Storage].GetRelationship …………………54
12.元数据……………………………………………………………54
a)模式元数据 ……………………………………………………54
b)实例元数据 ……………………………………………………54
G.安全性 ………………………………………………………………54
H.通知和改变跟踪 ……………………………………………………55
I.同步 …………………………………………………………………55
1.存储平台到存储平台的同步 ……………………………………56
a)同步(Sync)控制应用程序 ……………………………………56
b)模式注释 ………………………………………………………57
c)同步配置 ………………………………………………………58
(1)共同体文件夹—映射………………………………………58
(2)概况…………………………………………………………59
(3)时间表 …………………………………………………60
d)冲突处理……………………………………………………60
(1)冲突检测 ………………………………………………60
(a)基于知识的冲突……………………………………60
(b)基于约束的冲突……………………………………61
(2)冲突处理 ………………………………………………61
(a)自动冲突分解………………………………………61
(b)冲突日志记录………………………………………62
(c)冲突审查和分解……………………………………62
(d)复制品的会聚性及冲突分解的传播………………62
2.对非存储平台数据存储的同步………………………………63
a)同步服务……………………………………………………63
(1)改变枚举 ………………………………………………63
(2)改变应用 ………………………………………………64
(3)冲突分解 ………………………………………………65
b)适配器实现…………………………………………………65
3.安全性…………………………………………………………65
4.可管理性………………………………………………………66
J.传统文件互操作性………………………………………………66
K.存储平台API ……………………………………………………66
III.扩展和继承………………………………………………………71
A.类型***…………………………………………………………72
B.类型家族…………………………………………………………77
1.嵌套元素类型…………………………………………………77
2.项目类型………………………………………………………77
3.关系类型………………………………………………………78
a)关系语义……………………………………………………79
b)关系规则和约束……………………………………………80
4.扩展类型………………………………………………………81
C.增强的功能………………………………………………………82
1.继承……………………………………………………………82
2.扩展……………………………………………………………83
IV.结论 ………………………………………………………………84
I.引言
本发明的主题用细节来描述,以满足法定的要求。然而,该描述本身不试图限制本专利的范围。相反,本发明者设想,要求保护的主题也能以其它方式实施,以结合其它当前和未来的技术包括类似于本说明描述的不同的步骤或步骤的组合。此外,虽然术语“步骤”在这里可用于意味着所采用的方法的不同元素,然而该术语不能被解释为在这里揭示的各步骤之间隐含特定的次序,除非明确地描述了各个步骤的次序。
A.示例性计算环境
本发明的许多实施例可在计算机上执行。图1和下面讨论旨在提供其中实现本发明的合适计算环境的简要描述。虽然不是必需,本发明的诸方面能以诸如由如客户工作站或服务器的计算机上执行的程序模块的计算机可执行指令的一般上下文中描述。一般而言,程序模块包括例程、程序、对象、组件、数据结构等,它们执行特定任务或实现特定抽象数据类型。此外,本发明可用其它计算机***配置实现,包括手持设备、多处理器***、基于微处理器的***或可编程消费者电子设备、网络PC、小型机、大型机等。本发明还能在分布式计算环境中实现,其中任务由通过通信网络链接的远程处理设备完成。在分布式计算环境中,程序模块能位于本地或远程存储器存储设备中。
如图1所示,示例性通用计算***包括传统的个人计算机20等,它包括处理单元21、***存储器22和将包括***存储器的各种***组件耦合到处理单元21的***总线23。***总线23可以是若干种总线结构的任一种,包括存储总线或存储控制器、***总线、以及使用各种总线体系结构的任一种的局部总线。***存储器包括只读存储器(ROM)24和随机访问存储器(RAM)25。基本输入/输出***26(BIOS)包含如在启动时帮助在个人计算机20的诸元件之间传输信息的基本例程,存储在ROM 24中。个人计算机20还可包括读写硬盘(未示出)的硬盘驱动器27、读写可移动磁盘29的磁盘驱动器28、读写如CDROM或其它光介质的可移动光盘29的光盘驱动器30。硬盘驱动器27、磁盘驱动器28和光盘驱动器30分别通过硬盘驱动器接口32、磁盘驱动器接口33和光盘驱动器接口34连接***总线23。驱动器及其相关的计算机可读介质为个人计算机20提供计算机可读指令、数据结构、程序模块和其它数据的非易失存储。虽然这里描述的示例性环境采用硬盘、可移动磁盘29和可移动光盘31,本领域技术人员理解,在示例性操作环境中也能使用可存储能由计算机访问的数据的其它类型计算机可读介质,如盒式磁带、闪存卡、数字视频盘、Bernoulli盒式磁带、随机存取存储器(RAM)、只读存储器(ROM)等。类似地,示例环境还可包括许多类型的监视设备,如热敏和安全或火警***,及其它信息来源。
若干程序模块能存储在硬盘、磁盘29、光盘31、ROM 24或RAM 25中,包括操作***35、一个或多个应用程序36、其它程序模块37和程序数据38。用户能通过如键盘40和定位设备42等输入设备将命令和信息输入到个人计算机20。其它输入设备(未示出)可包括麦克风、操纵杆、游戏垫、圆盘式卫星天线、扫描仪等。这里和其它输入设备常通过耦合到***总线的串行接口46连接到处理单元21,但也可通过其它接口连接,如并行口、游戏口或通用串行总线(USB)。监视器47或其它类型的显示设备也通过如视频适配器48的接口连接到***总线23。除监视器47以外,个人计算机通常包括如话筒和打印机等其它***输出设备(未示出)。图1的示例***还包括主适配器55、小型计算机***接口(SCSI)总线56和连接到SCSI总线的外部存储设备62。
个人计算机20可使用到如远程计算机49的一个或多个远程计算机的逻辑连接在网络环境中操作。远程计算机49可以是另一台个人计算机、服务器、路由器、网络PC、对等设备或其它公共网络节点,并通常包括以上对个人计算机20描述的许多或所有元件,虽然在图1中只示出存储器存储设备50。图1中画出的逻辑连接包括局域网(LAN)51和广域网(WAN)52。那样的网络环境常见于办公室、企业范围计算机网络、内联网和因特网。
在LAN网络环境中使用时,个人计算机20通过网络接口或适配器53连接到LAN51。在WAN网络环境中使用时,个人计算机20通常包括调制解调器54或用于通过如因特网等广域网52建立通信的其它装置。内置或外接的调制解调器54通过串行端口接口46连接***总线23。在网络环境中,相对个人计算机20画出的程序模块或其部分可存储在远程存储器存储设备中。可以理解,示出的网络连接是示例性的,可使用在计算机之间建立通信链路的其它装置。
如图2的框图所示,计算机***200能被粗略地分成三个组件组:硬件组件202、硬件/软件接口***组件204、以及应用程序组件206(在这里某些上下文中也称为“用户组件”或“软件组件”)。
回到图1,在计算机***的各种实施例中,硬件组件202可包括中央处理单元(CPU)21、存储器(ROM 24和RAM 25)、基本输入/输出***(BIOS)26、以及各种输入/输出(I/O)设备,如键盘40、鼠标42、监视器47、和/或打印机(未示出)等。硬件组件202包括计算机***200的基本物理基础结构。
应用程序组件206包括各种软件程序,包括但不限于编译器、数据库***、文件处理程序、商业程序、视频游戏等。应用程序提供计算机资源用于为各种用户(机器、其它计算机***和/或最终用户)解决问题、提供解决方案和处理数据的手段。
硬件/软件接口***组件204包括(在某些实施例中可以仅包括)操作***,在大多数情况后者本身包括外壳和内核。“操作***”(OS)是担当在应用程序和计算机硬件之间的中介的特殊程序。硬件/软件接口***组件204还可包括虚拟机管理器(VMM)、公用语言运行库(CLR)或其功能等效物、Java虚拟机(JVM)或其功能等效物、或在计算机***中的操作***处或操作***外的其它软件组件。硬件/软件接口***的目的是提供用户能在其中执行应用程序的环境。任何硬件/软件接口***的目标是使计算机***便于使用,以及以有效的方式利用计算机硬件。
硬件/软件接口***一般在启动时被加载到计算机***,并随后管理在计算机***中所有应用程序。应用程序通过经由应用程序接口(API)请求服务来与硬件/软件接口***交互。某些应用程序使最终用户能通过如命令语言或图形用户界面(GUI)与硬件/软件接口***交互。
硬件/软件接口***传统上执行应用程序的各种服务。在多个程序同时运行的多任务硬件/软件接口***中,硬件/软件接口***确定哪些应用程序以什么次序运行,以及在切换到另一应用程序之前以供轮流对每个应用程允许多少时间。硬件/软件接口***还管理在多个应用程序之间内部存储器的共享,并处理来往于如硬盘、打印机和拨号端口等附加的硬件设备的输入和输出。硬件/软件接口***还将有关操作状态和可能发生的任何错误的消息发送到每个应用程序(在某些情况下到最终用户)。硬件/软件接口***也能下传(offload)批处理作业(如打印)的管理,使得启动的应用程序能摆脱此工作并重新开始其它处理和/或操作。在能提供并行处理的计算机上,硬件/软件接口***还管理划分程序,使得它同时在多个处理器上运行。
硬件/软件接口***外壳(这里简称“外壳”)是到硬件/软件接口***的交互式最终用户界面。(外壳也称为“命令解释器”,或在一个操作***中称为“操作***外壳”)。外壳是可直接由应用程序和/或最终用户访问的硬件/软件接口***的外层。与外壳相反,内核是直接与硬件组件交互的硬件/软件接口***的最内层。
虽然可构想本发明的许多实施例尤其适用于计算机化的***,然而在本说明中不意味着将本发明限于那些实施例。相反,这里使用的术语“计算机***”旨在包括能存储和处理信息和/或能使用存储的信息控制设备本身的行为或执行的任何和所有设备,而不管那些设备本质上是否为电子的、机械的、逻辑的、或虚拟的。
B.传统的基于文件的存储
在当今大多数计算机***中,“文件”是可存储信息的单元,它可包括硬件/软件接口***和应用程序、数据集等。在所有现代硬件/软件接口***中(Windows,Unix,Linux,MacOS,虚拟机***等),文件是能由硬件/软件接口***处理的基本的分立(可存储和可检索)信息单元。文件组通常被组织成“文件夹”。在MicrosoftWindows、Macintosh OS和其它硬件/软件接口***中,文件夹是能作为单个信息单元被检索、移动和处理的文件的集合。这些文件夹进而被组织成称为“目录”(在后面详细讨论)的基于树形的分层结构排列。在如Dos、z/OS和大多数基于Unix的操作***的其它硬件/软件接口***中,术语“目录”和/或“文件夹”是可交替使用的,早期的Apple计算机***(如Apple IIe)使用术语“类别”来代替目录;然而在这里使用时所有这些术语被看成是同义语并可交替使用,并旨在还包括对分层信息存储结构及其文件夹和文件组件的所有其它等价术语的引用。
传统上,目录(又名文件夹的目录)是基于树形的分层结构,其中文件被组合成文件夹,文件夹进而按构成目录树的相对节点位置排列。例如,如图2B所示,基于DOS的文件***的基本文件夹(或“根目录”)212可包括多个文件夹214,其每一个可以还包括另外的文件夹(如特定文件夹的“子文件夹”)216,而这些的每一个又包括另外的文件夹218,直到无限。这些文件夹的每一个可具有一个或多个文件220,虽然在硬件/软件接口***级上,文件夹中的各个文件除了它们在树形分层结构中的位置外没有什么共同点。不奇怪,将文件组织到文件分层结构的方法间接地反映了用于存储这些文件的典型存储介质(如硬盘、软盘、CD-ROM等)的物理组织。
除上述以外,每个文件夹是对其子文件夹和其目录的容器—即,每个文件夹拥有其子文件夹和文件。例如,当文件夹被硬件/软件接口***删除时,该文件夹的子文件夹和文件也被删除(在每个子文件夹的情况下还递归地包括它自己的子文件夹和文件)。同样,每个文件一般只由一个文件夹拥有,并且虽然文件能被拷贝且副本位于不同的文件夹,文件的副本本身是不同且独立单元,它与原始文件无直接连接(如对原始文件的改变在硬件/软件接口***级上不反映到副本文件)。因此在这方面,文件和文件夹在本质上是“物理的”,因为文件夹类似于物理容器来处理,而文件作为这些容器中不同且独立的物理元素来处理。
II.用于组织、搜索和共享数据的WINFS存储平台
本发明结合通过引用结合于此的发明针对用于组织、搜索和共享数据的存储平台。本发明的存储平台扩展和拓宽了数据平台,超越上文讨论的文件***及数据库***,并被设计成存储所有类型的数据,包括称为项目的新格式的数据。
C.词汇表
在这里及在权利要求书中使用的术语有下列意义:
·“项目”是能存储硬件/软件接口***可访问的信息的单元,不象简单文件,它是具有由硬件/软件接口***外壳展现给最终用户的所有对象共同支持的基本属性集的对象。项目还具对所有项目类型共同支持的属性和关系,包括允许引入新属性和关系的特征(在下面详细讨论)。
·“操作***”(OS)是扮作应用程序和计算机硬件之间的中介的特殊程序。在大多数情况下,操作***包括外壳和内核。
·“硬件/软件接口***”是软件、或硬件及软件的组合,它起着在计算机***的底层硬件组件和在计算机***上执行的应用程序之间的接口的作用。硬件/软件接口***通常包括(在某些实施例中只包括)操作***。硬件/软件接口***还能包括虚拟机管理器(VMM)、公用语言运行库(CLR)或其功能等效物,Java虚拟机(JVM)或其功能等效物、或在计算机***的操作***处或除操作***外的其它软件组件。硬件/软件接口***的目的是提供用户能执行应用程序的环境。任何硬件/软件接口***的目标是使计算机***便于使用,并以有效方式利用计算机硬件。
D.存储平台综述
参考图3,存储平台300包括在数据库引擎314上实现的数据存储302。在一个实施例中,数据库引擎包括带有对象关系扩展的关系型数据库引擎。在一个实施例中,关系型数据库引擎314包括Microsoft SQL Server关系型数据库引擎。数据存储302实现支持数据的组织、搜索、共享、同步和安全的数据模型304。在如模式340等模式中描述特定的数据类型,并且存储平台300提供用于采用这些模式并用于扩展这些模式的工具346,这在后面详述。
在数据存储302中实现的改变跟踪机制306提供跟踪数据存储的改变的能力。数据存储302还提供安全能力308和升级/降级能力310,均在后文详述。数据存储302还提供一组应用程序接口312,以向利用该存储平台的其它存储平台组件和应用程序(如应用程序350a,350b和350c)展现数据存储302的能力。本发明的存储平台还包括应用程序接口(API)322,使如应用程序350a,350b,和350c等应用程序能访问存储平台的所有上述功能并能访问在模式中描述的数据。应用程序能结合如OLE OB API 324和Microsoft Windows Win 32 API 326等其它API来使用存储平台API 322。
本发明的存储平台300能向应用程序提供各种服务,包括便于在用户或***之间共享数据的同步服务330。例如,同步服务330允许与具有与数据存储302相同格式的其它数据存储340的互操作,并访问具有其它格式的数据存储342。存储平台300还提供允许数据存储302与如Windows NTFS文件***318等现有文件***的互操作的文件***能力。在至少某些实施例中,存储平台320还能向应用程序提供另外的能力,以允许对数据起作用并允许与其它***的交互。这些能力可体现在如Info Agent服务334和通知服务332等附加服务328的形式中,以及体现在其它实用程序336的形式中。
在至少某些实施例中,存储平台以计算机***的硬件/软件接口***来实施,或形成其完整的一部分。例如而非限制,本发明的存储平台能用操作***、虚拟机管理器(VMM)、公用语言运行库(CLR)或其功能等效物、或Java虚拟机(JVM)或其功能等效物来实施,或形成其完整的一部分。通过其公用的存储基础和模式化的数据,本发明的存储平台使消费者、知识工人和企业能够更有效地进行应用程序的开发。它提供了丰富和可扩展的编程表面区域,不仅可得到内含在其数据模型中的能力,还能包括和扩展现有文件***和数据库访问方法。
在上述描述中及在各种附图中,本发明的存储平台300可称作“WinFs”。然而使用此名字指存储平台仅是为了描述方便,并不试图作出如此限制。
E.数据模型
本发明的存储平台300的数据存储302实现一种数据模型,它支持对驻留在数据存储中的数据的组织、搜索、共享、同步和安全。在本发明的数据模型中,“项目”是存储信息的基本单元。该数据模型提供一种机制,用于声明项目和项目的扩展、用于建立在项目之间的关系、以及用于将项目组织到项目文件夹和类别中,下面将更充分描述。
该数据模型依赖于两个原语机制:类型和关系。类型是提供支配类型的实例的形式的格式的结构。格式被表达成属性的有序组。属性是给定类型的值或一组值的名字。例如,USPostalAddress(美国邮政地址)类型具有属性Street(街道)、City(城市)、Zip(邮编)、State(州),其中Street、City和State是String类型,而Zip是Int32类型。Street可以是多值(即一组值),允许地址对Street属性具有一个以上值。***定义能在其它类型构造中使用的某些原语类型,包括String、Binary、Boolean、Int16、Int32、Int64、Single、Double、Byte、DateTime、Decimal和GUID。可使用任何原语类型(带有下面注释的某些限制)或任何构造的类型来定义类型的属性。例如,Location(位置)类型可定义具有属性Coordinate(座标)和Address(地址),其中Address属性是上述类型USPostalAddress。属性也可以是必需的或可任选的。
关系可被声明并表示两个类型的实例集之间的映射。例如,可以有在Person(个人)类型和Location类型之间声明的关系,称为LivesAt(生活在),它确定什么人生活在什么位置。关系具有名和两个端点,即源端点和目标端点。关系也可具有属性的有序集。源端点及目标端点均具有名和类型。例如,LivesAt关系具有称为类型Person的Occupant(居民)的源和称为类型Location的Dwelling(住房)的目标,且此外具有属性StartDate(起始日期)和EndDate(终止日期),表示该居民生活在该住房的时间段。注意,随时间推移,个人能生活在多个住房,且住房可有多个居民,所以放置StartDate和EndDate信息的最可能的地方是在关系本身处。
关系定义了在由作为端点类型给出的类型约束的实例之间的映射。例如LivesAt关系不能是其中Automobile(汽车)是Occupant(居民)的关系,因为Automobile不是Person。
数据模型允许定义类型间的子类型—超类型关系。也称为基本类型关系的子类型—超类系型关系以如下方式定义,若类型A是类型B的基本类型,则必须是B的每个实例也是A的实例的情况。另一种表达的方法是符合B的每个实例必须符合A。例如,若A具有String类型的属性Name(名字),而B具有Int16类型的属性Age(年龄),则得出,B的任何实例必须兼有Name和Age。类型的分层结构可被设想成带有在根上的单个超类型的树。根的分枝提供第一级子类型,该级分枝提供第二级子类型,如此等等,直到本身不再具有任何子类型的叶端(leaf-most)子类型。树不限于统一深度,但不能包含任何回路。给定的类型可具有零个或许多子类型和零个或一个超类型。给定实例可最多符合一个类型以及该类型的超类型。换言之,对树中任一级处给定的实例,该实例最多可符合该级上的一个子类型。如果一类型的实例必须也是该类型的子类型的实例,则该类型可说成是抽象。
1.项目
项目是可存储的信息的单元,不象简单的文件,它是具有由存储平台向最终用户或应用程序展现的所有对象共同支持的基本属性集的对象。项目也具有所有项目类型共同支持的属性和关系,包括如下所述允许引入新的属性和关系的特征。
项目是公用操作的对象,如拷贝、删除、移动、打开、打印、备份、恢复、复制等。项目是能被存储和检索的单元,且由存储平台处理的可存储信息的所有形式作为项目、项目的属性、或项目之间的关系存在,其每个在下面更详细讨论。
项目旨在表示现实的且容易理解的数据单元,如联系人(Contacts)、人(People)、服务(Services)、位置(Locations)、(各种类型的)文档(Documents)等。图5A是示出项目的结构的框图。该项目的不合格的名是“Location”。该项目的合格名是“Core.Location”,它表明,此项目结构被定义成Core(核心)模式中的特定类型的项目(Core模式在下面详细讨论)。
Location项目具有多个属性,包括EAddress(电子邮件地址)、MetropolitanRegion(都市地区)、Neighborhood(街坊)、和PostalAddress(邮政地址)。每个项目的特定类型属性紧跟属性名地表示,并用冒号(“:”)与属性名分开。在类型名的右边,对该属性类型允许的值的数量在方括号(“[]”)之间表示,其中冒号(“:”)右边的星号(“*”)表示未规定的和/或无限制的数量(“许多”)。冒号右边的“1”表明最多一个值。冒号左边的零(“0”)表明该属性是可任选的(可以完全没有值)。冒号左边的“1”表明必须至少有一个值(该属性是必须的)。Neighborhood和MetropolitanRegin均是“nvarchar”类型(或等效类型),它是预定义的数据类型或“简单类型”(这里用缺少大写来表示)。然而EAddress和PostalAddress分别是类型EAddress和PostalAddress的已定义类型或“复杂类型”(这里用大写标记)的属性。复杂类型是从一个或多个简单数据类型和/或从其它复杂类型导出的类型。一个项目的属性的复杂类型还构成”嵌套元素“,因为复杂类型的细节嵌套入直接项目中以定义其属性,而属于这些复杂类型的信息用具有这些属性的项目来维持(在该项目的边界内,如后面讨论)。类型的这些概念是众知的,且容易被本专业技术人员理解。
图5B是示出复杂属性类型PostalAddress和EAddress的框图。PostalAddress属性类型定义,属性类型PostalAddress的项目可期望有零个或一个City(城市)值、零个或一个Country Code(国家代码)值、零个或一个MailStop(国家代码)值、和任何数量(零到许多)PostalAddress类型等等。以此方式,定义了一项目中的特定属性的数据的形状。EAddress属性类型如所示类似地定义。虽然这里在本申请中可任选地使用,表示在Location项目中复杂类型的另一方法是用其中列出的每个复杂类型的各个属性得出该项目。图5C是示出Location项目的框图,在其中进一步描述其复杂类型。然而应该理解,在此图5C中Location项目的另一种表示恰是对图5A中示出的同一个项目。本发明的存储平台还允许子分类(subtyping),从而一个属性类能是另一个的子类型(其中一个属性类继承另一个父属性类型的属性)。
类似于但不同于属性及它们的属性类型,项目继承性地表示其自己的Item(项目)类型,它也是子分类的主题。换言之,本发明的若干实施例中的存储平台允许一个项目是另一个项目的子类型(从而一个项目继承另一个父项目的属性)。此外,对本发明的各种实施例,每个项目是“Item”项目类型的子类型,后者是在基础模式中找到的第一和基本的项目类型(基础模式也在后面详细讨论)。图6A示出一项目(在此实例中为Location项目)为在基础模式中找到的Item项目类型的子类型。在此图中,箭头表示Location项目(如所有其它项目)是Item项目类型的子类型。作为从中导出所有其它项目的基本项目的Item项目类型具有若干如ItemId的重要属性和各种时间标记,从而定义了操作***中所有项目的标准属性。在本图中,Item项目类型的这些属性被Location所继承,并从而成为Location的属性。
表示从Item项目类型继承的Location项目中属性的另一种方法是用来自其中列出的父项目的每个属性类型的各个属性得出Location。图6B是示出Location项目的框图,其中除了其直接属性外描述其继承的类型。应注意和理解,此项目是图5A中示出的同一项目,虽然在本图中,Location用所有其属性示出,包括直接属性(在本图及图5A中示出)和继承属性(在本图中示出但未在图5A中示出)(而在图5A中,通过用箭头示出Location项目是Item项目类型的子类型来引用这些属性)。
项目是独立的对象,因而若删除一项目,也删除项目的所有直接和继承的属性。类似地,当检索一项目时,检索的是该项目及其所有直接和继承的属性(包括属于其复杂属性类型的信息)。本发明的某些实施例可使人们能在检索特定项目时请求属性的子集;然而对许多那样的实施例默认的是在检索时提供具有所有其直接和继承的属性的项目。此外,项目的属性也能通过添加新的属性到该项目的类型的现有属性而加以扩展。这些“扩展”其后是该项目的真实属性,且该项目类型的子类型可自动地包括扩展属性。
项目的“边界”由其属性(包括复杂属性类型、扩展等)来表示。项目的边界也表示在项目上执行的操作的限制,包括拷贝、删除、移动、创建等。例如在本发明的若干实施例中,当拷贝一项目时,在该项目边界之内的所有内容也被拷贝。对每个项目,边界包括下列:
·项目的项目类型,且若该项目是另一项目的子类型(如在所有项目从基础模式的单个项目和项目类型导出的本发明的若干实施例的情况下),是任何适用的子类型信息(即属于父项目类型的信息)。若要拷贝的原始项目是另一项目的子类型,该副本也能是该相同项目的子类型。
·项目的复杂类型属性和扩展(如果有的话)。若原始项目具有复杂类型(原来的或扩展的)的属性,副本也能具有相同的复杂类型。
·在“所有权关系”上的项目的记录,即,本项目(“拥有项目”)拥有什么其它项目(“目录项目”)的项目拥有列表。这特别关系到下面充分讨论的项目文件夹和下面说到的所有项目必须至少属于一个项目文件夹的规则。此外,关于嵌入项目(下列更充分讨论),一个嵌入项目被认为是其中嵌入如拷贝、删除等操作的项目的一部分。
2.项目标识
在全局项目空间中用ItemID唯一地标识项目。Base.Item类型定义了存储该项目身份的类型GUID的字段ItemID。一项目必须在数据存储中准确只有一个身份。
项目引用是包含定位和标识项目的信息的数据结构。在该数据模型中,定义名为ItemReference的抽象类型,从中导出所有项目引用类型。ItemReference(项目引用)类型定义了名为Resolve(解析)的虚拟方法。Resolve方法解析ItemReference并返回一项目。此方法被ItemReference的具体子类型所覆盖,后者实现给定一引用时检索项目的功能。调用Resolve方法作为存储平台API 322的一部分。
ItemIDReference(项目ID引用)是ItemReference的子类型。它定义了Locator(***)和ItemID字段。Locator字段命名(即标识)项目的域。它由能将Locator的值解析到项目域的***解析方法来处理。ItemID字段是ItemID类型。
ItemPathReference(项目路径引用)是定义Locator和Path(路径)字段的ItemReference的特殊化。Locator字段标识一项目域。它由能将Locator的值解析到项目域的***解析方法来处理。Path字段包含以由Locator提供的项目域为根的存储平台名字空间中的(相对)路径。
不能在集合运算中使用此类引用。引用一般必须通过路径解析过程来解析。存储平台API 322的Resolve方法提供此功能。
上面讨论的引用形式通过图11示出的引用类型分层结构表示。从这些类型继承的另外引用类型能在模式中定义。它们能在关系声明中用作目标字段的类型。
3.项目文件夹和类别
如下面将更充分讨论的,项目组能组织成称为项目文件夹(不要与文件的文件夹混淆)的特殊项目。然而不象大多数文件***,一个项目可属于多个项目文件夹,使得当一个项目在一个项目文件夹中被访问和修订时,此修订的项目随后能直接从另一项目文件夹访问。实质上,虽然对一个项目的访问可从不同的项目文件夹发生,事实上真正访问的是同一个项目。然而,一个项目文件夹不必拥有其所有成员项目,或简单地结合其它文件夹共同拥有项目,使得一个项目文件夹的删除不必要导致项目的删除。然而在本发明的若干实施例中,一个项目必须至少属于一个项目文件夹,使得如果特定项目的唯一文件夹被删除,则对某些实施例,该项目被自动被删除,或在另外实施例中,该项目自动地成为默认项目文件夹的成员(“TrashCan(垃圾箱)”文件夹在概念上类似于在各种基于文件和文件夹的***中使用的类似名字文件夹。)
如下面更充分讨论的,项目也可属于基于共同描述的特征的类别,特征如:(a)项目类型(或类型),(b)特定的直接或继承的属性(或属性),或(c)对应于项目属性的特定值(或值)。例如,包括个人联系人信息的特定属性的项目可自动属于联系人(Contact)类别,具有联系人信息属性的任何项目同样也自动属于此类别。同样,具有“New York City(纽约市)”值的位置属性的任何项目可自动属于纽约市(NewYorkCity)类别。
类别在概念上不同于项目文件夹之处在于,项目文件夹可包括互相无关的项目(即无共同的描述的特征),而在类别中的每个项目具有对该类别描述的共同类型、属性或值(“共同性”),正是这个共同性形成对它与该类别中其它项目或那些项目之间的关系的基础。此外,虽然在特定文件夹中的项目的成员资格基于该项目的任何特定方面不是强制的,然而对某些实施例,具有在分类上与一类别相关的共同性的所有项目在硬件/软件接口***级上可自动地成为该类别的成员。概念上,类别也能看作虚拟项目文件夹,其成员资格基于特定查询(如在数据库的上下文中)的结果,而满足此查询的条件(由类别的共同性确定)的项目应构成该类别的成员资格。
图4示出在项目、项目文件夹和类别之间的结构关系。多个项目402、404、406、408、410、412、414、418和420是各个项目文件夹422、424、426、428和430的成员。某些项目属于一个以上项目文件夹,如项目402属于项目文件夹422和424。某些项目,如项目402、404、406、408、410和412也是一个或多个类别432、434和436的成员,而其它项目,如项目44,416,418和420可以不属于任何类别(虽然这大部分不象在某些实施例中,其中具有任何属性自动暗示类别中的成员资格,因此在那样实施例中为了不是任何类别的成员,项目应完全地无特征)。与文件夹的分层结构相反,类别和项目文件夹均有更像如所示的有向图的结构。在任何情况下,项目、项目文件夹和类别都是项目(尽管是不同的项目类型)。
与文件、文件夹和目录相反,本发明的项目、项目文件夹和类别的特征在本质上不是“物理的”,因为它们不具有物理容器的概念上的等价性,因而项目可存在于一个以上那样的位置。项目存在于一个以上项目文件位置以及被组织成类别的能力提供了在硬件/软件接口级上增强和丰富程度的数据处理及存储结构能力,超越了在本领域中当前可得到的能力。
4.模式
a)基础模式
为了提供创建和使用项目的通用基础,本发明的存储平台的各实施例包括建立用于创建和组织项目及属性的概念性框架的基础(Base)模式。基础模式定义了某些特定类型的项目和属性,以及从中进一步导出子类型的这些特定基本类型的特征。使用此基础模式使程序员能在概念上将项目(及其各自的类型)与属性(及其各自的类型)加以区别。此外,基础模式列出所有项目可拥有的基本属性集,因为所有项目(及其对应的项目类型)是从基础模式的此基本项目(及其对应的项目类型)导出。
如图7所示,对于本发明的若干实施例,基础模式定义三个顶层类型:Item(项目)、Extension(扩展)和PropertyBase(属性基础)。如图所示,通过此基本“Item”项目类型的属性定义了项目类型。相反,顶层属性类型“PropertyBase”没有预定义的属性,仅是一个锚位(anchor),从中导出所有其它属性,并通过它所有导出的属性类型互相联系(共同从单个属性类型导出)。Extension类型属性定义该扩展扩展了哪个项目,并定义将一个扩展与另一个项目相区别的标识,因为一个项目可具有多个扩展。
ItemFolder(项目文件夹)是Item项目类型的子类型,除了从Item继承的属性外,它表征用于建立到其成员(如果有的话)的关系,尽管Identitykey(身份关键字)和Property(属性)均是PropertyBase的子类型。CategoryRef(目录引用)进而是IdentityKey的子类型。
b)核心模式
本发明的存储平台的各种实施例还包括为顶层项目类型结构提供概念框架的核心(Core)模式。图8A是示出核心模式中的项目的框图,而图8B是示出核心模式中属性类型的框图。在带不同扩展名(*.com、*.exe、*.bat、*.sys等)的文件和在基于文件和文件夹***中其它准则之间作出的区分是类似于核心模式的功能。在基于项目的硬件/软件接口***中,核心模式定义了一组核心项目类型,它们直接(按项目类型)或间接地(按项目子类型)将所有项目特征化成基于项目的硬件/软件接口***理解并能以预定或可预计的方式直接处理的一个或多个核心模式项目类型。预定的项目类型反映了在基于项目的硬件/软件接口***中最常用的项目,且因此通过理解这些包括核心模式的预定项目类型的基于项目的硬件/软件接口***获取有效性级别。
在某些实施例中,核心模式是不可扩展的,即,没有另外的类型可直接从基础模式中的项目类型子分类,除非作为核心模式的一部分的特定的预定导出的项目类型。通过禁止对核心模式的扩展(即,通过禁止向核心模式添加新的项目),存储平台托管核心模式项目类型的使用,因为每个后续的项目类型必须是核心模式项目类型的子类型。此结构允许在保持具有一组预定的核心项目类型的益处的同时在定义另外项目类型时有合理程度的灵活性。
参考图8A,对本发明的各种实施例,由核心模式支持的特定项目类型可包括下列的一个或多个:
·Category(类别):此项目类型(及从中导出的子类型)的项目代表在基于项目的硬件/软件接口***中的有效类别。
·Commodity(物品):作为值的可标识事物的项目。
·Device(设备):具有支持信息处理能力的逻辑结构的项目。
·Document(文档):具有不能由基于项目的硬件/软件接口***解释而相反由对应于文档类型的应用程序解释的内容的项目。
·Event(事件):记录环境中某些发生事件的项目。
·Location(位置):代表物理位置(如地理位置)的项目。
·Message(消息):在两个或更多主体(下面定义)之间通信的项目。
·Principal(主体):具有除ItemId之外的至少一个肯定可验证身份(如,个人、组织、组、家庭、作者、服务等的标识)的项目。
·Statement(语句):具有关于环境的特定信息的项目,包括但不限于:政策、预订、凭证等。
类似地参考图8B,由核心模式支持的特定属性类型可包括下列的一个或多个:
·Certificate(证书)(从基础模式中的基本PropertyBase类型导出)
·PrincipalIdentityKey(主体身份关键字)(从基础模式中的IdentityKey类型导出)
·PostalAddress(邮政地址)(从基础模式中Property类型导出)
·RichText(多信息文本)(从基础模式中Property类型导出)
·EAddress(电子邮件地质)(从基础模式中Property类型导出)
·IdentitySecnrityPackage(身份安全包)(从基础模式中Relationship类型导出)
·RoleOccupancy(居民角色)(从基础模式中Relationship类型导出)
·BasicPresence(基础存在)(从基础模式中Relationship类型导出)这些项目和属性按在图8A和图8B中列出的各自属性进一步描述。
5.关系
关系是二元关系,其中一个项目被指定为源,另一个被指定为目标。源项目和目标项目通过关系相联系。源项目一般控制关系的生命周期。即,当源项目被删除,项目之间的关系也被删除。
关系被分类成:包含(Containment)和引用(Reference)关系。包含关系控制目标项目的生命周期,而引用关系不提供任何生命周期管理语义。图12示出关系分类的方式。
包含关系又被分类成持有(Holding)和嵌入(Embedding)关系。当对一个项目的所有持有关系被移除,该项目被删除。持有关系通过引用计数机制控制目标。嵌入关系能够对复合项目建模,并能被看作排他的持有关系。一个项目能是一个或多个持有关系的目标;但一个项目只能是一个嵌入关系的目标。作为嵌入关系的目标的项目不能是任一其它持有或嵌入关系的目标。
引用关系不控制目标项目的生命周期。它们可以是摇摆不定的—目标项目可以不存在。引用关系能用于在全局项目名字空间的任何处(即,包括远程数据存储)建模对项目的引用。
获得一项目不自动取得某关系,应用程序必须明确地请求项目的关系。此外,修改关系不修改源或目标项目;类似地,添加关系不影响源/目标项目。
a)关系声明
显式的关系类型用下列元素定义;
·在Name(名字)属性中指定关系名
·下列之一的关系类型:持有、嵌入、引用。这是在Type(类型)属性中指定的。
·源和目标端点。每个端点指定所引用项目的名和类型。
·源端点字段一般是ItemID(项目ID)类型(未声明),而必须引用在与关系实例同一数据存储中的项目。
·对持有和嵌入关系,目标端点字段必须是ItemIDReference(项目ID引用)类型,且它必须引用在与关系实例相同存储中的项目。对引用关系,目标端点能是任何ItemReference(项目引用)类型,并能引用在其它存储平台数据存储中的项目。
·能可任选地声明标量或PropertyBase(属性基础)类型的一个或多个字段。这些字段能包含与该关系相关联的数据。
·关系实例被存储在全局关系表中。
·每个关系实例唯一地由组合(源ItemID、关系ID)标识。对所有源自给定项目的关系,在给定的源ItemID中关系ID是唯一的,而不管它们的类型。
源项目是关系的拥有者。而被指定为拥有者的项目控制关系的生命周期,关系本身和与它们相关的项目分开。存储平台API 322提供用于展现与项目相关联的关系的机制。
这里是一个关系声明的例子。
<Relationship Name=″Employment″BaseType=″Reference″>
<Source Name=″Employee″ItemType=″Contact.Person″/>
<Target Name=″Employer″ItemType=″Contact.Organization″
ReferenceType=″ItemIDReference″/>
<Property Name=″StartDate″Type=″the storage
platformTypes.DateTime″/>
<Property Name=″EndDate″Type=″the storage
platformTypes.DateTime″/>
<Property Name=″Office″Type=″the storage
platformTypes.DateTime″/>
</Relationship>
这是引用关系的例子。若由源引用所引用的个人项目不存在,则不能创建该关系。而且若该个人项目被删除,在个人和组织之间的关系实例也被删除。然而若组织项目被删除,关系不被删除,而它是摇摆不定的。
b)持有关系
持有关系用于基于目标项目的生命周期管理来对引用计数建模。
一个项目可以是用于对项目的零个或多个关系的源端点。不是嵌入项目的项目可以是在一个或多个持有关系中的目标项目。
目标端点引用类型必须是ItemIDReference,且它必须引用在与关系实例相同的存储中的项目。
持有关系实施目标端点的生命周期管理。持有关系实例和作为目标的项目的创建是原子操作。可以创建将同一项目作为目标的另外的持有关系实例。当具有给定项目作为目标端点的最后一个持有关系实例被删除时,该目标项目也被删除。
在关系声明中指定的端点项目的类型一般在创建该关系的实例时强制。在关系建立之后端点项目的类型不能改变。
持有关系在形成项目的名字空间中起着关键作用。它们包含“Name(名字)”属性,它定义目标项目相对于源项目的名字。对所有源自给定项目的持有关系,相对名字是唯一的。从根项目开始到给定项目的相对名字的有序类表形成该项目的全名。
持有关系形成一有向非循环图(DAG)。在创建持有关系时,***确保不产生回路,从而确保项目的名字空间形成DAG。
虽然持有关系控制目标项目的生命周期,它不控制目标端点项目的操作的一致性。目标项目在操作上独立于通过持有关系拥有它的项目。在作为持有关系的源的项目上的拷贝、移动、备份和其它操作不影响作为同一关系的目标的项目—例如,备份文件夹项目不自动地备份该文件夹中所有项目(FolderMember(文件夹成员)关系中的目标)。
下面是持有关系的例子:
<Relationship Name=″FolderMembers″BaseType=″Holding”>
<Source Name=″Folder″ItemType=″Base.Folder″/>
<Target Name=″Item″ItemType=″Base.Item″
ReferenceType=″ItemIDReference″/>
</Relationship>
FolderMember关系使文件夹的概念成为项目的类属集合。
c)嵌入关系
嵌入关系将目标项目的生命周期的排外控制的概念模型化。它们允许合成项目的概念。
嵌入关系实例和作为目标的项目的创建是原子操作。一个项目能是零个或多个嵌入关系的源。然而一个项目能是一个且仅是一个嵌入关系的目标。作为嵌入关系的目标的项目不能是持有关系的目标。
目标端点引用类型必须是ItemIDReference,且它必须引用在与关系实例相同数据存储中的项目。
在关系声明中指定的端点项目的类型一般在创建该关系的实例时强制。在关系建立之后端点的类型不能改变。
嵌入关系控制该目标端点的操作一致性。例如,串行化项目的操作可包括串行化所有源自该项目及所有其目标的所有嵌入关系;拷贝一项目也拷贝所有它的嵌入项目。
下面是示例声明:
<Relationship Name=″ArchiveMembers″BaseType=″Embedding”>
<Source Name=″Archive″ItemType=″Zip.Archive″/>
<Target Name=″Member″ItemType=″Base.Item″
ReferenceType=″ItemIDReference″/>
<Property Name=″ZipSize″Type=″the storage
platformTypes.bigint″/>
<Property Name=″SizeReduction″Type=″the storage
platformTypes.float″/>
</Relationship>
d)引用关系
引用关系不控制它引用的项目的生命周期。尤其是,引用关系不保证目标的存在,也不保证目标的类型如关系声明中指定的那样。这意味着引用关系能是摇摆不定的。而且引用关系能引用在其它数据存储中的项目。引用关系能看作类似于网页上的链接的概念。
下面是引用关系说明的例子:
<Relationship Name=″DocumentAuthor″BaseType=″Reference″>
<Sourc ItemType=″Document″
ItemType=″Base.Document″/>
<Target ItemType=″Author″ItemType=″Base.Author″
ReferenceType=″ItemIDReference″/>
<Property Type=″Role″Type=″Core.CategoryRef/>
<Property Type=″DisplayName″Type=″the storage
platformTypes.nvarchar(256)″/>
</Relationship>
在目标的端点允许任何引用类型。参与引用关系的项目可以是任何项目类型。
引用关系用于对项目之间的大多数非生命周期管理关系建模。因为不强制目标的存在,引用关系便于对松散耦合的关系建模。引用关系能用于在其它存储,包括在其它计算机上的存储中的目标项目。
e)规则和约束
下列附加规则和约束应用于关系:
·一个项目必须是(仅一个嵌入关系)或(一个或多个持有关系)的目标。一个例外是根项目。一个项目能是零个或多个引用关系的目标。
·作为嵌入关系目标的项目不能是持有关系的源。它能是引用关系的源。
·一个项目若是从文件升级,则不能是持有关系的源。它能是嵌入关系和引用关系的源。
·一个从文件升级的项目不能是嵌入关系的目标。
f)关系的排序
在至少一个实施例中,本发明的存储平台支持关系的排序。通过在基本关系定义中名为“Order(排序)”的属性完成排序。在Order字段中无唯一性约束。不保证带有同一“Order”属性值的关系的次序,然而保证,它们能排序在带较低“Order”值的关系之后并在带较高“Order”字段值的关系之前。
应用程序通过在在组合(SourceItem ID,RelationshipID,Order)上排序得到默认次序的关系。源自给定项目的所有关系实例被排序成单个集合,而不管在集合中关系的类型。然而这保证,给定类型(如,FolderMembers(文件夹成员))的所有关系是给定项目的关系集合的已排序子集。
用于处理关系的数据存储API 312实现一组支持关系的排序的操作。引入下列术语帮助解释那些操作:
·RelFirst是有序集合中带次序值OrdFirst的第一个关系;
·RelLast是有序集合带次序值OrdLast的最后一个关系;
·RelX是集合中带次序值OrdX的给定关系;
·RelPrev是集合中最接近于RelX的带小于OrdX的次序值OrdPrev的关系;以及
·RelNext是集合中最接近于RelX的带大于OrdX的次序值OrdNext的关系。
操作包括但不限于:
·InsertBeforeFirst(SourceItemID,Relationship)***关系作为集合中的第一个关系。新关系的“Order”属性的值可小于OrdFirst。
·InsertAfterLast(SourceItemID,Relationship)***关系作为集合中的最后一个关系。新关系的“Order”属性的值可大于OrdLast。
·InsertAt(SourceItemID,ord,Relationship)***带有对“Order”属性指定的值的关系。
·InsertBefore(SourceItemID,ord,Relationship)在带有给定次序值的关系之前***该关系。新的关系可被分配“Order”值,它在OrdPrev和ord之间,但不包括这两个值。
·InsertAfter(SourceItemID,ord,Relationship)在带有给定次序值的关系之后***该关系。新的关系可被分配“Order”值,它在ord和OrdNext之间,但不包括这两个值。
·MoveBefore(SourceItemID,ord,Relationship)将带给定关系ID的关系移动到带指定“Order”值的关系之前。关系可被分配新的“Order”值,它在OrdPrev和ord之间,但不包括这两个值。
·MoveAfter(SourceItemID,ord,Relationship)将带给定关系ID的关系移动到带指定“Order”值的关系之后。该关系可被分配新的次序值,它在ord和OrdNext之间,但不包括这两个值。
如前提到,每个项目必须是项目文件夹的成员。按照关系,每个项目必须与一项目文件夹有一关系。在本发明的若干实施例中,某些关系由在诸项目之间存在的关系表示。
如对本发明的各实施例的实现,关系提供一有向的二元关系,它由一个项目(源)延伸到另一项目(目标)。关系由源项目(延伸它的项目)拥有,因此若源被移除则关系被移除(如在源项目被删除时关系被删除)。此外在某些情况下,关系可共享(共同拥有的)目标项目的拥有权,且那样的拥有权仅可反映在关系的IsOwned(被拥有)属性(或其等效属性)中(如图7对关系属性类型所示)。在这些实施例中,创建一新的IsOwned关系自动递增该目标上的引用计数,而删除那样的关系可递减该目标项目上的引用计数。对这些特定实施例,若项目具有大于0的引用计数,则继续存在,若项目计数达到0则自动删除。再一次,项目文件夹是具有(或能具有)与其它项目的一组关系的项目,这些其它项目包括项目文件夹的成员资格。关系的其它实际实现是可能的,并由本发明构想来实现这里描述的功能。
不管实际的实现如何,关系是从一个对象到另一对象的可选择的连接。一个项目属于一个以上项目文件夹以及一个或多个类别,而不论这些项目、文件夹和类别是公有的或私有的能力是由给予基于项目的结构中的存在(或缺乏)的意义所确定的。这些逻辑关系是分配给一组关系的意义,而不论其专门用来实现这里所述功能的物理实现如何。逻辑关系是在项目及其文件夹或类别之间建立的(或相反),因为本质上项目文件夹和类别的每一个都是特定类型的项目。因此,能象其它项目一样地对项目文件夹和类别起作用(拷贝、添加到电子邮件消息中、嵌入文档等等,而无限制),而项目文件夹和类别能象其它项目一样使用相同的机制串行化和解串行化(导入和导出)。(例如在XML中,所有项目可具有串行化的格式,且此格同等地应用于项目文件夹、类别和项目)。
代表项目及其项目文件夹之间的关系的上述关系在逻辑上能从项目延伸到项目文件夹、从项目文件夹延伸到项目、或两者。逻辑上从一项目延伸到项目文件夹的关系表明该项目文件夹对于该项目是公有的,并与该项目共享其成员资格信息;相反,缺乏从项目到项目文件夹的逻辑关系表明该项目文件夹对该项目是私有的,且不与该项目共享其成员资格信息。类似地,逻辑上从项目文件夹延伸到项目的关系表明该项目是公有的,并可与该项目文件夹共享,而缺乏从项目文件夹延伸到项目的逻辑关系表明该项目是私有的且不能共享。因此,当向其它***导出项目文件夹时,它是“公有”的项目,它在新的环境中共享,且当项目搜索其项目文件夹寻找其它可共享的项目时,它是“公有”的项目文件夹,它向该项目提供关于属于它的可共享项目的信息。
图9是示出项目文件夹(它本身也是项目)、其成员项目、和项目文件夹及其成员项目之间互联关系的框图。项目文件夹900具有多个项目902、904和906作为其成员。项目文件夹900具有从它本身到项目902的关系912,它表明项目902是公有的,且能与项目文件夹900、其成员904和906、和任何可访问项目文件夹900的任何其它项目文件夹、类别、或项目(未示出)共享。然而从项目902到项目文件夹项目900没有关系,这表明项目文件夹900对项目902是私有的,且不与项目902共享其成员资格信息。另一方面,项目904确实具有从它本身到项目文件夹900的关系924,这表明项目文件夹900是公有的,且与项目904共享其成员资格信息。然而没有从项目文件夹900到项目904的关系,这表明项目904是私有的,且不与项目文件夹900、其另外的成员902、906、及可访问项目文件夹900的任何其它项目文件夹、类别、或项目(未示出)共享。与其到项目902和904的关系(或没有这些关系)相反,项目文件夹900具有从其本身到项目906的关系916,且项目906具有回到项目文件夹900的关系926,一起表明项目906是公有的,且能对文件夹900、其成员902和904、和可访问项目文件夹900的任何其它项目文件夹、类别、或项目(未示出)共享,且项目文件夹900是公有的,并与项目906共享其成员资格信息。
如前讨论,在项目文件夹中的项目不需要共享共同性,因为项目文件夹未被“描述”。另一方面,类别由对所有其成员项目共同的共同性描述。因此,类别的成员资格固有地限于具有所描述的共同性的项目,且在某些实施例中,满足类别的描述的所有项目自动地成为该类别的成员。因此,尽管项目文件夹允许由其成员资格来表示不重要的类型结构,类别基于定义的共同性来允许成员资格。
当然,类别描述本质上是逻辑的,因而类别可通过类型、属性和/或值的任何逻辑表示来描述。例如,对一类别的逻辑表示可以是其成员资格,以包括具有两个属性之一或两者的项目。若这些对类别描述的属性是“A”和“B”,则该类别的成员资格可包括具有属性A而没有B的项目、具有属性B而没有A的项目、及兼有属性A和B的项目。通过逻辑运算符“OR(或)”来描述属性的逻辑表示,其中由类别描述成员组是具有属性A OR B的项目。如本领域的技术人员所理解的,也能使用类似的逻辑运算符(包括但不限于单独的“AND(和)”“XOR(异或)”和“NOT(非)”或其组合)来描述类别。
尽管在项目文件夹(未描述)和类别(已描述)之间有区别,但在本发明的许多实施例中,原则上到项目的类别关系及到类别的项目关系以上面对项目文件夹和项目的同样方法揭示。
图10是示出一类别(其本身也是项目)、其成员项目、类别及其成员项目之间的互联关系的框图。类别1000具有多个项目1002、1004和1006作为成员,所有这些都共享由类别1000描述的共同的属性、值和类型1008(共同性描述1008’)的某个组合。类别1000具有从其本身到项目1002的关系,它表明项目1002是公有的,且能与类别1000、其成员1004和1006、以及可访问类别1000的任何其它类别、项目文件夹、或项目(未示出)共享。然而,没有从项目1002到类别1000的关系,这表明类别1000对项目1002是私有的,且不与项目1002共享成员资格信息。另一方面,项目1004的确具有从其本身到类别1000的关系1024,这表明类别1000是公有的,且与项目1004共享其成员资格信息。然而,不存在从类别1000延伸到项目1004的关系,这表明项目1004是私有的,且不能与类别1000、它的其它成员1002和1006、以及可访问类别1000的任何其它类别、项目文件夹、或项目(未示出)共享。与它与项目1002和1004的关系(或没有此关系)相反,类别1000具有从其本身到项目1006的关系1016,且项目1006具有回到类别1000的关系1026,这一起表明项目1006是公有的,且能与类别1000、其项目成员1002和1004、以及可访问类别1000的任何其它类别、项目文件夹、或项目(未示出)共享,且类别1000是公有的,且与项目1006共享其成员资格信息。
最后,由于类别和项目文件夹本身是项目,且项目可以互相关系,类别可关系到项目文件夹,反之亦然,且在某些另外实施例中,类别、项目文件夹和项目可分别关系到其它类别、项目文件夹和项目。然而在各种实施例中,项目文件夹结构和/或类别结构在硬件/软件接口***级上禁止包含回路。当项目文件夹和类别结构类似于有向图时,禁止回路的实施例类似于有向非循环图(DAG),根据图论领域的数学定义,DAG是其中没有路径在同一顶点开始与终止的有向图。
6.可扩展性
如上所述,本存储平台旨在提供初始模式组340。然而,至少在某些实施例中,该存储平台还允许包括独立软件分销商(ISV)等顾客创建新的模式344(即新的项目和嵌套的元素类型)。本节讨论通过扩展在初始模式组340中定义的项目类型和嵌套的元素类型(或简称“元素”类型)着眼于创建该模式的机制。
较佳地,项目和嵌套元素类型的初始组的扩展如下约束:
·允许ISV引入新的项目类型,即子类型Base.Item;
·允许ISV引入新的嵌套元素类型,即子类型Base.NestedElement;
·允许ISV引入新的扩展,即子类型Base.NestedElement;但
·ISV不能子分类由存储平台的初始模式组340定义的任何类型(项目、嵌入元素、或扩展类型)。
由于由存储平台的初始模式组定义的项目类型或嵌入元素类型可能不精确地匹配ISV应用程序的需要,必须允许ISV定制该类型。这就考虑了扩展的概念。扩展是强类型的实例,但是(a)它们不能独立存在,以及(b)它们必须附属于项目或嵌套元素。
除了解决对模式可扩展性的需要之外,扩展还旨在解决“多分类”问题。在某些实施例中,因为存储平台可能不支持多继承性或重叠子类型,应用程序可以使用扩展作为模型化重叠类型实例(如文档既是合法文档又是安全文档)的方法。
a)项目扩展
为提供项目的可扩展性,数据模型还定义名为Base.Extension的抽象类型。这是扩展类型的分层结构的根类型。应用程序可以子分类Base.Extension,以创建特定的扩展类型。
在基础模式中如下定义Base.Extension类型:
<Type Name=″Base.Extension″IsAbstract=″True″>
<Propety Name=″ItemID″
Type=″the storage platformTypes.uniqueidentified″
Nullable=″false″
MultiValued=″false″/>
<Property Name=″ExtensionID″
Type=″the storage platformTypes.uniqueidentified″
Nullable=″false″
MultiValued=″false″/>
</Type>
ItemID字段包含与该扩展关联的项目的ItemID。带此ItemID的项目必须存在。若带给定ItemID的项目不存在,则不能创建扩展。当项目被删除,带同一ItemID的所有扩展被删除。二元组(ItemID,ExtensionID)唯一地标识了扩展实例。
扩展类型的结构类似于项目类型的结构:
·扩展类型具有字段;
·字段可以是原语或嵌套元素类型;以及
·扩展类型可被子分类。
下列限制应用于扩展类型
·扩展不能是关系的源和目标;
·扩展类型实例不能独立于项目存在;以及
·扩展类型不能用作在存储平台类型定义中的字段类型
对能与给定的项目类型关联的扩展的类型没有约束。任何扩展类型允许扩展任何项目类型。当多个扩展实例被附加到一个项目,它们在结构和行为上彼此独立。
扩展实例被分别存储并从项目访问。所有扩展类型实例可从全局扩展视图访问。能组成一有效的查询,它将返回给定类型的扩展的所有实例,而不管它们关联什么类型的项目。存储平台API提供可存储、检索和修改项目扩展的编程模型。
扩展类型可是使用存储平台的单个继承模型来子分类的类型。从一个扩展类型导出创建新的扩展类型。一个扩展的结构或行为不能覆盖或替代项目类型分层结构的结构或行为。类似于项目类型,扩展类型实例能通过与该扩展类型关联的视图直接访问。扩展的ItemID表明,它们属于哪个项目,并能用于从全局项目视图检索对应的项目对象。为操作一致性的目的,扩展被考虑成项目的一部分。拷贝/移动、备份/恢复和存储平台定义的其它常用操作可以在作为项目的一部分的扩展上操作。
考虑下述例子。在Windows类型组中定义Contact(联系人)类型。
<Type Name=″Contact″BaseType=″Base.Item″>
<Property Name=″Name″
Type=″String″
Nullable=″false″
MultiValued=″false″/>
<Property Name=″Address″
Type=″Address″
Nullable=″true″
MultiValued=″false″/>
</Type>
CRM(客户关系管理)应用程序开发者喜欢将CRM应用程序扩展附加到存储在存储平台中的联系人。应用程序开发者定义包含应用程序能处理的附加数据结构的CRM/扩展。
<Type Name=″CRMExtension″BaseType=″Base.Extension″>
<Property Name=″CustomerID″
Type=″String″
Nullable=″false″
MultiValued=″false″/>
…
</Type>
HR应用程序开发者希望也将附加数据附加到联系人。此数据独立于CRM应用程序数据。应用程序开发者还可创建—扩展
<Type Name=″HRExtension″EBaseType=″Base.Extension″>
<Property Name=″EmployeeID″
Type=″String″
Nullable=″false″
MultiValued=″false″/>
…
</Type>
CRMExtension和HRExtension是能附加到联系人项目的两个独立扩展。它们能彼此独立地创建和访问。
在上述例子中,CRMExtension类型的字段和方法不能覆盖联系人分层结构的字段和方法。应注意,CRMExtension类型的实例能被附加到不同于联系人的项目类型。
在检索联系人项目时,不自动地检索它的项目扩展。给定联系人项目,可通过查询全局扩展视图以寻找带同一ItemID的扩展来访问其有关的项目扩展。
可通过CRMExtension类型视图来访问***中所有的CRMExtension扩展,而不论它们属于什么项目。一个项目的所有项目扩展共享同一项目id。在上述例子中,联系人项目实例和附加的CRMExtension和HRExtension实例共享同一ItemID。
下面的表总结了在Item(项目)、Extension(扩展)和NestedElement(嵌套元素)类型之间的相似性和差别:
Item、ItemExtension与NestedElement
|
Item |
ItemExtension |
NestedElement |
项目ID存储查询/搜索查询/搜索范围关系语义与项目的关联 |
具有自己的项目id项目的分层结构存储在其自己表中能查询项目表能搜索一个项目类型的所有实例能具有与项目的关系能通过持有嵌入和软关系与其它项目相关 |
共享项目的项目id项目扩展分层结构存储在其自己表中能查询项目扩展表能搜索一个项目扩展类型的所有实例与项目扩展无关系通常只能通过扩展来相关。扩展语义类似于嵌入项目语义 |
不具有其自己的项目id。嵌套元素是项目的一部分存储在项目中通常只能在包含项目的上下文中查询通常只能在单个(包含的)项目的嵌套元素类型实例中搜索与嵌套元素无关系通过字段来与项目相关。嵌套元素是项目的一部分 |
b)扩展NestedElement类型
嵌套元素类型不用与项目类型相同的机制扩展。嵌套元素的扩展用与嵌套元素类型字段相同的机制存储和访问。
数据模型定义了名为Element(元素)的嵌套元素类型的根。
<Type Name=″Element″
IsAbstract=″True″>
<Property Name=″ElementID″
Type=″the storage platformTypes.uniqueidentifier″
Nullable=″false″
MultiValued=″false″/>
</Type>
NestedElement类型从此类型继承。NestedElement元素类型另外定义—字段,它是多组元素。
<Type Name=″NestedElement″BaseType=″Base.Element″
IsAbstract=″True″>
<Property Name=″Extensions″
Type=″Base.Element″
Nullable=″false″
MultiValued=″true″/>
</Type>
NestedElement扩展在下面方面不同于项目扩展:
·嵌套元素扩展不是扩展类型。它们不属于以Base.Extension类型为根的扩展类型分层结构。
·嵌套元素扩展与该项目的其它字段一起存储,且不是全局可访问的—不能组成检索给定扩展类型的所有实例的查询。
·象存储其它嵌套元素(或项目)一样地存储这些扩展。象其它的嵌套组,NestedElement扩展被存在UDT中。它们可通过嵌套元素类型的Extension(扩展)字段来访问。
·用于访问多值属性的集合接口也用于在类型扩展组上的访问和迭代。
下面的表总结和比较Item扩展和NestedElement扩展。
Item扩展与NestedElement扩展
|
项目扩展 |
NestedElement扩展 |
存储 |
项目扩展分层结构存入它自己的表 |
象嵌套元素那样存储 |
查询/搜索查询/搜索范围可编程性行为关系语义项目ID |
能查询项目扩展表能查询一个项目扩展类型的所有实例需要特殊的扩展API和扩展表上的特殊查询能关联行为与项目扩展无关系共享项目的项目id |
通常只能在包含项目的上下文中查询通常只能在单个(包含)项目的嵌套元素类型实例中搜索NestedElement扩展类似嵌套元素的任何其它多值字段;使用正常的嵌套元素类型API不允许行为(?)与NestedElement扩展无关系不具有它自己的项目id。NestedElement扩展是项目的一部分 |
F.数据库引擎
如上提到,数据存储在数据库引擎上实现。在本实施例中,数据库引擎包括诸如Microsoft SQL Server引擎等实现SQL查询语言、带有对象关系扩展的关系数据库引擎。本节按照本实施例,描述数据存储实现的数据模型到关系存储的映射,在逻辑API上提供由存储平台的客户机使用的信息。然而可以理解,当采用不同的数据库引擎时可采用不同的映射。确实,除了在关系型数据库引擎上实现存储平台概念数据模型之外,也可在其它类型数据库上实现,如面向对象和XML数据库。
面向对象(OO)数据库***为编程语言对象(如C++、Java)提供持续性和事务。“项目”的存储平台概念可很好地映射到面向对象***中的对象,虽然嵌入的集合必须添加给对象。类似继承性和嵌套元素类型等其它存储平台类型概念也映射到面向对象类型的***。面向对象***通常已经支持对象身份;因此,项目身份可被映射到对象身份。项目的行为(操作)很好地映射到对象方法。然而,面向对象的***通常缺乏组织能力并在搜索方面很差。而且,面向对象的***不提供对非结构化和半结构化数据的支持。为支持这里描述的完全存储平台数据模型,象关系、文件夹和扩展等概念需要添加到对象数据模型。此外,需要实现如升级、同步、通知和安全性等机制。
类似于面向对象的***,基于XSD(XML模式定义)的XML数据库支持基于单继承类型的***。本发明的项目类型***可映射到XSD类型模型。XSD也不提供对行为的支持。项目的XSD必须增添项目的行为。XML数据库处理单个XSD文档并缺乏组织和拓宽搜索能力。如面向对象数据库那样,为支持这里描述的数据模型,如关系和文件夹等其它概念需要被结合到该XML数据库;而且需要实现如同步、通知和安全性等机制。
关于下面小节,提供少量图示以便于一般的信息揭示:图13是示出通知机制的图示。图14是示出两个事务均将新记录***同一B树的例子的图示。图15示出数据改变检测过程。图16示出示例性目录树。图17示出其中基于目录的文件***的现有文件夹被移动到存储平台数据存储中。
1.使用UDT的数据存储实现
在本实施例中,在一个实施例中包括Microsoft SQL Server引擎的关系型数据库引擎314支持内建的标量类型。内建的标量类型是“原生(native)”且“简单”的。它们是原生的意义是,用户不能定义他们自己的类型;它们是简单的意义是,用户不能封装复杂的结构。用户定义的类型(下文称为UDT)通过使用户能通过定义复杂的结构化类型来扩展类型***,提供了一种用于超过或超越原生的标量类型***的类型可扩展性的机制。一旦由用户定义,UDT能用于可以使用内建标量类型的类型***中的任何地方。
按本发明的一个方面,存储平台模式被映射到数据库引擎存储中的UDT类。数据存储项目被映射到从Base.Item类型导出的UDT类。类似于项目,扩展也能映射到UDT类并使用继承。根扩展类型是Base.Extension,从它导出所有扩展类型。
UDT是CLR类,它具有状态(即数据字段)和行为(即例程)。使用任何受管语言(c#、VB.NET等)定义UDT。UDT方法和操作符能在T-SQL中针对该类型的实例调用。UDT能是:行中列的类型、T-SQL中例程的参数的类型、或在T-SQL中变量的类型。
存储平台模式到UDT类的映射在高级别上完全是直接的。一般而言,存储平台模式被映射到CLR名字空间。存储平台类型被映射到CLR类。CLR类的继承镜象了存储平台类型的继承,且存储平台属性被映射到CLR类属性。
2.项目映射
为了希望项目能够被全局地搜索,并在本实施例的关系型数据中支持继承以及类型可替代性,对在数据库存储中的项目存储的一种可能的实现是在带有类型Base.Item的列的单个表中存储所有项目。使用类型可替代性,能存储所有类型的项目,且可按使用Yukon的“is of(类型)”的操作符的项目类型的子类型来过滤搜索。
然而,由于在本实施例中牵涉到与这一方法相关联的额外开销,由顶级类型将各项目划分,使得每个类型“家族”的项目存储到单独的表中。在此划分模式中,对每个直接从Base.Item继承的项目类型创建一个表。如上所述,继承下面这些的类型使用类型的可替代性存储在合适的类型家族表中。只有从Base.Item的第一级继承被专门地处理。
使用一“阴影”表存储所有项目的全局可搜索属性的副本。此表可由存储平台API的Update()方法维护,通过此方法作出所有数据的改变。不象类型家族表,此全局项目表只包含该项目的顶级标量属性,而不是全UDT项目对象。全局项目表允许通过展现ItemID和TypeID(类型ID)导航到存储在类型家族表中的项目对象。ItemID通常唯一地标识数据存储中的项目。可使用这里未予描述的元数据将TypeID映射到类型名和包含该项目的视图。由于通过其ItemID寻找项目在全局项目表的上下文及其它情况下都是常用操作,因此给定了项目的ItemId,提供GetItem()函数来检索项目对象。
为便于访问和尽可能地隐藏实现的细节,项目的所有查询可以对照在上述项目的表上构建的视图进行。具体说来,对每个项目类型针对合适类型的家族表创建视图。这些类型视图可选择相关联的类型,包括子类型的所有项目。为方便起见,除了UDT对象,视图能对包括继承字段的该类型的所有顶级域展现列。
3.扩展映射
扩展非常类似于项目,且具有某些相同要求。如支持继承性的另一根类型,扩展受到存储中许多同样的考虑和折衷比较。为此,对扩展应用类似的类型家族映射,而不是单个表方法。当然,在其它实施例中,可使用单个表方法。在本实施例中,扩展通过ItemID仅与一个项目关联,并包含在项目的上下文中唯一的ExtensionID。如同项目一样,给定包括ItemID和ExtensionID对的身份,可提供一函数用于检索扩展。类似于项目类型视图,对每个扩展类型可创建视图。
4.嵌套元素映射
嵌套元素是可嵌入到项目、扩展、关系、或其它嵌套元素以形成深嵌套结构的类型。类似于项目和扩展,嵌套元素作为UDT实现,但它们存储在项目和扩展中。因此,嵌套元素没有超越它们的项目和扩展容器的映射的存储映射。换言之,在***中没有直接存储NestedElement类型的实例的表,且没有专门用于嵌套元素的视图。
5.对象身份
在数据模型中的每一实体,即每个项目、扩展和关系具有唯一的关键字值。一个项目由其ItemId唯一地标识。扩展由合成关键字(ItemId,ExtensionId)唯一地标识。关系由合成关键字(ItemId,RelationId)标识。ItemId,ExtensionId和RelationshipId均是GUID值。
6.SQL对象命名
在数据存储中创建的所有对象可存储在从存储平台模式名字导出的SQL模式名字中。例如,存储平台基础模式(常称“基础”)可产生在“[System.Storage]”SQL模式中的类型,如“[System.Storage].Item”。产生的名字可用限定词加前缀以消除命名的冲突。在合适处可使用惊叹号(!)作为名字的每个逻辑部分的分割符。下面表概括了在数据存储用于对象的命名习惯。与用于访问数据存储中的实例的修饰的命名习惯一起列出每个模式元素(项目、扩展、关系和视图)。
对象 |
名字修饰 |
描述 |
例子 |
主项目搜索视图 |
Master!Item |
在当前项目域中提供项目的综述 |
[System.Storage].[Master!Item] |
分类型的项目搜索视图 |
ItemType |
提供来自项目和任何父类型的所有属性数据 |
[AcmeCorp.Doc].[OfficeDoc] |
主扩展搜索视图 |
Master!Extension |
提供在当前项目域中所有扩展的综述 |
[System.Storage].[Master!Extension] |
分类型的扩展搜索视图 |
Extension!extensionType |
对扩展提供所有属性数据 |
[AcmeCorp.Doc].[Extension!SlickyNote] |
主关系视图 |
Master!Relationship |
提供在当前项目域中所有关系的综述 |
[System.Storage].[Master!Relationship] |
关系视图 |
Relationship!relationshipName |
提供所有与给定的关系相关联的数据 |
[AcmeCorp.Doc].[Relationship!AuthorsFromDocument] |
视图 |
View!viewName |
基于模式视图定义提供列/类型 |
[AcmeCorp.Doc].[View!DocumentTitles] |
7.列命名
当映射任一对象模型到存储时,由于与应用程序对象一起存储的附加信息,有可能发生命名冲突。为避免命名冲突,所有非类型的特定列(不直接映射到类型声明中的命名的属性的列)用下划线字符(_)加前缀。在本实施例中,下划线字符(_)不允许作为任何标识符属性的开始字符。此外,为统一在CLR和数据存储之间的命名,存储平台类型或模式元素的所有属性(关系等)应具有大写的第一字符。
8.搜索视图
由存储平台提供视图,用于搜索存储的内容。对每个项目和扩展类型提供SQL视图。此外,提供视图以支持关系和视图(由数据模型定义)。所有SQL视图和在存储平台中的底层表是只读的。下面将更充分描述,使用存储平台API的Update()方法可存储或改变数据。
在存储平台模式中直接定义的每个视图(由模式设计者定义,而非由存储平台自动地生成)可由命名的SQL视图[<schema-name>].[View!<view-name>]访问。例如,在模式“AcmePublisher.Books”中名为“BookSales”的视图可使用名字“[AcmePublisher.Books].[View!BookSales]来访问。因为视图的输出格式在每一视图的基础上是自定义的(由定义视图的那一方提供的任意查询确定的),列基于模式视图定义被直接映射。
存储平台数据存储中的所有SQL搜索视图使用列的下述排序习惯:
·如ItemId、ElementId、RelationshipId等的视图结果的逻辑“关键字”列
·如TypeId等关于结果类型的元数据信息。
·改变如CreateVersion(创建版本)、UpdateVersion(更新版本)等跟踪列
·类型专用的列(声明的类型的属性)
·类型专用的视图(家族视图)也包含返回对象的对象列
每个类型家族的成员可使用一系列项目视图来搜索,在数据存储中每个项目类型有一个视图。图28是示出项目搜索视图的概念的图示。
a)项目
每个项目搜索视图对特定类型或其子类型的项目的每个实例包含一行。例如,文档的视图能返回Document(文档)、LegalDocument(合法文档)和ReviewDocument(审阅文档)的实例。给定此例,能如图29那样概念化项目视图。
(1)主项目搜索视图
存储平台数据存储的每个实例定义称为主项目视图(Master Item View)的特殊项目视图。此视图提供关于数据存储中每个项目的综述信息。视图对每个项目类型属性提供一列,其中一列描述项目的类型,若干列用于提供改变跟踪和同步信息。在数据存储中使用名字“[System.Storage].[Master!Item]”来标识主项目视图。
列 |
类型 |
描述 |
ItemId |
ItemId |
该项目的存储平台身份 |
_TypeId |
TypeId |
该项目的TypeId-标识该项目的确切类型并能用于使用元数据类别来检索关于类型的信息 |
_RootItemId |
ItemId |
控制此项目的生命周期的第一个非嵌入先辈的ItemId |
<全局改变跟踪> |
… |
全局改变跟踪信息 |
<项目属性> |
n/a |
对每个项目类型属性有一列 |
(2)分类型的项目搜索视图
每个项目类型也具有搜索视图。类似于根项目视图,此视图还提供通过“_Item”列对项目对象的访问。在数据存储中使用名字[schemaName].[itemTypeName]标识每个分类型的项目搜索视图。例如[AcmeCorp.Dod].[OfficeDoc]。
列 |
类型 |
描述 |
ItemId |
ItemId |
该项目的存储平台身份 |
<类型改变跟踪> |
… |
类型改变跟踪信息 |
<父属性> |
<属性专用> |
对每个父属性有一列 |
<项目属性> |
<属性专用> |
对此类型的每个排他属性有一列 |
_Item |
项目的CLR类型 |
CLR对象一声明的项目的类型 |
b)项目扩展
WinFs存储中的所有项目扩展也可使用搜索视图来访问。
(1)主扩展搜索视图
数据存储的每个实例定义一称为主扩展视图(Master Extension View)的特殊扩展视图。此视图提供关于数据存储中每个扩展的综述信息。该视图对每个扩展属性有一列,其中一列描述扩展的类型,而若干列用于提供改变跟踪和同步信息。使用名字“[System.Storage].[Master!Extension]”在数据存储中标识主扩展视图。
列 |
类型 |
描述 |
ItemId |
ItemId |
与此扩展关联的项目的存储平台身份 |
ExtensionId |
ExtensionId(GUID) |
此扩展实例的id |
_TypeId |
TypeId |
该扩展的TypeId-标识该扩展的确切类型,并能用于使用元数据类别来检索关于该扩展的信息 |
<全局改变跟踪> |
… |
全局改变跟踪信息 |
<扩展属性> |
<属性专用> |
对每个扩展类型属性有一列 |
(2)分类型的扩展搜索视图
每个扩展类型还具有搜索视图。类似于主扩展视图,此视图还提供通过_Extension列对项目对象的访问。在数据存储中使用名字[SchemaName].[Extension!extensionTypeName]标识每个分类型的扩展搜索视图。例如[AcmeCorp.Doc].[Extension!OfficeDocExt]。
列 |
类型 |
描述 |
ItemId |
ItemId |
与此扩展关联的项目的存储平台身份 |
ExtensionId |
ExtensionId(GUID) |
此扩展实例的Id |
<类型改变跟踪> |
… |
类型改变跟踪信息 |
<父属性> |
<属性专用> |
对每个父属性有一列 |
<扩展属性> |
<属性专用> |
对每个此类型的排他属性有一列 |
_Extension |
扩展实例的CLR类型 |
CLR对象—声明的扩展的类型 |
c)嵌套的元素
所有嵌套的元素存储在项目、扩展或关系实例之中。因此,它们能通过查询合适的项目、扩展或关系搜索视图来访问。
d)关系
如上讨论,关系形成在存储平台数据存储中各项目之间链接的基本单元。
(1)主关系搜索视图
每个数据存储提供—主关系视图。此视图提供关于数据存储中所有关系实例的信息。在数据存储中使用名字“[System.Storage].[Master!Relationship]”来标识主关系视图。
列 |
类型 |
描述 |
ItemId |
ItemId |
源端点的身份(ItemId) |
RelationshipId |
RelationshipId(GUID) |
该关系实例的id |
_RelTypeId |
RelationshiPTypeId |
该关系的RelTypeId-使用元数据类别来标识该关系实例的类型 |
<全局改变跟踪> |
… |
全局改变跟踪信息 |
TargetItemReference |
ItemReference |
目标端点的身份 |
_Relationship |
Relationship |
对此实例的Relationship对象的实例 |
(2)关系实例搜索视图
每个声明的关系也有返回该特定关系的所有实例的搜索视图。类似于主关系视图,此视图对该关系数据的每个属性提供命名的列。在数据存储中使用名字[schemaName].[Relationship!relationshipName]来标识每个关系实例搜索视图。例如[AcmeCorp.Doc].[Relationship!DocumentAuthor]。
列 |
类型 |
描述 |
ItemId |
ItemId |
源端点的身份(ItemId) |
RelationshipId |
RelationshipId(GUID) |
该关系实例的id |
<类型改变跟踪> |
… |
类型改变跟踪信息 |
TargetItemReference |
ItemReference |
目标端点的身份 |
<源名> |
ItemId |
源端点身份的命名属性(ItemId的别名) |
<目标名> |
ItemReference或导出的类 |
目标端点身份的命名属性(TargetItemReference的别名和模型(cast)) |
<关系属性> |
<属性专用> |
对每个关系定义的属性有一列 |
_Relationship |
关系实例的CLR类型 |
CLR对象—声明关系的类型 |
e)
9.更新
存储平台数据存储中所有视图是只读的。为创建数据模型元素(项目、扩展或关系)的新实例,或更新现有的实例,必须使用存储平台API的ProcessOperation或ProcessUpdategram方法。ProcessOperation方法是单个存储的过程,它是由消费细化拟执行的动作的“操作”的数据存储定义的。ProcessUpdategram方法是存储的过程,它采取称为“更新元素(updategram)”的一组有序的操作,它们共同细化拟执行的一组动作。
操作格式是可扩展的,并提供在模式元素上的各种操作。某些公用操作包括:
1.项目操作:
a.CreateItem(在嵌入或持有关系的上下文中创建一新的项目)
b.UpdateItem(更新一现有的项目)
2.关系操作:
a.CreateRelationship(创建引用或持有关系的实例)
b.UpdateRelationship(更新一关系实例)
c.DeleteRelationship(移除一关系实例)
3.扩展操作
a.CreateExtension(添加一扩展到现有的项目)
b.UpdateExtension(更新一现有的扩展)
c.DeleteExtension(删除一扩展)
10.改变跟踪及墓碑
如下面更充分讨论,由数据存储提供改变跟踪和墓碑服务。本节提供在数据存储中展现的改变跟踪信息的概述
a)改变跟踪
由数据存储提供的每个搜索视图包含用于提供改变跟踪信息的列;那些列对所有项目、扩展和关系视图是公用的。由模式设计者明确地定义的存储平台模式视图不自动地提供改变跟踪信息—该信息是通过在其上构建视图本身的搜索视图来间接提供的。
对数据存储中的每个元素,可从两个地方得到改变跟踪信息:“主”元素视图和“分类型的”元素视图。例如,可从主项目视图“[System.Storage].[Master!Item]”和分类型的项目视图[AcmeCorp.Document].[Document]中得到关于AcmeCorp.Document.Document项目类型的改变跟踪信息。
(1)“主”搜索视图中的改变跟踪
主搜索视图中的改变跟踪信息提供关于元素的创建和更新版本的信息、关于哪个同步伙伴创建该元素的信息、关于哪个同步伙伴最后一次更新该元素的信息、以及来自每个伙伴的用于创建和更新的版本号。用伙伴关键字来标识同步关系中的伙伴(下面描述)。类型[System.Storge.Store].ChangeTrackingInfo的名为_ChangeTrackingInfo的单个UDT对象包含所有这些信息。在System.Storage模式中定义类型。在项目、扩展和关系的所有全局搜索视图中可得到_ChangeTrackingInfo。_ChangeTrackingInfo的类型定义是:<Type Name=″ChangeTrackingInfo″BaseType=″Base.NestedElement″> <FieldProperty Name=″CreationLocalTS″ Type=″SqlTypes.SqlInt64″Nullable=″False″/><FieldProperty Name=″CreatingPartnerKey″ Type=″SqlTypes.SqlInt32″
Nullable=″False″/><FieldProperty Name=″CreatingPartnerTS″ Type=″SqlTypes.SqlInt64″
Nullable=″False″/><FieldProperty Name=″LastUpdateLocalTS″ Type=″SqlTypes.SqlInt64″
Nullable=″False″/><FieldProperty Name=″LastUpdatingPartnerKey″Type=″SqlTypes.SqlInt32″
Nullable=″False″/><FieldProperty Name=″LastUpdatingPartnerTS″ Type=″SqlTypes.SqlInt64″
Nullable=″False″/></Type>
这些属性包含下述信息:
列 |
描述 |
_CreationLocalTS |
本地机器的创建时间标记 |
_CreatingPartnerKey |
创建此实体的伙伴的PartnerKey。若实体是本地创建的,这是本地机器的PartnerKey |
_CreatingPartnerTS |
在对应于_CreatingPartnerKey的伙伴处创建此实体的时间的时间标记 |
_LastUpdateLocalTS |
对应于本地机器的更新时间的本地时间标记 |
_LastUpdatePartnerKey |
最后一次更新此实体的伙伴的PartnerKey。若对该实体的最后一次更新在本地完成,则这是本地机器的PartnerKey。 |
_LastUpdatePartnerTS |
在对应于_LastUpdatingPartnerKey的伙伴处更新此实体的时间的时间标记。 |
(2)“分类型的”搜索视图中的改变跟踪
除了提供与全局搜索视图相同信息外,每个分类型的搜索视图提供记录在同步拓扑中每个元素的同步状态的附加信息。
列 |
类型 |
描述 |
<全局改变跟踪> |
… |
来自全局改变跟踪的信息 |
_ChangeUnitVersions |
MultiSet<改变单元版本> |
特定元素中的改变单元的版本号的描述 |
_ElementSyncMetadata |
ElementSyncMetadata |
关于只对同步运行库感兴趣的项目的附加版本无关元数据 |
_VersionSyncMetadata |
VersionSyncMetadata |
关于只对同步运行库感兴趣的版本的附加版本专用元数据 |
b)墓碑
数据存储为项目、扩展和关系提供墓碑信息。墓碑视图提供一个地方中有关活动和墓碑实体两者(项目、扩展和关系)的信息。项目和扩展墓碑视图不提对对应对象的访问,而关系墓碑视图提供对关系对象的访问(在墓碑关系的情况下关系对象为空)。
(1)项目墓碑
通过视图[System.Storage].[Tombstone!item]从***检索项目墓碑。
列 |
类型 |
描述 |
ItemId |
ItemId |
项目的身份 |
_TypeID |
TypeId |
项目的类型 |
<项目属性> |
… |
对所有项目定义的属性 |
_RootItemId |
ItemId |
包含此项目的第一个非嵌入项目的ItemId |
_ChangeTrackingInfo |
ChangeTrackingInfo类型的CLR实例 |
此项目的改变跟踪信息 |
_IsDeleted |
BIT |
这是标志,0是活动项目,1是墓碑项目 |
_DeletionWallclock |
UTCDATETIME |
按删除项目的伙伴的UTC墙钟日期时间,若该项目是活动的,它为空 |
(2)扩展墓碑
使用视图[System.Storage].[Tombstone!Extension]从***检索扩展墓碑。扩展改变跟踪信息类似于为项目提供的添加了ExtensionId属性的信息。
列 |
类型 |
描述 |
ItemId |
ItemId |
拥有该扩展的项目的身份 |
ExtensionId |
ExtensionId |
该扩展的ExtensionId |
_TypeID |
TypeId |
该扩展的类型 |
_ChangeTrackingInfo |
ChangeTrackingInfo类型的CLR实例 |
此扩展的改变跟踪信息 |
_IsDeleted |
BIT |
这是标志,0是活动项目,而1是墓碑扩展 |
_DeletionWallclock |
UTCDATETIME |
按删除该扩展的伙伴的UTC墙钟日期间。若该扩展是活动的,它为空 |
(3)关系墓碑
通过视图[System.Storage].[Tombstone!Relationship]从***检索关系墓碑。关系墓碑信息类似于对扩展提供的信息。然而,在关系实例的目标ItemRef上提供附加信息。此外,还选择关系对象。
列 |
类型 |
描述 |
ItemId |
ItemId |
拥有该关系的项目的身份(关系的源端点的身份) |
RelationshipId |
RelationshipId |
该关系的RelationshipId |
_TypeID |
TypeId |
关系的类型 |
_ChangeTrackingInfo |
ChangeTrackingInfo类型的CLR实例 |
此关系的改变跟踪信息 |
_IsDeleted |
BIT |
这是标志,0是活动项目,而1是墓碑扩展 |
_DeletionWallclock |
UTCDATETIME |
按删除该关系的伙伴的UTC墙钟日期时间。若该关系是活动的,它为空 |
_Relationship |
关系的CLR实例 |
这是活动关系的关系对象,对墓碑的关系它为空 |
TargetItemReference |
ItemReference |
目标端点的身份 |
(4)墓碑清除
为防止墓碑信息无限制地增长,数据存储提供墓碑清除任务。此任务确定什么时候可以舍弃墓碑信息。该任务计算本地创建/更新版本的界限,并随后通过舍弃所有更早的墓碑版而截断墓碑信息。
11.助手API和函数
基础映射还提供若干助手函数。提供这些函数以帮助在该数据模型上的公用操作。
a)函数[System.Storage].GetItem
//给定ItemId返回一项目对象
Item Getltem(Itemld Itemld)
b)函数[System.Storage].GetExtension
//给定ItemId和ExtensionId返回一扩展对象
Extension GetExtension(Itemld Itemld,Extensionld Extensionld)
c)函数[System.Storage].GetRelationship
//给定ItemId和RelationshipId返回—关系对象
Relationship GetRelationship(Itemld Itemld,Relationshipld Relationshipld)
12.元数据
有两类在存储中表示的元数据:实例元数据(项目的类型等),和类型元数据。
a)模式元数据
模式元数据作为来自元模式的项目类型的实例存储在数据存储中。
b)实例元数据
应用程序使用实例元数据来查询项目的类型,并寻找与项目相关联的扩展。给定项目的ItemId,应用程序可查询全局项目视图,以返回该项目的类型,并使用此值来查询Meta.Type视图以返回关于该项目的声明的类型的信息。例如,
//对给定的项目实例返回元数据项目对象
SELECT m._Item AS metadataInfoObj
FROM[System.Storage].[Item]i INNER JOIN[Meta].[Type]m ON i._Typeld=m.Itemld
WHERE i.Itemld=@Itemld
G.安全性
一般而言,所有可保护的对象使用图26中所示的访问掩码格式来安排访问权限。在此格式中,低16位用于对象专用的的访问权限,接着7位用于应用于大多数对象类型的标准访问权限,高4位用于指定类属访问权限,每个对象类型将其映射到一组标准且对象专用的权限。ACCESS_SYSTEM_SECURITY位对应于访问对象的SACL的权限。
在图26的访问掩码结构中,项目专用的权限被放置在对象专用权限段(低16位)。由于在本实施例中,存储平台向管理员安全性展现两组API:Win32和存储平台API,为促进存储平台对象专用权限的设计,必须考虑文件***对象专用的权限。
在通过引用结合于此的有关专利中充分描述了用于本发明的存储平台的安全模型。在这点上,图27(部分a、b和c)画出按安全模型的一实施例,作为从现有安全区域开拓出的新的等同地保护的安全区域。
H.通知和改变跟踪
按本发明的另一方面,存储平台提供允许应用程序跟踪数据改变的通知能力。此特征主要供保持易失状态或执行数据改变事件上的业务逻辑的应用程序使用。应用程序注册在项目、项目扩展及项目关系上的通知。在提交了数据改变通知被异步地传送。应用程序可按项目、扩展和关系类型以及操作类型来过滤通知。
按一个实施例,存储平台API 322为通知提供两类接口。第一,应用程序注册由对项目、项目扩展和项目关系的改变触发的简单数据改变事件。第二,应用程序创建“监视程序”对象来监视项目、项目扩展和项目之间关系的组。在***失败或***离线超过预定时间之后,可保存和重新创建监视程序对象的状态。单个通知可反映多个更新。
关于此功能的附加细节能在先前通过引用结合于此的有关专利中找到。
I.同步
按照本发明的另一个方面,存储平台提供同步服务330,它(i)允许存储平台的多个实例(每个具有它自己的数据存储器302)按照一组灵活的规则同步它们的部分内容,以及(ii)为第三方提供一个基础结构,以用实现专有协议的其它数据源来同步本发明的存储平台的数据存储。
存储平台对存储平台同步在一组参与的复制品之间发生。例如,参考图3,可能想要在存储平台300的数据存储器302与在存储平台的另一个实例控制下的另一个远程数据存储338(可能运行在一个不同的计算机***上)之间提供同步。这个组的全部成员资格对于任何给定的复制品在任何给定时间不必是已知的。
不同的复制品可以独立地作出改变(即,同时地)。同步的过程定义使每个复制品知道其它复制品作出的改变。这个同步能力固有地是多主的(multi-master)。
本发明的同步能力允许复制品:
·确定另一个复制品知道哪些改变;
·请求关于这个复制品不知道的改变的信息;
·传送关于另一个复制品不知道的改变的信息;
·确定何时两个改变彼此冲突;
·在本地应用改变;
·传送冲突分解方案到其它复制品以保证会聚;以及
·基于冲突分解方案的指定政策分解冲突。
1.存储平台到存储平台的同步
本发明的存储平台的同步服务300的基本应用是同步存储平台(每个带有它自己的数据存储)的多个实例。同步服务在存储平台模式级上操作(而不是在数据库引擎314的底层表中)。因此,例如“范围(Scope)”用于定义下面讨论的同步组。
同步服务按“纯改变(net change)”的原则操作。不是记录和发送各个操作(如事务复制),同步服务而是发送这些操作的最终结果,因此常将多个操作的结果合并成单个最终结果。
同步服务通常不考虑事务边界。换言之,若在单个事务中对存储平台数据存储作出两个改变,不保证这些改变原子地应用到所有其它复制品上—可以示出一个改变而不示出其它改变。此原则的例外是,若在同一事务中对同一项目作出两个改变,则这些改变保证被原子地发送和应用到其它复制。因此,项目是同步服务的一致性单元。
a)同步(Sync)控制应用程序
任一应用程序可连接到同步服务并启动sync(同步)操作。那样的应用程序提供执行同步(见下面同步概况)所需的所有参数。那样的应用程序在这里被称为同步控制应用程序(SCA)。
在同步两个存储平台实例时,在一侧由SCA启动同步。该SCA通知本地同步服务与远程伙伴同步。在另一侧,同步服务通过由来自发起机器的同步服务发出的消息唤醒。它基于在目标机器上存在的持久配置信息(见下文的映射)作出响应。同步服务能按时间表或响应于事件运行。在这些情况下,实现时间表的同步服务成为SCA。
为启用同步,需要采取两个步骤。首先,模式设计者必须用合适的同步语义注释存储平台模式(如下文所述的指定改变单元)。其次,同步必须在具有参与同步的存储平台的实例的所有机器上正确地配置(如下所述)。
b)模式注释
同步服务的基本概念是改变单元(Change Unit)的概念。改变单元是由存储平台个别地跟踪的最小的模式片段。对每个改变单元,同步服务能确定自从最后一次同步以来它是被改变还是未被改变。
指定模式中的改变单元达到若干目的。首先,它确定了在线的同步服务如何罗嗦。当在改变单元内作出改变时,整个改变单元被发送到其它复制品,因为同步服务不知道改变单元的哪部分被改变。其次,它确定了冲突检测的粒度。当对同一改变单元作出两个并发的改变(这些术语在后继章节中详细定义),同步服务引起冲突;另一方面,若对不同改变单元作出并发改变,则无冲突发生,且改变被自动地合并。第三,它严重地影响了由***保持的元数据的量。对每个改变单元保持许多同步服务元数据;因此,使改变单元更小会增加同步的额外开销。
定义改变单元需要找出正确的折衷。为此,同步服务允许模式设计者参与此过程。
在一个实施例中,同步服务不支持大于一个元素的改变单元。然而,它支持让模式设计者指定比一个元素更小的改变单元的能力—即将一个元素的多个属性组合到单独的改变单元中。在该实施例中,这是使用下述句法实现的:<Type Name=″Appointment″MajorVersion=″1″MinorVersion=″0″ExtendsType=″Base.Item″
ExtendsVersion=″1″>
<Field Name=″MeetingStatus″Type=″the storage platformTypes.uniqueidentifierNullable=″False″/>
<Fileld Name=″OrganizerName″Type=″the storage platformTypes.nvarchar(512)″Nullable=″False″/>
<Filed Name=″OrganizerEmail″Type=″the storage plattorm Types.nvarchar(512)″TypeMajorVersion=″1″ MultiValued=″True″/>
…
<ChangeUnit Name=″CU_Status″><Field Name=″MeetingStatus″/>
</ChangeUnit>
<ChangeUnit Name=″CU_Organizer″/><Field Name=″OrganizerName″/><Field Name=″OrganizerEmail″/>
</ChangeUnit>
…</Type>
c)同步配置
希望保持它们数据的某些部分同步的一组存储平台伙伴被称为同步共同体。虽然共同体的成员希望保持同步,它们不需要以完全相同的方式表示数据;换言之,同步伙伴可转换他们正在同步的数据。
在对等情况下,让对等方对所有它们的伙伴维持转换映射是不现实的。取代地,同步服务采取定义“共同体文件夹”的方法。共同体文件夹是代表所有共同体成员正在与之同步的假设的“共享文件夹”的抽象。
此概念最好用一例子说明。若Joe希望保持他的若干计算机的My Documents(我的文档)文件夹同步,Joe定义一共同体文件夹,如称为JoeDocuments。随后在每台计算机上,Joe在假设的JoeDocuments文件夹和本地My Documents文件夹之间配置一映射。从这点出发,当Joe的计算机彼此同步时,它们借助JoeDocuments中的文档而不是它们的本地项目来交谈。以此方法,所有Joe的计算机互相理解,而不必知道其它人是谁—共同体文件夹成为同步共同体的通用语。
配置同步服务包括三个步骤:(1)定义在本地文件夹和共同体文件夹之间的映射;(2)定义确定哪个得到同步的同步概况(如与谁同步,以及哪个子集应当被发送、哪个被接收);以及(3)定义不同的同步概况应当运行的时间表,或手动运行它们。
(1)共同体文件夹—映射
共同体文件夹映射作为XML配置文件被存储在个别机器上。每个映射具有以下模式:/mappings/communityFolder
此元素命名映射的共同体文件夹。名字遵循文件夹的句法规则。/mappings/localFolder
此元素命名映射所转换到的本地文件夹。此名字遵循文件夹的句法规则。为了映射有效,文件夹必须已存在。此文件夹中的项目被看作对每一此映射的同步。/mappings/transformations
此元素定义如何将项目从共同体文件夹转换到本地文件夹以及如何反向转换。若缺少或为空,不执行转换。具体说来,这意味着无ID被映射。此配置主要用于创建文件夹的高速缓存。/mappings/transformations/mapIDs
此元素请求新生成的本地ID被赋予所有从共同体文件夹映射的项目,而不是重新使用共同体ID。同步运行库维护ID映射,以来回转换项目。/mappings/transformations/localRoot
此元素请求共同体文件夹中的所有根项目作为指定根的子项目。/mappings/runAs
此元素控制,在谁的授权下处理针对此映射的请求。若不存在,则假设发送者。/mappings/runAs/sender
存在此元素表明,对此映射的消息发送者必须是人格化的,且在他的凭证下处理请求。
(2)概况
同步概况是分离同步所需的总的参数组。由SCA将其提供给同步运行库以启动同步。存储平台到存储平台的同步的同步概况包含以下信息:
·本地文件夹,用作改变的源和目标;
·与之同步的远程文件夹名—此文件夹必须通过如上定义的映射从远程伙伴发布;
·方向—同步服务支持只发送、只接收以及发送—接收同步;
·本地过滤器—选择发送什么本地信息到远程伙伴。表示成本地文件夹上的存储平台查询;
·远程过滤器—选择从远程伙伴接收什么远程信息—表示成共同体文件夹上的存储平台查询;
·转换—定义如何在项目和本地格式间转换;
·本地安全性—指定是在远程端点(人格化)的许可下应用从远程端点检索的改变,还是用户在本地启动同步;以及
·冲突分解政策—指定冲突是否应被拒绝、记入日志或自动分解—在后一种情况下,指定使用哪个冲突分解器以及它的配置参数。
同步服务提供允许简单构建同步概况的运行时CLR类。概况可被串行化成XML文件或从XML文件串行化,以便容易存储(常与时间表一起)。然而,在存储平台中没有存储所有概况的标准地方;欢迎SCA在不必永久保持的点上构建概况。注意,不需要具有本地映射来启动同步。能在概况中指定所有同步信息。然而为响应于由远程方启动的同步请求,需要映射。
(3)时间表
在一个实施例中,同步服务不提供它自己的调度基础结构。相反,它依赖于另一组件来完成此任务—在Microsoft Windows操作***中可得到的WindowsScheduler。同步服务包括命令行实用程序,它担当SCA并基于保存在XML文件中的同步概况触发同步。该实用程序使得按时间表或者响应于如用户登录或登出等事件来配置Windows Scheduler变得非常容易。
d)冲突处理
同步服务中的冲突处理被划分成三个阶段:(1)发生在改变应用时的冲突检测—此步骤判断是否可安全地应用改变;(2)自动冲突分解并记入日志—在此步骤(发生在紧接着冲突检测之后)资讯自动冲突分解器,以查看冲突是否能被分解—若不能,可任选地将冲突记入日志;以及(3)冲突检查与分解—若某些冲突已被记入日志,且发生在同步会话之外,则采取此步骤—此时,被记入日志的冲突能被分解并从日志中移除。
(1)冲突检测
在本实施例中,同步服务检测两类冲突:基于知识和基于约束的。
(a)基于知识的冲突
当两个复制品对同一改变单元作出独立的改变时,发生基于知识的冲突。两个改变若是它们在互相不知道的情况作出的,则称为独立的—换言之,第一个的版本不被第二个的知识所覆盖,反之亦然。同步服务基于上述复制品的知识自动检测所有那些冲突。
将冲突想成在改变单元的版本历史中的分叉有时是有益的。若在改变单元的生命中不发生冲突,其版本历史是简单的链—每个发生在前一个之后。在基于知识的冲突的情况下,两个改变并行发生,导致链***,成为版本树。
(b)基于约束的冲突
存在独立的改变在一起应用时破坏完整性约束的情况。例如,在同一目录中用同样的名字创建一个文件的两个复制品能导致发生那样的冲突。
基于约束的冲突牵涉到两个独立的改变(就象基于知识的冲突),但它们不影响同一改变单元。相反,它们影响不同的改变单元,但在它们之间存在约束。
同步服务检测在改变应用时的约束破坏,并自动引起基于约束的冲突。分解基于约束的冲突通常需要自定义代码,它以不破坏约束的方式修改那些改变;同步服务不提供这样做的通用机制。
(2)冲突处理
在检测到冲突时,同步服务可采取三个动作之一(由同步概况中的同步启动者选择):(1)拒绝该改变,将其返回到发送者;(2)将冲突记入到冲突日志;或(3)自动分解冲突。
若改变被拒绝,同步服务如同该改变没有到达该复制品那样地运作。否定确认被发回到发起者。此分解政策主要在无领导的复制品(如文件服务器)上有用,在那里将冲突记入日志是不可行的。相反,那些复制品通过拒绝它们来强迫其它复制品处理那些冲突。
同步启动者在它们的同步概况中配置冲突分解。同步服务支持在单个概况中以下列方式组合多个冲突分解器—首先通过指定冲突分解器的列表,一个接着一个地尝试分解,直到其中一个成功;第二,通过将冲突分解器与冲突类型相关联,如引导更新—更新基于知识的冲突到一个分解器,但所有其它冲突记入日志。
(a)自动冲突分解
同步服务提供若干默认的冲突分解器。其列表包括:
·本地赢:若与本地存储的数据冲突,则不予处理进入的改变;
·远程赢:若与进入的改变冲突,则不予处理本地数据;
·最后写赢:基于改变的时间标记挑选每个改变单元的本地赢或远程赢(注意,同步服务一般不依赖于时钟值;此冲突分解器是该规则的唯一例外);
·确定的:以保证在所有复制品上相同,但在其它情况下无意义的方式挑选赢者—同步服务的一个实施例使用伙伴ID的字典式比较来实现此特征。
此外,ISV能实现并安装它们自己的冲突分解器。自定义冲突分解器可接受配置参数;那些参数必须由SCA在同步概况中的冲突分解段中指定
在冲突分解器处理冲突时,它向运行库返回需要执行的操作(替代冲突改变)的列表。然后同步服务应用这些操作,其具有正确地调整的远程指示,以包括冲突处理器所考虑的所有内容。
在应用分解的同时可能检测到另外冲突。在那样情况下,新的冲突必须在原先处理重新开始之前被分解。
将冲突考虑成项目的版本历史中的分枝时,冲突分解可看成合并—组合两个分枝以形成单个点。因此,冲突分解将版本历史转到DAG。
(b)冲突日志记录
一种非常特定类型的冲突分解器是冲突日志记录器。同步服务将冲突记入日志作为ConflictRecord(冲突记录)的项目。这些记录反过来与冲突中的项目有关(除非项目本身已被删除)。每个冲突记录包括:导致冲突的进入的改变;冲突的类型;更新—更新、更新—删除、删除—更新、***—***或约束;以及进入的改变的版本和发送它的复制品的知识。记入日志的冲突可用于下面所述的检查和分解。
(c)冲突审查和分解
同步服务对应用程序提供API,以检查冲突日志并建议其中的冲突分解。该API允许应用程序枚举所有冲突,或与给定项目有关的冲突。还允许那些应用程序以下列三种方法之一分解记入日志的冲突:(1)远程赢—接受记入日志的改变并覆写冲突的本地改变;(2)本地赢—忽略记入日志的改变的冲突部分;以及(3)建议新的改变—其中,应用程序提议一合并,以它的观点,该合并分解冲突。一旦由应用程序分解了冲突,同步服务将它们从日志中移除。
(d)复制品的会聚性及冲突分解的传播
在复杂同步的情况下,在多个复制品中能检测到同一冲突。若发生此情况,发生若干事情:(1)在一个复制品上能分解冲突,并将分解送到其它复制品;(2)冲突在两个复制品上被自动分解;以及(3)在两个复制品上手动分解冲突(通过分解检查API)。
为保证会聚性,同步服务将冲突分解转发到其它复制品。当分解冲突的改变到达复制品时,同步服务自动地在日志中寻找由此更新分解的任何冲突,并消除它们。在此情况下,一个复制品上的冲突分解被绑定到所有其它复制品。
若不同的复制品对同一冲突选择了不同的赢者,则同步服务应用绑定冲突分解的原则,并自动地挑选两个分解中一个胜过另一个。以确定性的方式挑选赢者以保证在所有时刻都产生同样的结果(一个实施例使用复制品ID字典式比较)。
若不同复制对同一冲突建议不同的“新改变”,则同步服务将此新冲突处理成特殊冲突,并使用冲突日志记录器来防止它传播到其它复制品。那样情况常在手动冲突分解时发生。
2.对非存储平台数据存储的同步
按本发明的存储平台的另一方面,存储平台提供ISV用于实现同步适配器的体系结构,同步适配器使存储平台能与如Microsoft Exchange、AD、Hotmail等传统***同步。同步适配器得益于由下述同步服务提供的许多同步服务。
不管其名称如何,同步适配器不需要作为某个存储平台体系结构的插件来实现。在需要时,“同步适配器”能简单地是利用同步服务运行库接口来获得如改变枚举和应用等服务的任何应用程序。
为了使其他人能更容易地配置和运行到给定背端(backend)的同步,鼓励同步适配器的编写者展现标准同步适配器接口,它在给定上述的同步概况时运行同步。概况提供配置信息给适配器,某些适配器传送到同步运行库以控制运行库服务(如,要同步的文件夹)。
a)同步服务
同步服务向适配器编写者提供若干同步服务。在本节余下部分,方便地将存储平台在其上做同步的机器称为“客户机”,而适配器正与其对话的非存储平台背端称为“服务器”。
(1)改变枚举
基于由同步服务维持的改变跟踪数据,改变枚举允许同步适配器容易地枚举自从最后一次与该伙伴试图作出同步以来对数据存储文件夹发生的改变。
基于“锚位(anchor)”的概念来枚举改变—这是表示有关最后一次同步的信息的不透明的结构。如以前章节所述,锚位采取存储平台知识的形式。利用改变枚举服务的同步适配器落入两大类别:使用“存储的锚位”的适配器和使用“提供的锚位”的适配器。
区别基于关于最后一次同步的信息存储在哪里—在客户机上或在服务器上。适配器常常容易地存储此信息在客户机上—背端往往不能容易地存储此信息。另一方面,若多个客户机与同一背端同步,则将此信息存储在客户机上是低效且在某些情况下是不正确的—这使一个客户机不知道其它客户机已推到服务器的改变。若适配器希望使用服务器存储的锚位,则适配器需要在改变枚举时将其送回到存储平台。
为了让存储平台维护锚位(用于本地或远程存储),存储平台需要知道成功地应用在服务器上的改变。这些且只有这些改变能包括在锚位中。在改变枚举期间,同步适配器使用确认(Acknowledgement)接口,以报告哪个改变已被成功地应用。在同步结束时,使用提供的锚位的适配器必须读出新锚位(它集合所有成功应用的改变)并将其发送到它们的背端。
各适配器常常需要存储适配器专用数据以及***到存储平台数据存储中的各项目。该数据存储的常见例子是远程ID和远程版本(时间标记)。同步服务提供用于存储此数据的机制,而改变枚举提供接收此额外数据以及要返回的改变的机制。在大多数情况下,这消除了适配器重新查询数据库的需求。
(2)改变应用
改变应用允许同步适配器将从它们的背端接收的改变应用到本地存储平台。期望适配器将改变转换到存储平台模式。图24示出从存储平台模式生成存储平台API类的过程。
改变应用的主要功能是自动检测冲突。如在存储平台到存储平台同步的情况下,冲突被定义成在互相不知道时作出的两个重叠的改变。当适配器使用改变应用时,它们必须指定对其执行冲突检测的锚位。若检测到未被适配器的知识覆盖的重叠的本地改变,则改变应用引起冲突。类似于改变枚举,适配器可使用存储的或提供的锚位。改变应用支持适配器专用元数据的有效存储。那样的数据可由适配器将其附加到要应用的改变上,且可被同步服务存储。数据可在下次改变枚举时返回。
(3)冲突分解
以下在IV中描述的冲突分解机制(包括记入日志和自动分解选项)也对同步适配器可用。在应用改变时,同步适配器能指定用于冲突分解的政策。若指定了,冲突可被传递到指定的冲突处理程序并予以分解(若可能)。冲突也能被记入日志。当试图将本地改变应用到背端时,适配器有可能检测冲突。在那样情况下,适配器仍可以将冲突传递到同步运行库,以按政策分解。此外,同步适配器可请求任何由同步服务检测的冲突发回给它们以便处理。在背端能存储或分解冲突的情况这特别方便。
b)适配器实现
虽然某些“适配器”简单地是利用运行库接口的应用程序,然而鼓励适配器实现标准的适配器接口。这些接口允许同步控制应用程序:请求适配器按给定的同步概况执行同步;取消正进行的同步;以及接收关于正进行同步的进展报告(完成百分比)。
3.安全性
同步服务努力将尽可能少的同步引入到由存储平台实现的安全模式。不是去定义对同步新的权限,而是使用现有的权限。具体地,
·能读数据存储项目的任何人可枚举对那个项目的改变;
·能写到数据存储项目的任何人可应用改变到该项目;以及
·能扩展数据存储项目的任何人可将同步元数据与该项目关联。
同步服务不维护安全授权信息。当在复制品A由用户U作出改变,且将其转发到复制品B时,该改变最初在A处(由U)作出的事实丢失了。若B将此改变转发到复制品C,则这是在B的授权而不是在A的授权下完成的。这就导致下述限制:若不信任一个复制品对一个项目作出它自己的改变,它不能转发由其它复制品作出的改变。
在启动同步服务时,由同步控制应用程序完成。同步服务人格化SCA的身份,并在该身份下完成所有操作(本地的和远程的)。作为说明,观察到用户U不能使本地同步服务从远程存储平台检索对用户U不具有读访问的项目的改变。
4.可管理性
监视复制品的分布式共同体是复杂的问题。同步服务可使用“扫描(sweep)”算法来收集和分发关于该复制品的状态的信息。扫描算法的属性确保关于所有所配置的复制品的信息最终被收集,且检测到该失败(无响应)的复制品。
在每个复制品上可得到共同体范围的监视信息。可在任意选取的复制品上运行监视工具,以检查此监视信息并作出管理决策。在受影响的复制品上必须直接作出配置改变。
J.传统文件互操作性
如上提到,至少在某些实施例中,本发明的存储平台旨在被实施为计算机***的硬件/软件接口***的整体部分。例如,本发明的存储平台可被实施为如Microsoft Windows家族操作***的整体部分。在这方面,存储平台API成为操作***API的一部分,应用程序通过它与操作***交互。因此,存储平台成为装置,应用程序通过它将信息存到操作***上,且从而基于项目的存储平台的数据模型替代了这一操作***的传统文件***。例如,当在Microsoft Windows家族操作***中实施时,存储平台可替代在该操作***中实现的NTFS文件***。当前,应用程序通过由Windows家族操作***展现的Win32API来访问NTFS文件***的服务。
然而,应认识到,完全用本发明的存储平台替代NTFS文件***需要重新编码现有的基于Win32的应用程序,且那样的重新编码可能是不合需要的,因此本发明的存储平台提供与如NTFS等现有文件***的某种互操作性是有益的。从而,在本发明的一个实施例中,存储平台使依赖于Win32编程模型的应用程序能同时访问存储平台的数据存储以及传统的NTFS文件***的数据存储的内容。为此,存储平台使用作为Win32命名***台支持通过Win32 API访问存储在存储平台卷中的文件和目录。
关于此功能的另外细节能在先前通过引用结合于此的有关专利中找到。
K.存储平台API
存储平台包括API,它使应用程序能访问上面讨论的存储平台的特征和能力,并访问存储在数据存储中的项目。本节描述本发明的存储平台的存储平台API的一个实施例。关于此功能的细节能在通过引用结合于此的有关专利中找到,为方便起见在下面总结此信息的某一些。
参考图18,包含文件夹是一个项目,它包含与其它项目的持有关系,且与通常概念的文件***文件夹等价。每个项目“包含”在至少一个包含文件夹中。
图19示出按本实施例的存储平台API的基本体系结构。存储平台API使用SQL客户机1900与本地数据存储302对话,并还使用SQL客户机1900与远程数存储(如数据存储340)对话。本地存储还可使用DQP(分布式查询处理器)或通过上述的存储平台同步服务(“Sync”)与远程数据存储340对话。存储平台API322还担当数据存储通知的桥接器API,将应用程序的下标传送到通知引擎,并如上所述将通知路由到应用程序(如应用程序350a、350b或350c)。在一个实施例中,存储平台API 322还定义受限制的“提供者”体系结构,使得它能访问MicrosoftExchange和AD中的数据。
图20示意性地表示存储平台API的各种组件。存储平台AP包括下列组件:(1)数据类2002,它代表存储平台元素和项目类型;(2)运行库架构2004,它管理对象的持久性并提供支持类2006;以及(3)工具2008,它用于从存储平台模式生成CLR类。
从给定模式得出的类的分层结构直接反应了该模式中类型的分层结构。作为例子,考虑在如图21A和图21B中所示的联系人模式中定义的项目类型。
图22示出操作中的运行库架构。运行库架构如下操作:
1.应用程序350a、350b或350c绑定到存储平台的项目。
2.架构2004创建对应于绑定项目的ItemContext对象2202,并将其返回给应用程序。
3.应用程序提交在此ItemContext(项目上下文)上的Find(寻找),以得到项目的集合;返回的集合在概念上是对象图2204(由于关系)。
4.应用程序改变、删除和***数据。
5.应用程序通过调用Update()方法保存改变。
图23示出“FindAll(寻找所有)”操作的执行。
图24示出从存储平台模式生成存储平台API类的过程。
图25示出文件API所基于的模式。存储平台API包括处理文件对象的名字空间。该名字空间被称为System.Storage.Files。System.Storage.Files中的类的数据成员直接反映了存储在存储平台存储中的信息;此信息是从文件***对象的“升级”或使用Win32API本机地创建。System.Storage.Files名字空间具有两个类:FileItem(文件项目)和DirectoryItem(目录项目)。这些类的成员及其方法可通过审阅图25中的模式图来预测。FileItem和DirectoryItem是从存储平台API只读的。为修改它们,必须使用System.IO中的Win32API或类。
对于API,编程接口(或简称之为接口)可以被视为用于令代码的一个或多个片断能与由代码的一个或多个其它片断提供的功能进行通信或对其进行访问的任一机制、过程、协议。或者,编程接口可以被视为能够通信地耦合至其它计算机的一个或多个机制、方法、函数调用、模块等的***的组件的一个或多个机制、方法、函数调用、模块、对象等。上述语句中的术语“代码片断”意在包括代码的一个或多个指令或代码行,并包括,如,代码模块、对象、子例程、函数等等,无论应用的术语是什么、或代码片断是否被单独编译、或代码片断是否被提供为源码、中间码或对象代码、代码片断是否在运行时***或进程中使用、或它们是否位于同一或不同机器上或跨多个机器分布、或由代码片断表示的功能是否完全由软件、完全由硬件或硬件和软件的组合来实现。
概念上,编程接口可以被一般地察看,如图30A或图30B所示的。图30A示出了接口“接口1”为管道,第一和第二代码片断通过该管道进行通信。图30B示出了接口包括接口对象I1和I2(可以是或不是第一和第二代码片断的部分),它们令***的第一和第二代码片断能通过介质M进行通信。在图30B中,可以认为接口对象I1和I2为同一***的单独接口,并且也可以认为对象I1和I2加上介质M构成了接口。尽管图30A和30B示出了双向流程以及该流程的每一侧上的接口,某些实现可仅具有一个方向上的信息流(或如下所述没有信息流),或仅具有一侧的接口对象。作为示例而非局限,诸如应用编程或程序接口(API)、入口点、方法、函数、子例程、远程过程调用和组件对象模型(COM)接口等术语包含在编程接口的定义之内。
这类编程接口的方面可包括第一代码片断向第二代码片断发送信息的方法(其中,“信息”以其最广泛的意义使用,并包括数据、命令、请求等等);第二代码片断接收信息的方法;以及该信息的结构、序列、语法、组织、模式、定时和内容。在这一点上,只要信息以接口所定义的方式传输,底层传输介质本身可以对接口的操作不重要,无论该介质是有线还是无线,或两者的组合。在某些情况下,在常规意义上,当一个代码片断仅访问由第二代码片断执行的功能时,信息可不在一个或两个方向上传输,因为信息传输可以是或者通过另一机制(如,信息被放置在与代码片断之间的信息流分离的缓存、文件等中)或者不存在。这些方面的任一个或所有可以在给定的情况下重要,如,取决于代码片断是否是松耦合或紧耦合配置的***的一部分,并且因此该列表应当被认为是说明性的而非限制。
编程接口的这一概念对本领域的技术人员是已知的,并且可以阅读上述本发明的详细描述而清楚这一概念。然而,有其它方法来实现编程接口,并且除非明显地排除,这些方法也由所附权利要求书包含在内。这些其它方法看似比图30A和30B的视图更精密或复杂,但是它们仍执行类似的功能来完成同一整体结果。现在简要描述编程接口的某些说明性替换实现。
分解:可以通过将通信***成多个离散通信来间接地实现从一个代码片断到另一个的通信。这在图31A和31B中示意性地描述。如图所示,可以按照功能的可分组来描述某些接口。由此,可以分解图30A和30B的接口功能来达到相同的结果,如同可以在数学上提供24,或2乘2乘3乘2一样。因此,如图31A所示,可以细分由接口“接口1”提供的功能以将该接口的通信变换成多个接口“接口1A”、“接口1B”、“接口1C”等,而达到相同的结果。如图31B所示,由接口I1提供的函数可以被细分成多个接口I1a、I1b、I1c等,而达到相同的结果。类似地,从第一代码片断接收信息的第二代码片断的接口I2可以被分解成多个接口I2a、I2b、I2c等。当分解时,包括在第一代码片断中的接口的数量不需要匹配包括在第二代码片断中的接口的数量。在图31A或31B的任一情况下,接口“接口1”和I1的功能性精神分别与图30A和30B的保持相同。接口的分解也可遵从联合、通信和其它数学性质,使得分解较难识别。例如,命令操作可以是不重要的,并且因此由接口完成的功能可以在达到该接口之前由另一段代码或接口较好地完成,或者由***的单独组件执行。此外,编程领域的普通技术人员可以理解有各种方式来作出不同的函数调用而达到相同的结果。
重定义:在某些情况下,可能忽略、添加或重定义编程接口的某些方面(如参数),而仍达到预期的结果。这在图32A和32B中示出。例如,假定图30A的接口“接口1”包括函数调用Square(input,precision,output)(平方),它包括三个参数,input(输入)、precision(精度)和output(输出),并且由第一代码片断向第二代码片断发布。如果中间参数precision在给定的情形下无关紧要,如图32A所示,它也可以被忽略或甚至由meaningless(无意义)(在这一情况下)参数来替换。也可以添加无关紧要的additional(另外)参数。在任一情况下,只要在输入由第二代码片断平方之后返回输出,就可以达到square(平方)的功能。Precision也有可能对计算***的某一下游或其它部分是极有意义的参数;然而,一旦认识到precision对计算平方这一有限目的不是必需的,它可以被替换或忽略。例如,不是传递一个有效的pricision值,而是在不对结果产生不利影响的情况下传递诸如出生日期等无意义的值。类似地,如图32B所示,接口I1由接口I1′替换,它被重新定义来忽略或向接口添加参数。接口I2可类似地被重定义为接口I2′,它被重定义来忽略不必要的参数,或可在别处处理的参数。此处的要点是在某些情况下,编程接口可包括对某一目的而言所不需要的方面,诸如参数,因此可以忽略或重定义它们,或在别处处理它们用于其它目的。
内嵌代码:合并两个单独的代码模块的一些或全部功能也是可行的,使得它们之间的“接口”改变形式。例如,图30A和30B的功能可以被分别转化到图33A和33B的功能。在图33A中,图30A的先前的第一和第二代码片断被合并成包含两者的模块。在这一情况下,该代码片断仍可以彼此通信,但是该接口可以适用于更适合单个模块的形式。由此,例如,正式的调用(Call)和返回(Return)语句将不再必需,但是依照接口“接口1”的类似的处理或响应仍是有效的。类似地,如图33B所示,图30B的部分(或所有)接口I2可以内嵌地写入接口I1来形成接口I1″。如图所示,接口I2被划分成I2a和I2b,并且接口部分I2a内嵌在接口I1中书写代码来形成接口I1″。对于具体的示例,考虑图30B的接口1执行函数调用square(input,output),它由接口I2接收,在由第二代码片断处理传递到input的值(对其求平方)之后,它被使用output传递回已求平方的结果。在这一情况下,由第二代码片断执行的处理(对input求平方)可以由第一代码片断在不调用该接口的情况下执行。
脱离:可以通过将通信***成多个离散的通信来间接地完成从一个代码片断到另一个的通信。这在图34A和34B中示意性地描述。如图34A所示,提供了中间件的一个或多个片断(脱离接口(Divorce Interface),因为它们从原始的接口脱离的功能和/或接口函数),以转化第一接口“接口1”上的通信,使得它们符合不同的接口,在本情况下为“接口2A”、“接口2B”和“接口2C”。这可以在这样一种情况中完成,例如,依照“接口1”协议设计应用的已安装基础与如操作***进行通信,但是然后改变该操作***来使用不同的接口,在本情况下为接口“接口2A”、“接口2B”和“接口2C”。要点是改变了由第二代码片断使用的原始接口,使得它不再与第一代码片断所使用的接口兼容,因此使用中介来令旧接口和新接口兼容。类似地,如图34B所示,可以使用脱离接口DI1引入第三代码片断以从接口I1接收信息,并使用脱离接口DI2引入第三代码片断以向例如接口I2a和I2b发送接口功能,重新设计接口I2a和I2b以使用DI2,但是提供相同的功能性结果。类似地,DI1和DI2可共同工作以将图30B的接口I1和I2的功能转换成一新操作***,而提供相同或类似的功能性结果。
重写:再一种可能的变化是动态地重写代码,使用别的东西来替换接口的功能,而仍达到相同的总体结果。例如,可以有一种***,其中,向执行环境(如由.Net框架提供的环境、Java运行时环境或其它类似的运行时刻类型环境)中的及时(Just-in-Time)(JIT)编译器或解释器提供了中间语言(如Microsoft IL、JavaByteCode等)中呈现的代码片断。可以书写JIT编译器以动态地将通信从第一代码片断转化到第二代码片断,即,令它们符合第二代码片断(原始或不同的第二代码片断)所需要的不同接口。这在图35A和35B中有描述。如图35A中所看见的,这一方式类似于上述的脱离情形。它可以在这样一种情况下完成,例如,依照“接口1”协议设计应用的已安装基础操作***进行通信,然后改变该操作***以使用不同的接口。JIT编译器可以用于令已安装基础应用的空中通信符合操作***的新接口。如图35B所描述的,可以应用这一动态重写接口的方法以进行动态分解,或者改变接口。
应当注意,上述通过替换实施例实现与接口相同或相似的结果的情形也可以以各种方式串行、并行或与其它干预代码组合。由此,上文呈现的替换实施例并非相互穷尽,并且可以被混合、匹配和组合以产生与图30A和30B中所呈现的一般情形相同或等效的情形。也应当注意,如同大多数编程构造,本发明可能未描述达到与接口相同或相似的功能的其它类似的方式,但是它们仍由本发明的精神和范围来表示,即,应当注意,它至少部分地是由作为接口的值的基础的接口表示的功能或由其启用的有利结果。
III.扩展和继承
本发明的一个基础概念是利用项目,它在一定程度上用由模式描述的并由硬件/软件接口***实施的复杂结构、行为和操作来模型化真实世界应用对象。为提供丰富的子类型化功能,并且在本发明的各种实施例中,硬件/软件接口***(为了方便,在下文中将简称为“WinFS”)可提供一种机制,通过它可以使用“扩展”来扩展项目(和项目类型)。扩展提供附加的数据结构(属性,关系等)到已经存在的项目类型结构。
如前面在本文中讨论的(并且特别是在章节II.E.6.(a)和II.F.3中讨论的),尽管是要为存储平台提供模式的初始集合,但在至少有些实施例中存储平台允许客户包括独立的软件销售商(ISV)创建新的模式(即,新的项目和嵌套元素类型)。由于由存储平台模式的初始集合定义的项目类型或嵌套元素类型不精确地符合ISV应用的需求,因此有必要允许ISV定制类型。这是用扩展的概念来允许的。扩展是强类型化实例但(a)它们不能独立地存在并且(b)它们必须附着于项目或嵌套元素。而且,除了解决模式可扩展性的需求,扩展还要解决“多重类型化”问题。由于在有些实施例中存储平台不支持多重继承或者重叠子类型,因此应用可以使用扩展作为模型化重叠类型实例的方式(例如,一个文档可以是“合法文档”,也可以是“安全文档”)。
A.类型***
在本发明的各种实施例中,WinFS类型***提供一种定义数据的结构的机制。类型***用于表示存储在WinFS中的数据。WinFS类型在WinFS模式中声明。WinFS模式定义一个名字空间,它用作一组类型和其它WinFS模式元素的逻辑分组。WinFS模式可使用WinFS模式定义语言(SDL)(它可能使用XML语言)来声明。下面是一个可能的模式声明的例子:
<Schema Namespace=″System.Storage″>
Type definitions
</Schema>
WinFS模式也用作类型版本化单元。WinFS定义若干引导***的***模式。这些是System.Storage模式名字空间,它包含***中根类型的类型声明,和System.Storage.WinFS模式名字空间,它声明***中所有基本标量类型。
WinFS类型***声明一组简单的标量类型。这些类型用作WinFS类型***中所有其它类型的最基本的构件块。这些类型在模式名字空间System.Storage.WinFS中声明。下面的表定义基本类型集合。
WinFS类型 |
受管SQL类型 |
CLR类型 |
描述 |
String |
SqlString |
String |
可变长度Unicode数据具有最大长度为2^31个字符长度。使用“max”(最大)关键字长度可以从1-4000个字符固定或者不受约束。 |
Binary |
SqlBinary |
Byte[] |
可变长度的二进制数据具有最大长度为2^32个字节长度。使用“max”(最大)关键字长度可以从1-8000个字节固定或者不受约束。 |
Boolean |
SqlBoolean |
Boolean |
能够为NULL的布尔值 |
Byte |
SqlByte |
Byte |
单个无符号字节 |
Int16 |
SqlInt16 |
Int16 |
从-2^15(-32,768)到2^15-1(32,767)的整数数据 |
Int32 |
SqlInt32 |
Int32 |
从-2^31(-2,147,483,648)到2^31-1(2,147,483,647)的整数(整数)数据 |
Int64 |
SqlInt64 |
Int64 |
从-2^63(-9223372036854775808)到2^63-1(9223372036854775807)的整数(整数)数据 |
Double |
SqlDouble |
Double |
浮点精度数数据从-3.40E+38到3.40E+38 |
Single |
SqlSingle |
Single |
浮点精度数数据从-1.79E+308到1.79E+308 |
Decimal |
SqlDecimal |
Decimal |
SQLDecimal具有比CLRDecimal类型较大的值范围。在存储器中精度总是28个数 |
| | |
字且比例为0。 |
DateTime |
SqlDateTime |
DateTime |
日期和时间,从1753年1月1日到9999年12月31日,具有三百分之一秒或3.33秒的精确度 |
Guid |
SqlGuid |
Guid |
全球唯一标识符(GUID) |
Xml |
SqlXmlReader |
XmlReader |
对于里程碑B,WinFS.Xml将被映射到“String”类型。真正的XML数据类型支持预期在里程碑C中。 |
Stream |
TBD |
TBD |
二进制数据类型,使用支持文件流的存储用于有效访问。这个类型将在里程碑C中支持。 |
WinFS枚举是一个标量类型,它声明一组命名的常数,称为值列表。枚举类型可以在可以使用标量类型的任何地方使用。这里是枚举声明的例子:
<Enumeration Name=″Gender″>
<Value Name=″Male″/>
<Value Name=″Female″/>
</Enumeration>
枚举值是基于零的。在上面的例子中Gender.Male表示值0而Gender.Female表示值1。
复杂类型是由名字和一组属性定义的。属性是类型的成员字段,并且是由名字和类型定义的。属性的类型可以是标量(包括枚举类型)或者可以是其它复杂类型。可以用作属性的类型的WinFS类型被称为嵌套类型。嵌套类型的实例可以只作为复杂WinFS类型的属性的属性值存在--该实例嵌套在一个复杂类型的实例内。嵌套类型是使用NestedType(嵌套类型)模式元素声明的。这里是有效类型声明的一些例子:
<NestedType Name=″Address″BaseType=″System.Storage.NestedObject″>
<Property Name=″Street″Type=″WinFS.String″Size=″256″
Nullable=″false″/>
<Property Name=″City″Type=″WinFS.String″Size=″256″
Nullable=″false″/>
<Property Name=″State″Type=″WinFS.String″Size=″256″
Nullable=″false″/>
<Property Name=″Country″Type=″WinFSString″Size=″256″
Nullable=″false″/>
</NestedType>
<ItemType Name=″Person″BaseType=″System.Storage.Item″>
<Property Name=″Name″Type=″WinFS.String″Size=″256″
Nullable=″false″/>
<Property Name=″Age″Type=″WinFS.Int32″
Nullable=″false″Default=″1″/>
<Property Name=″Picture″Type=″WinFS.Binary″Size=″max″/>
<Property Name=″Addresses″Type=″MultiSet″MultiSetOfType=″Address″/>
</ItemType>
对于类型String和Binary的属性,必须指定Size(尺寸)属性。这个属性指定包含在Property(属性)中的值的最大尺寸。属性可以使用Nullable属性可选地声明能够为null的约束。这个属性的值为“false(假)”表示应用在创建该类型的实例时必须提供一个值。另一个可选的Property(属性)属性是Default(默认)属性,它指定Property(属性)的默认值。这个值将在实例创建时被赋给Property(属性),如果应用没有提供它的话。
在上例中Addresses(地址)属性是MultiSet(多重设置)类型的。MultiSet(多重设置)类型的属性也称为多值属性。在本例中MultiSet(多重设置)包含一组Address(地址)类型的实例。MultiSet(多重设置)与集合相似。它可以包含零或多个复杂类型的实例。在MultiSet(多重设置)中的实例的类型必须是复杂嵌套类型。MultiSet(多重设置)类型不支持WinFS标量类型(包括枚举类型)的实例。MultiSet(多重设置)类型的属性不能是能够为null的并且不能有默认值。
WinFS支持类型的单一继承。在WinFS中的所有类型必须从一个且只能在一个WinFS类型上继承。继承的类型称为导出类型并且从其导出这个类型的类型称为基类型。在WinFS声明元素中的BaseType(基类型)属性中的基类型。假定类型A从基类型B导出,而B进而从类型C导出。类型C是类型A和类型B的祖先类型。类型A是类型B和C的子孙类型。存储在WinFS中的数据实例始终是单一类型的实例。然而可以将数据实例视为一组包含该类型及其所有祖先类型的类型的实例。对于作为这样一组类型的实例的数据实例,调用不是在最后导出(most-derived)类型的组中的任何其它类型的祖先的类型。单独类型化的数据实例是就是一个最后导出类型的实例。通常,将单独类型化的元素的最后导出类型称为它的类型。导出类型继承在其基类型中声明的所有属性。导出类型可以声明新的属性但不能覆盖在基类型中定义的属性。在导出类型中声明的属性必须不使用与基类型的属性相同的名字。
在数据模型中继承的主要优点来自于继承类型的可代换性。考虑下面的例子:
<NestedType Name=″Name″BaseType=″System.Storage.NestedObject″>
<Property Name=″FirstName″Type=″WinFS.String″/>
<Property Name=″LastName″Type=″WinFS.String″/>
</Nestedype>
<NestedType Name=″NameWithMiddleInitial″BaseType=″Name″>
<Property Name=″MiddleInitial″Type=“WinFS.String″/>
</NestedType>
<NestedType Name=″Person″BaseType=″System.Storage.Item″>
<Property Name=″RealName″Type=″Name″/>
<Property Name=″OtherNames″Type=″MultiSet″MultiSetOfType=″Name″/>
</NestedType>
在上面的例子中,类型Person(个人)具有类型为Name(名字)的属性RealName(真实名字)和作为一组Name(名字)类型的属性OtherNames(其它名字)。通常要求属性RealName(真实名字)只有其类型为Name(名字)的实例。然而,通过继承,允许单值实例为RealName(真实名字)的值,只要Name(名字)类型是该元素的最后导出类型的祖先之一。因此,NameWithMiddleInitial(具有中间首字母的名字)的实例将允许为属性RealName(真实名字)的值。
扩展相同的规则以设置属性。属性OtherNames(其它名字)包含一组元素。对于每个单独类型化实例(它们是该集合的一个成员),该实例的最后导出类型必须具有Name(名字)作为它的祖先之一。因此,在OtherNames(其它名字)集合中的一些实例可以是Name(名字)类型的实例,尽管其它实例可能是NameWithMiddleInitial(具有中间首字母的名字)类型的实例。
继承也支持方便的查询,因为有可能在WinFS***中找出某个类型的所有实例。当查找一个类型的所有实例时,查询引擎也将返回所有其最后导出类型是这个类型的子孙的实例。然而,只有项目、扩展和关系类型(不是属性类型)支持这些操作。对于嵌套类型(又叫嵌套元素、属性或复杂属性类型),只有包含在单个多重设置属性内的实例支持该操作。
B.类型家族
总之,WinFS类型***定义四个不同的类型系列:
·嵌套元素类型(又叫嵌套类型或属性类型)
·项目类型
·关系类型
·扩展类型
每个类型系列在WinFS类型***中具有一个不同的属性和用法集合。System.Storage模式名字空间声明四种类型用作每个类型系列的根类型。下面的章节详细地描述这些类型***。
1.嵌套元素类型
不像其它WinFS类型系列,嵌套类型可以用作复杂WinFS类型的属性的类型。嵌套类型的实例只可以嵌套在另一个复杂类型的实例内。然而,嵌套类型的实例不能被全局查询--即,应用不能编写一个简单的查询来返回在WinFS存储器中一个给定嵌套类型的所有实例。
2.项目类型
WinFS项目是其祖先是System.Storage.Item类型的类型的实例。这个类型是作为项目类型系列的根的复杂类型。System.Storage.Item声明了一个名为ItemID(项目ID)类型为Guid的属性。这是项目的一个特殊属性,用作项目的主关键字。保证这个属性的值对于一个给定WinFS存储器中的项目是唯一的。这个属性是不能够为null的,并且必须由应用在创建项目类型的实例时赋值。ItemID(项目ID)属性也是不可变的--它从不改变并且必须不被重复使用。
查询引擎可以返回WinFS存储器中给定项目类型的实例。这个查询可返回该类型及其所有类型子孙类型的所有实例。本文稍后描述项目在WinFS***操作语义中具有的中心角色。
3.关系类型
关系类型使关系能够存在于项目之间。WinFS关系类型描述二进制关系,其中指定一个项目为源并且指定另一个项目为目标。关系是其祖先是System.Storage.Relationship类型的类型的实例。这个类型是关系类型层次结构的根。System.Storage.Relationship类型声明下列属性:
·SourceItemID(源项目ID)--作为关系实例的源的项目的ItemID(项目ID)
·RelationshipID(关系ID)--相对于源项目的关系的唯一标识符;(SourceItemID(源项目ID),RelationshipID(关系ID))对形成WinFS中关系的主关键字
·TargetItemId(目标项目ID)--关系的目标的ItemID(项目ID)
·Mode(方式)--3种可能的关系实例方式之一:Holding(持有)、Embedding(嵌入)或Reference(引用)
·Name(名字)--包含关系的名字用于持有关系
·IsHidden(是否隐藏)--布尔属性,应用可以可选地使用它来过滤不需要被显示的关系
SourceItemID(源项目ID)、RelationshipID(关系ID)、TargetItemId(目标项目ID)和Mode(方式)属性值是不可变的。它们在关系实例创建时间被赋值并且不能改变。
关系类型声明为具有下列附加约束的复杂类型:
·源和目标端点规范:每个端点指定名字和被引用项目的类型
·关系类型的实例的所允许方式:关系实例不能具有在关系声明中不允许的Mode(方式)属性的值
这里是关系声明的例子:
<RelationshipType Name=″DocumentAuthor″
BaseType=″System.Storage.Relationship″
AllowsHolding=″true″
AllowsEmbedding=″false″
AllowsReference=″true″>
<Source Name=″Document″Type=″Core.Document″/>
<Target Name=″Author″Type=″Core.Contact″/>
<Property Name=″Role″Type=″WinFS.String″/>
<Property Name=″DisplayName″Type=″WinFS.String″/>
</RelationshipType>
DocumentAuthor(文档作者)关系是用实例对Holding(持有)或Reference(引用)的限制来声明的。这意味着DocumentAuthor(文档作者)关系的实例可以有具有值Mode=″Reference″或Mode=″Holding″的实例。不允许具有值Mode=″Embedding″的实例。
关系声明项目类型“Core.Document”的名为“Document(文档)”的源端点和项目类型“Core.Contact”的目标端点。关系还声明了两个附加属性。关系实例与项目分开地存储和访问。所有关系实例可从全局扩展视图访问。可以编写一个查询来返回给定关系类型的所有实例。
给定一个项目,所有该项目为源的关系可以基于关系的SourceItemID(源项目ID)属性来枚举。同样,对于一个给定的项目,在同一存储器中该项目为目标的所有关系可以使用关系的TargetItemId(目标项目ID)属性来枚举。
a)关系语义
下面的章节描述不同关系实例方式的语义:
持有关系:持有关系用于模型化目标项目的基于引用计数的寿命管理。一个项目可以是零或多个关系到项目的源端点。不是嵌入的项目的项目可以是一个或多个持有关系的目标。目标项目必须与关系实例在同一存储器中。
持有关系实施目标端点的寿命管理。持有关系实例和作为目标的项目的创建是原子操作。可以创建以同一项目为目标的附加的持有关系。当最后一个具有一个给定项目作为目标端点的持有关系实例被删除时,目标项目也被删除。
在关系声明中指定的端点项目的类型将在关系的实例创建时被实施。端点项目的类型在建立关系之后不能被改变。
持有关系在形成WinFS项目名字空间时扮演一个关键角色。所有持有关系参与名字空间声明。在关系声明中的“Name(名字)”属性相关于源项目声明目标项目的名字。这个相关名字对于所有源自一个给定项目的持有关系是唯一的并且不能是null。这个相关名字的有序列表从根项目开始到一个形成项目的完整名字的给定项目。
持有关系形成有向非循环图(DAG)。当持有关系创建时,***保证不产生循环,因而保证项目名字空间形成DAG。对于WinFS名字空间和项目路径的更多信息,参考“WinFS名字空间”规范。
嵌入关系:嵌入关系模型化目标项目的寿命的独占控制的概念。它们支持复合项目的概念。嵌入关系实例和作为目标的项目的创建是原子操作。一个项目可以是零或多个嵌入关系的源。然而,一个项目可以是一个且仅一个嵌入关系的目标。作为嵌入关系的目标的项目不能是持有关系的目标。目标项目必须与关系实例在同一存储器中。
在关系声明中指定的端点项目类型将在关系的实例被创建时实施。端点项目的类型不能在建立关系之后改变。嵌入关系不参与WinFS名字空间。嵌入关系的Name(名字)属性值必须是null。
引用关系:引用关系不控制它引用的项目的寿命。引用关系不保证目标的存在,也不保证如在关系声明中指定的目标类型。这意味着引用关系可以是虚悬的。而且,引用关系可以引用其它WinFS存储器中的项目。
在WinFS中引用关系将用于模型化项目之间大多数非寿命管理的关系。由于不强制目标的存在,因此引用关系便于模型化松耦合的关系。引用关系可以用于在其它WinFS存储器(包括存储在其它机器上)中的目标项目。嵌入关系不参与WinFS名字空间。嵌入关系的Name(名字)属性的值必须是null。
b)关系规则和约束
下面附加的规则和约束适用于关系:
·一个项目必须是(就一个嵌入关系)或者(一或多个持有关系)的目标。一个例外是根项目。一个项目可以是零或多个引用关系的目标。
·作为嵌入关系目标的项目不能是持有关系的源。它可以是引用关系的源。
·一个项目不能是持有关系的源,如果它是从文件提升的。它可以是嵌入关系和引用关系的源。
·一个从文件提升的项目不能是嵌入关系的目标。
当关系类型A是从基关系类型B导出时,下列规则适用:
·关系类型A可以进一步限制端点类型。端点类型必须是基关系B中的相应端点类型的子类型。如果端点被进一步限制,则必须为该端点声明一个新名字。如果不限制端点,则端点的规范是可选的
·关系类型A可以进一步限制在基关系中声明的所允许的实例方式。受限制的实例方式集合必须是所允许的实例类型的基类型的子集。
·端点的名字视为属性名字:它们不与属性的名字或者端点的名字或者它的基类型相同。
·源和目标元素是可选的,如果相应的端点类型没有被所导出的关系进一步限制
这里是从在本文上面定义的DocumentAuthor(文档作者)关系导出的关系类型的声明的例子:
<RelationshipType Name=″LegalDocumentAuthor″
BaseType=″Core.DocumentAuthor″
AllowsHolding=″false″
AllowsEmbedding=″false″
AllowsReference=″true″>
<Source Name=″LegalDocument″Type=″Legal.Document″/>
<Property Name=″CaseNumber″Type=″WinFS.String″/>
</RelationshipType>
LegalDocumentAuthor(合法文档作者)关系还限制源端点但不限制目标端点。源端点类型是Legal.Document,它从Core.Document导出。目标端点在本例中没有被进一步限制,因此省略了目标元素。关系还进一步限制所允许的实例方式。它不允许Holding(持有)方式并且仅保留的允许方式是引用。
4.扩展类型
WinFS扩展是其祖先是System.Storage.Extension类型的类型的实例。这个类型是为扩展类型系列的根的复杂类型。
·System.Storage.Extension定义两个属性:
·ItemID(项目ID)-与扩展相关联的项目的ItemID(项目ID)
·ExtensionID(扩展ID)--扩展相关于ItemID(项目ID)的唯一标识符。(ItemID(项目ID),ExtensionID(扩展ID))对唯一标识扩展实例。
下面的限制适用于扩展类型:
·扩展类型实例不能独立于项目存在。具有同一ItemID(项目ID)作为扩展ItemID(项目ID)的项目类型实例必须在扩展类型实例创建之前存在于存储器中。如果具有给定ItemID(项目ID)的项目不存在,则不能创建扩展。当该项目被删除时,具有同一ItemID(项目ID)的所有扩展被删除。
·一个给定的最后导出扩展类型的至多一个实例可以与一个单独的项目相关联。
·扩展不能是关系的源和目标。
可以与给定项目类型相关联的扩展的类型上没有约束。允许任何扩展类型来扩展任何项目类型。当不同扩展类型的多个实例附着到一个项目时,它们在结构和行为两方面都彼此无关。扩展实例与项目分开地存储和访问。所有扩展实例可从全局扩展视图访问。可以编写一个查询来返回给定类型的扩展的所有实例,不管它们与什么类型的项目相关联。扩展的ItemID(项目ID)表示它们属于哪一个项目并且可以用于从全局项目视图检索相应的项目对象。而且,给定一个项目,所有与该项目相关联的扩展实例可以使用扩展的ItemID(项目ID)属性来枚举。
C.增强的功能
在本发明的若干实施例中,硬件/软件接口***利用扩展和继承以便形式化各种项目之间的关系,从而增强查询多个项目的能力。
1.继承
图36示出一系列相互联系的项目和它们的关系的子集。Document(文档)项目3602和Contact(联系人)项目3604是直接由指定的关系3606相关的,在本例中,关系3606是“作者关系”--即,Contact(联系人)3604是Document(文档)3602的“作者”。在本例中,Picture(照片)项目3622、Music(音乐)项目3624和Special(特殊)项目3626都从Document(文档)项目3604继承,因为每个项目的类型是Document(文档)项目类型的子类型。同样,Person(个人)项目3642和Organization(组织)项目3644从Contact(联系人)项目3604继承。在本发明的若干实施例中,这些继承的项目(Person(个人)3622、Music(音乐)3624、Special(特殊)3626、Person(个人)3642和Organization(组织)3644)不仅继承相应双亲项目(Document(文档)3602和Contact(联系人)3604)的属性,而且它们还继承在这两个双亲项目之间指定的关系。例如,Person(个人)3622继承与Contact(联系人)3664的关系3662,与Person(个人)3642的关系3664和与Organization(组织)3644的关系3666。一个相似的关系集合也由所示的每个其它项目继承。
然而,重要的是注意,关系继承性不是自动的并且不在每个上下文中发生。例如,描述何时一个类型可以被继承的属性(即,继承性控制)本身是不可继承的。继承性参数是由硬件/软件接口***保存和调整的。
2.扩展
图37A示出用于应用专用目的的项目的标准子类型化的缺点。在本附图中,Contact(联系人)可由四个应用,APP1,APP2,APPX和APPY访问。APP1和APP2访问标准Contact(联系人),但APPX和APPY每一个需要一个扩展的联系人对象(添加附加的字段),因而导出Contact′和Contact″,它们每个从Contact(联系人)继承。然而,问题是现在存在基本Contact(联系人)项目的三个不同的实例--一个在Contact(联系人)中,一个在Contact′中,以及一个在Contact″中。
这个问题的部分解决方案,如图37B所示,要扩展Contact(联系人)的属性以包括要求这样的应用所需要的字段。在这种情况下,扩展Contact(联系人)以包括由APPX要求的附加字段。然而,直接扩展一个项目诸如Contact(联系人)的字段只能进行一次,因而APPY不能使用这个方法。
在本发明的一个实施例中,更全面的解决方案是用与Contact(联系人)本身不同和单独的扩展来扩展Contact(联系人)。这样,APPX可以扩展Contact(联系人)以包括它的APPX附加字段,同时APPY也可以扩展Contact(联系人)以包括它的APPY附加字段。随后这些扩展是可搜索的和可查询的,并且因而这些扩展支持多重类型化的形式用于硬件/软件接口***。
IV.结论
如之前所示,本发明针对用于组织、搜索以及共享数据的存储平台。本发明的存储平台扩展并且扩大了现有文件***和数据库***之外的数据存储的概念,并且被设计为用于所有类型的数据的存储,包括结构化的、非结构化的、或者半结构化的数据例如关系(表列)数据、XML,以及一种被称作项目的新形式的数据。通过其共同存储函数和模式化的数据,本发明的存储平台允许用于客户、知识工作者以及企业的更有效的应用开发。它提供了丰富的并且可扩展的应用编程接口,所述接口不仅可以使用其数据模型中固有的性能,而且包含并扩展了现有文件***和数据库访问方法。可以理解,在不脱离其宽泛的发明概念的情况下,可以对以上所述的实施例进行的改变。因此,本发明并不限于所公开的特殊实施例,而是旨在由所附权利要求所规定的覆盖本发明的精神和范围内的所有改变。
如根据以上所述变得很明显的,本发明的各种***、方法、以及方面的所有或者一部分可以以程序代码(即,指令)的形式来体现。这种程序代码可以被存储在计算机可读介质上,例如磁的、电的或者光的存储介质,在非限定情况下包括软盘、CD-ROM、CD-RW、DVD-ROM、DVD-RAM、磁带、闪速存储器、硬盘驱动器、或者其它机器可读存储介质,其中当程序代码被载入到机器例如计算机或服务器中并由机器执行时,所述机器就变成用于实施本发明的装置。本发明还可以以在一些传输介质上被传输的程序代码的形式来体现,在传输介质上例如在电线或者电缆上、通过光纤、在网络上,包括因特网或内部网,或者通过任何其它形式的传输,其中,当程序代码被接收并且被载入到机器例如计算机中并且由机器执行时,所述机器就变成用于实施本发明的装置。当在通用处理器上被实现时,所述程序代码与处理器相结合,以便提供类似于特定逻辑电路的操作的唯一装置。