用于基于项目的存储平台中的数据建模的系统和方法

文档序号:6419776阅读:222来源:国知局

专利名称::用于基于项目的存储平台中的数据建模的系统和方法
技术领域
:本发明一般涉及信息存储和检索领域,尤其涉及用于在计算机化系统中组织、搜索和共享不同类型的数据的活动存储平台。
背景技术
:在最近十年中,单个盘的容量每年增长约百分之70(70%)。摩尔(Moore)定律精确地预测了在过去数年中中央处理单元(CPU)能力的惊人增长。有线和无线技术已经提供了数量上巨大的连接和带宽。假设当前趋势持续,在数年内一般的膝上计算机将具有约万亿字节(TB)的存储并包含数百万个文件,而5千亿字节(500GB)的驱动器成为常见的。消费者使用他们的计算机主要用于通信和组织个人信息,不论它们是传统的个人信息管理器(PIM)风格的数据还是如数字音乐或照片那样的媒体。数字内容的量和存储原始字节的能力已经大量地增长;然而消费者可用于组织和统一此数据的方法却跟不上步伐。知识工人花费大量时间来管理和共享信息,某些研究估计,知识工人花费15-25%的时间在与无效信息有关的活动上。另外研究估计,典型的知识工人每天约花费2.5小时搜索信息。开发者与信息技术(IT)部门投资大量的时间与金钱来构建他们自己的用于公用存储抽象的数据存储,以表示如人、地方、时间和事件等事项。这不仅导致重复的工作,还形成公用数据的孤岛,没有共同搜索或共享那些数据的机制。仅考虑当今在运行MicrosoftWindows操作系统的计算机上有多少地址簿。如电子邮件客户端和个人财务程序那样的许多应用程序保留各自的地址簿,且在每个那样的程序分别维护的地址簿数据应用程序之间只有很少共享。因而,财务程序(如MicrosoftMoney)不与在电子邮件联系人文件夹(如MicrosoftOutlook中的联系人文件夹)中维护的地址共享支付人的地址。确实,许多用户具有多个设备,在这些设备之间和包括到如MSN和AOL等商业服务的手机电话号码的各种附加来源之间应该在逻辑上同步它们的个人数据;然而共享文档的协作大部分是通过将文档附到电子邮件消息来完成的—这是手动的且低效的。缺乏协作的一个原因是组织计算机系统中的信息的传统方法集中在使用基于文件—文件夹—目录的系统(“文件系统”),来基于用于存储文件的存储介质的物理组织的抽象将多个文件组织到文件夹的目录分层结构中。在1960年代开发的Multics操作系统被认为是在操作系统级上使用文件、文件夹和目录来管理可存储数据单元的先驱。具体而言,Multics在文件的分层结构中使用符号地址(从而引入文件路径的概念),其中文件的物理地址对用户(应用程序和最终用户)是不透明的。此文件系统完全不考虑任何单个文件的文件格式,且在文件中及文件之间的关系在操作系统级上被认为是无关的(即,与分层结构中文件的位置不同)。由于Multics的出现,在操作系统级上可存储的数据被组织成文件、文件夹和目录。这些文件一般包括放在由文件系统维护的一特定文件中的文件分层结构本身(“目录”)。此目录进而维护对应于该目录中所有其它文件和那些文件在分层结构(这里指文件夹)中的节点位置的条目的列表。这是本领域中近40年的状态。然而,虽然提供了驻留在计算机的物理存储系统中的信息的合理表示,但是文件系统是物理存储系统的抽象,因而文件的利用需要在用户处理什么(具有上下文、特征以及与其它单元的关系的单元)和操作系统提供什么(文件、文件夹和目录)之间的间接(解释)层。结果,用户(应用程序和/或最终用户)只好强制把信息单元放入文件系统结构,即使这样做是低效的、不一致的、或不希望的。此外,现有的文件系统关于在各个文件中存储的数据的结构知之甚少,因此,大多数信息在文件中保持封闭,只能被写那些数据的应用程序访问(和可理解)。因此,缺乏信息的模式描述和管理信息的机制,导致形成数据的先进先出存储缓冲区(silo),只有很少数据能在各先进先出存储缓冲区之间共享。例如,许多个人计算机(PC)用户具有5个以上各异的存储,它们包含有关他们在某一层上交互的人的信息—如Outlook联系人、在线账户地址、Windows地址簿、Quicken受款人和即时消息(IM)伙伴列表—因为组织文件向这些PC用户提出重要的挑战。由于大多数现有的文件系统利用嵌套的文件夹隐喻来组织文件和文件夹,因此当文件数量增加时,为维持灵活且有效的组织模式所必需的努力变得十分惊人。在这些情况下,具有单个文件的多重分类是非常有用的;然而使用现有文件系统中的硬和软链接是麻烦且难以维护的。过去已作了若干不成功的尝试来克服文件系统的缺点。这些以前尝试中的某一些已经涉及使用内容可定址的存储器来提供可以通过内容而不是通过物理地址来访问数据的机制。然而,这些努力被证明是不成功的,因而虽然内容可定址的存储器对由如高速缓存和存储器管理单元等设备的小规模使用被证明是有用的,但对如物理存储介质等设备的大规模使用由于各种原因尚不可能,因此那样的解决方案简直不存在。已作出使用面向对象的数据库(OODB)系统的其它尝试,但是这些尝试虽然带有强烈的数据库的特征,且良好的非文件表示,但在处理文件表示方面并不有效,并不能重现在硬件/软件接口系统级上基于分层结构的文件及文件夹的速度、效率和简单性。诸如试图使用SmallTalk(和其它派生方法)的其它尝试在处理文件和非文件表示方面被证明相当有效,但缺乏有效地组织和利用在各种数据文件之间存在的关系所必需的数据库特征,因此那种系统的整体有效性是不可接受的。使用BeOS(和其它那样操作系统研究)的又一种尝试尽管能够胜任适当地表示文件的同时又提供某些必要的数据库特征,在处理非文件的表示上被证明是不够的,这是传统文件系统同样的核心缺点。数据库技术是存在类似挑战的另一专业领域。例如,虽然关系型数据库模型已取得很大的商业上的成功,实际上独立软件分销商(ISV)一般运用了关系型数据库软件产品(如MicrosoftSQLServer)中可得到的功能一小部分。相反,应用程序与那样产品的大多数交互是以简单的“gets”和“puts”的形式。对此虽然有若干容易明白的原因(如作为平台或数据库的不可知),一个常被忽略的关键的原因是数据库没有必要提供主要商业应用程序分销商确实需要的精确抽象。例如,虽然真实世界具有如“客户”或“订单”等“项目”的概念(以及订单的嵌入的“行式项目”作为其中的项目和项目本身),而关系型数据库只在表和行的方面来谈论。结果,虽然应用程序可能希望具有在项目级上的一致性、锁定、安全和/或触发器的方面(只列出一些),通常数据库只在表/行级上提供这些特征。尽管若每个项目映射到数据库某个表的单个行也能工作得很好,但在带多个行式项目的订单的情况下,存在一个项目实际上要映射到多个表的原因,且在此情况下,单个关系型数据库系统不能确切地提供正确的抽象。因此,应用程序必须在数据库的顶层构建逻辑以提供这些基本抽象。换言之,基本关系模型不提供在其上容易开发高级应用程序的存储数据的足够平台,因为基本关系模型需要在应用程序和存储系统之间的间接层,其中只在某些情况的应用程序中可以看到数据的语义结构。尽管某些数据库分销商正将高级功能构建到他们的产品中(如提供对象关系能力,新的组织模型等),至今尚没有哪个提供需要的全面解决方案,其中真正的全面解决方案是为有用的域抽象(如“个人”、“位置”、“事件”等)提供有用的数据模型抽象(如“项目”、“扩展”、“关系”等)的解决方案。考虑到现有数据存储和数据库技术中的上述缺点,需要一种新的存储平台,它提供了一种改进的能力以便组织、搜索和共享计算机系统中的所有类型的数据—一种存储平台,它在现有的文件系统和数据库系统之外扩展和扩大了数据平台,并且被设计为存储所有类型的数据。本发明满足这一需求。发明概述以下概述提供了对本发明的各方面的综述。该综述并非旨在提供对本发明的所有重要方面的详尽描述,也不旨在定义本发明的范围。相反,本概述旨在用作对以下的详细描述和附图的介绍。本发明针对一种用于组织、搜索和共享数据的存储平台。本发明的存储平台在现有文件系统和数据库系统之外扩展和扩大了数据存储的概念,并被设计成储存所有类型的数据,包括结构化的、非结构化的或半结构化的数据。依照本发明的一方面,本发明的存储平台包括在数据库引擎上实现的数据存储。在本发明的各实施例中,数据库引擎包括具有对象关系扩展的关系型数据库引擎。该数据存储实现支持数据的组织、搜索、共享、同步和安全性的数据模型。具体的数据类型在模式中描述,且该平台提供了一种扩展模式集以定义新数据类型(本质上是由模式提供的基本类型的子类型)的机制。一种同步能力有助于在用户或系统间共享数据。提供了类似文件系统的能力,它允许该数据存储与现有文件系统的互操作性,而不存在这种传统文件系统的限制。一种改变跟踪机制提供了跟踪数据存储的改变的能力。该存储平台还包括一组应用程序接口,它们使得应用程序能够访问该存储平台的上述的所有能力,并且能够访问在模式中描述的数据。依照本发明的另一方面,由该数据存储实现的数据模型按照项目、元素和关系定义了数据存储的单元。项目是可在数据存储中存储的数据单元,并且可以包括一个或多个元素和关系。元素是类型的实例,包括一个或多个字段(此处也被称为属性)。关系是两个项目之间的链接。(如此处所使用的,这些以及其它特定的术语可以被大写,以便将它们从类似所使用的其它术语分离,然而,并不是旨在区别对待被大写的术语例如“Item”和不被大写时的同一个术语,例如“item”,并且不应假设或暗示这种区别。)依照本发明的另一方面,一种计算机系统包括多个项目,其中每个项构成可由硬件/软件接口系统操纵的离散的可存储信息单元;多个项目文件夹,它们构成了所述项目的组织结构;以及用于操纵多个项目的硬件/软件接口系统,并且其中每个项目属于至少一个项目文件夹,并且可以属于一个以上项目文件夹。依照本发明的另一方面,一种计算机系统包括多个项目,其中,每一项目构成可由硬件/软件接口系统操纵的离散信息单元,且与从持久存储中导出相反,项目或某些项目属性值可以被动态地计算。换言之,该硬件/软件接口系统不要求项目被存储,并且支持某些操作,诸如枚举当前项目集的能力,或是给出项目在存储平台上的标识符(在描述应用程序编程接口或API的一节中更完整地描述)而检索项目的能力—例如,项目可以是蜂窝电话的当前位置,或从温度传感器读到的温度。依照本发明的另一方面,一种用于计算机系统的硬件/软件接口系统还包括由该硬件/软件接口系统管理的多个关系互连的项目,其中所述硬件/软件接口系统操纵多个项目。依照本发明的另一方面,一种用于计算机系统的硬件/软件接口系统,其中所述硬件/软件接口系统操纵具有可由所述硬件/软件接口系统理解的属性的多个离散信息单元。依照本发明的另一方面,一种用于计算机系统的硬件/软件接口系统包括核心模式,以便定义所述硬件/软件接口系统可以理解,并且能够以一种预定的和可预测的方式直接进行处理的一组核心项目。依照本发明的另一方面,公开了一种用于操纵用于计算机系统的硬件/软件接口系统中的多个离散信息单元(“项目”)的方法,所述方法包括将所述项目与多个关系互连,以及在硬件/软件接口系统级上管理所述关系。依照本发明的另一特征,该存储平台的API为存储平台模式集中定义的每个项目、项目扩展和关系提供了数据类。此外,该应用程序编程接口提供了一组框架类,它们为所述数据类定义了一组公共行为,并且与数据类一起为存储平台API提供了基本的编程模型。依照本发明的另一特征,该存储平台API提供了简化的查询模型,它以将应用程序员从底层数据库引擎的查询语言的细节隔离开的方式,使得应用程序员能够形成基于数据存储中的项目的各种属性的查询。依照本发明的存储平台API的又一方面,该API收集由应用程序对项目作出的改变,并且然后将它们组织到实现该数据存储的数据库引擎(或任何种类的存储引擎)所需的正确更新中。这使得应用程序员能够对在存储器中项目进行改变,而将数据存储更新的复杂性留给API。通过其公共存储基础和被模式化的数据,本发明的存储平台能够为消费者、知识工作者和企业作出更有效的应用程序开发。它提供了丰富且可扩展的应用程序编程接口,该接口不仅使得其数据模型中所固有的能力可用,而且还包含并扩展了现有文件系统和数据库的访问方法。通过阅读以下本发明的详细描述和附图,可以清楚本发明的其它特征和优点。附图简述当结合所附的附图进行阅读时,可以更好地理解上面的概述以及下面对本发明的详细描述。出于解释本发明的目的,在附图中示出了本发明的各个方面的示例性实施例;然而,本发明不限于所公开的具体方法和手段。在附图中图1是表示其中可结合本发明的各方面的计算机系统的框图;图2是示出了被分为3个组件组的计算机系统的框图硬件组件、硬件/软件系统接口组件和应用程序组件;图2A示出了用于被分组到基于文件的操作系统中的目录内的文件夹中的文件的传统的基于树的分层结构;图3是示出依照本发明的存储平台的框图;图4示出了本发明的各实施例中项目、项目文件夹和类别之间的结构关系;图5A示出了项目的结构的框图;图5B是示出图5A的项目的复杂属性类型的框图;图5C是示出“Location(位置)”项目的框图,其中进一步描述(明确地列出)其复杂类型;图6A示出了作为基础模式中找到的项目的子类型的项目;图6B是示出了图6A的子类型项目的框图,其中明确地列出了其继承的类型(除了其直接属性之外);图7是示出了基本模式的框图,该基本模式包括其两个顶层类类型,即Item(项目)和PropertyBase(属性基),以及从其中导出的附加基础模式类型;图8A是示出核心模式中的项目的框图;图8B是示出核心模式中的属性类型的框图;图9是示出项目文件夹、其成员项目以及项目文件夹和其成员项目之间的互连关系的框图;图10是示出了类别(它本身也是项目)、其成员项目以及类别及其成员项目之间的互连关系的框图;图11是示出依照本发明的存储平台的数据模型的引用类型层次的图;图12是示出依照本发明的一个实施例关系是如何被分类的图;图13是示出依照本发明的一个实施例的通知机制的图;图14是示出其中两个事务都向同一个B树插入新记录的示例的图;图15示出了依照本发明的一个实施例的数据改变检测过程;图16示出了示例性的目录树;图17示出了依照本发明的一方面其中现有的基于目录的文件系统的文件夹被移动到该存储平台数据存储中的示例;图18示出了依照本发明的一方面包含文件夹的概念;图19示出了存储平台API的基本体系结构;图20示意性地表示了存储平台API栈的各个组件;图21A和21B是示例性联系人模式(项目和元素)的图形表示;图22示出了依照本发明的一方面的存储平台API的运行时框架;图23示出了依照本发明的一个实施例的“FindAll”操作的执行;图24示出了依照本发明的一方面用于从存储平台模式生成存储平台API类的过程;图25示出了依照本发明的另一方面File(文件)API所基于的模式;图26是示出依照本发明的一个实施例用于数据安全目的的访问掩码格式的示意图;图27(a)、(b)、(c)给出了依照本发明的一方面的一个实施例从现有的安全区域内划分出的一个新的同样地保护的安全区域;图28是示出依照本发明的一方面的一个实施例的项目搜索视图的概念的示意图;图29是示出依照本发明的一个实施例的示例性项目层次的示意图;发明详细描述目录A.示例性计算环境………………………………………………………………16B.传统的基于文件的存储………………………………………………………19II.用于组织、搜索和共享数据的新存储平台……………………………………20A.词汇表…………………………………………………………………………20B.存储平台综述…………………………………………………………………21C.数据模型………………………………………………………………………221.项目…………………………………………………………………………232.项目标识……………………………………………………………………26a)项目引用…………………………………………………………………26(1)ItemIDReference……………………………………………………26(2)ItemPathReference…………………………………………………26b)引用类型分层结构………………………………………………………273.项目文件夹和类别…………………………………………………………274.模式…………………………………………………………………………28a)基础模式…………………………………………………………………28b)核心模式…………………………………………………………………295.关系…………………………………………………………………………30a)关系声明…………………………………………………………………31b)持有关系…………………………………………………………………32c)嵌入关系…………………………………………………………………33d)引用关系…………………………………………………………………33e)规则和约束………………………………………………………………34f)关系的排序………………………………………………………………346.可扩展性……………………………………………………………………38a)项目扩展…………………………………………………………………39b)扩展NestedElement类型………………………………………………42D.数据库引擎……………………………………………………………………431.使用UDT的数据存储实现…………………………………………………442.项目映射……………………………………………………………………453.扩展映射……………………………………………………………………474.嵌套元素映射………………………………………………………………485.对象身份……………………………………………………………………486.SQL对象命名………………………………………………………………497.列命名………………………………………………………………………508.搜索视图…………………………………………………………………50a)项目……………………………………………………………………50(1)主项目搜索视图…………………………………………………51(2)类型化的项目搜索视图…………………………………………51b)项目扩展………………………………………………………………52(1)主扩展搜索视图…………………………………………………52(2)类型化的扩展搜索视图…………………………………………52c)嵌套的元素……………………………………………………………53d)关系……………………………………………………………………53(1)主关系搜索视图…………………………………………………53(2)关系实例搜索视图………………………………………………539.更新………………………………………………………………………5410.改变跟踪及墓碑………………………………………………………54a)改变跟踪………………………………………………………………55(1)“主”搜索视图中的改变跟踪……………………………………55(2)“类型化的”搜索视图中的改变跟踪……………………………56b)墓碑……………………………………………………………………56(1)项目墓碑……………………………………………………………57(2)扩展墓碑……………………………………………………………57(3)关系墓碑……………………………………………………………57(4)墓碑清除……………………………………………………………5811.助手API和函数…………………………………………………………58a)函数[System.Storage].GetItem……………………………………58b)函数[System.Storage].GetExtension……………………………58c)函数[System.Storage].GetRelationship…………………………5912.元数据…………………………………………………………………59a)模式元数据……………………………………………………………59b)实例元数据……………………………………………………………59E.安全性………………………………………………………………………591.综述………………………………………………………………………592.安全模型的详细描述……………………………………………………63a)安全描述符结构………………………………………………………64(1)访问掩码格式……………………………………………………65(2)类属访问权限……………………………………………………65(3)标准访问权限……………………………………………………65b)项目专用权限…………………………………………………………66(1)文件和目录对象专用权限………………………………………66(2)WinFSItemRead……………………………………………………67(3)WinFSItemReadAttributes………………………………………68(4)WinFSItemWriteAttributes……………………………………68(5)WinFSItemWrite…………………………………………………68(6)WinFSItemAddLink………………………………………………69(7)WinFSItemDeleteLink……………………………………………69(8)删除项目的权限…………………………………………………69(9)复制项目的权限…………………………………………………69(10)移动项目的权限…………………………………………………70(11)查看项目上的安全策略的权限…………………………………70(12)改变项目上的安全策略的权限…………………………………70(13)没有直接等效物的权限…………………………………………703.实现………………………………………………………………………71a)在容器中创建新项目…………………………………………………71b)向项目添加显式ACL…………………………………………………71c)向项目添加持有关系…………………………………………………72d)从项目删除持有关系…………………………………………………72e)从项目中删除显式ACL………………………………………………72f)修改与项目相关联的ACL……………………………………………72F.通知和改变跟踪……………………………………………………………731.存储改变事件……………………………………………………………73a)事件……………………………………………………………………73b)监视程序………………………………………………………………742.改变跟踪和通知生成机制………………………………………………75a)改变跟踪………………………………………………………………76b)时间标记管理…………………………………………………………77c)数据改变检测—事件检测……………………………………………77G.同步…………………………………………………………………………781.存储平台到存储平台的同步……………………………………………78a)同步(Sync)控制应用程序……………………………………………79b)模式注释………………………………………………………………79c)同步配置………………………………………………………………80(1)共同体文件夹—映射……………………………………………81(2)概况…………………………………………………………81(3)时间表………………………………………………………82d)冲突处理………………………………………………………82(1)冲突检测……………………………………………………83(a)基于知识的冲突…………………………………………83(b)基于约束的冲突…………………………………………83(2)冲突处理……………………………………………………83(a)自动冲突分解……………………………………………84(b)冲突日志记录……………………………………………84(c)冲突检查和分解…………………………………………85(d)复制品的收敛和冲突分解的传播………………………852.对非存储平台数据存储的同步……………………………………85a)同步服务………………………………………………………86(1)改变枚举……………………………………………………86(2)改变应用……………………………………………………87(3)冲突分解……………………………………………………87b)适配器实现……………………………………………………873.安全性………………………………………………………………884.可管理性……………………………………………………………88G.传统文件互操作性……………………………………………………881.互操作性模型………………………………………………………892.数据存储特征………………………………………………………90a)非卷………………………………………………………………90b)存储结构…………………………………………………………90c)不移植所有文件…………………………………………………90d)对存储平台文件的NTFS名字空间访问…………………………91e)期望的名字空间/驱动器字母…………………………………91I.存储平台API…………………………………………………………911.综述…………………………………………………………………912.命名和范围…………………………………………………………923.存储平台API组件…………………………………………………944.数据类………………………………………………………………945.运行时架构…………………………………………………………101a)运行时架构类……………………………………………………101(1)ItemContext…………………………………………………101(2)ItemSearcher………………………………………………102(a)目标类型…………………………………………………102(b)过滤器……………………………………………………102(c)准备搜索…………………………………………………103(d)查找选项…………………………………………………103(3)项目结果流(“FindResult”)……………………………104b)操作中的运行时架构……………………………………………105c)公共编程模式……………………………………………………106(1)打开和关闭ItemContext对象………………………………106(2)搜索对象……………………………………………………107(a)搜索选项…………………………………………………108(b)FindOne和FindOnly……………………………………108(c)搜索ItemContext上的快捷方式………………………109(d)按照ID或路径查找………………………………………109(e)GetSearcher模式………………………………………110(3)更新存储……………………………………………………1106.安全性……………………………………………………………1127.对关系的支持……………………………………………………112a)基础关系类型…………………………………………………113(1)Relationship类…………………………………………113(2)ItemReference类…………………………………………114(3)ItemIdReference类………………………………………114(4)ItemPathReference类……………………………………115(5)RelationshipId结构……………………………………115(6)VirtualRelationshipCollection类……………………116b)生成的关系类型………………………………………………117(1)生成的关系类型…………………………………………118(2)RelationshipPrototype类………………………………118(3)RelationshipPrototpyeCollection类…………………119c)Item类中的关系支持…………………………………………119(1)Item类……………………………………………………119(2)RelationshipCollection类……………………………119d)搜索表达式中的关系支持……………………………………120(1)从项目遍历到关系………………………………………120(2)从关系遍历到项目………………………………………120(3)组合关系遍历…………………………………………………121e)关系支持的示例使用………………………………………………121(1)搜索关系………………………………………………………121(2)从关系导航到源和目标项目…………………………………122(3)从源项目导航到关系…………………………………………123(4)创建关系(以及项目)…………………………………………124(5)删除关系(以及项目)…………………………………………1258.“扩展”存储平台API………………………………………………125a)域行为………………………………………………………………126b)增值行为……………………………………………………………126c)作为服务提供者的增值行为………………………………………1279.设计时架构……………………………………………………………12810.查询形式……………………………………………………………128a)过滤器基础…………………………………………………………129b)类型强制转换………………………………………………………130c)过滤器句法…………………………………………………………13011.遥控…………………………………………………………………131a)API中的本地/远程透明性…………………………………………131b)遥控的存储平台实现………………………………………………132c)访问非存储平台存储………………………………………………132d)与DFS的关系………………………………………………………132e)与GXA/Indigo的关系………………………………………………13212.约束…………………………………………………………………13313.共享…………………………………………………………………134a)表示共享……………………………………………………………135b)管理共享……………………………………………………………135c)访问共享……………………………………………………………135d)可发现性……………………………………………………………13614.Find的语义…………………………………………………………13615.存储平台ContactsAPI……………………………………………136a)System.Storage.Contact的综述…………………………………137b)域行为………………………………………………………………13716.存储平台FileAPI…………………………………………………138a)介绍…………………………………………………………………138(1)在存储平台中反映NTFS卷……………………………………139(2)在存储平台名字空间中创建文件和目录……………………139b)文件模式……………………………………………………………140c)System.Storage.Files的综述……………………………………140d)代码示例……………………………………………………………140(1)打开文件并向其写入…………………………………………140(2)使用查询………………………………………………………141e)域行为………………………………………………………………141J.总结………………………………………………………………………141I.引言本发明的主题用细节来描述,以满足法定的要求。然而,该描述本身不试图限制本专利的范围。相反,本发明者设想要求保护的主题也能以其它方式实施,以结合其它当前和未来的技术来包括类似于本文档所描述的不同的步骤或步骤的组合。此外,虽然术语“步骤”在这里可用于意味着所采用的方法的不同元素,然而该术语不能被解释为隐含这里所揭示的各步骤之间的特定次序,除非明确地描述了各个步骤的次序。A.示例性计算环境本发明的许多实施例可在计算机上执行。图1和下面讨论旨在提供其中实现本发明的合适计算环境的简要描述。虽然不是必需,但本发明的诸方面能以诸如由如客户工作站或服务器的计算机上执行的程序模块的计算机可执行指令的一般上下文中描述。一般而言,程序模块包括例程、程序、对象、组件、数据结构等,它们执行特定任务或实现特定抽象数据类型。此外,本发明可用其它计算机系统配置实现,包括手持设备、多处理器系统、基于微处理器的系统或可编程消费者电子设备、网络PC、小型机、大型机等。本发明还能在分布式计算环境中实现,其中任务由通过通信网络链接的远程处理设备完成。在分布式计算环境中,程序模块能位于本地或远程存储器存储设备中。如图1所示,示例性通用计算系统包括传统的个人计算机20等,它包括处理单元21、系统存储器22和将包括系统存储器的各种系统组件耦合到处理单元21的系统总线23。系统总线23可以是若干种总线结构的任一种,包括存储总线或存储控制器、外围总线、以及使用各种总线体系结构的任一种的局部总线。系统存储器包括只读存储器(ROM)24和随机存取存储器(RAM)25。基本输入/输出系统26(BIOS)包含如在启动时帮助在个人计算机20的诸元件之间传输信息的基本例程,它存储在ROM24中。个人计算机20还可包括读写硬盘(未示出)的硬盘驱动器27、读写可移动磁盘29的磁盘驱动器28、读写如CDROM或其它光介质的可移动光盘31的光盘驱动器30。硬盘驱动器27、磁盘驱动器28和光盘驱动器30分别通过硬盘驱动器接口32、磁盘驱动器接口33和光盘驱动器接口34连接到系统总线23。驱动器及其相关联的计算机可读介质为个人计算机20提供计算机可读指令、数据结构、程序模块和其它数据的非易失性存储。虽然这里描述的示例性环境采用硬盘、可移动磁盘29和可移动光盘31,但本领域的技术人员可以理解,在示例性操作环境中也能使用可存储能由计算机访问的数据的其它类型计算机可读介质,如盒式磁带、闪存卡、数字视频盘、Bernoulli盒式磁带、随机存取存储器(RAM)、只读存储器(ROM)等。类似地,示例环境还可包括许多类型的监视设备,如热敏和安全或火警系统,及其它信息源。若干程序模块能存储在硬盘、磁盘29、光盘31、ROM24或RAM25中,包括操作系统35、一个或多个应用程序36、其它程序模块37和程序数据38。用户能通过如键盘40和定点设备42等输入设备将命令和信息输入到个人计算机20。其它输入设备(未示出)可包括麦克风、操纵杆、游戏垫、圆盘式卫星天线、扫描仪等。这些和其它输入设备常通过耦合到系统总线的串行接口46连接到处理单元21,但也可通过其它接口连接,如并行口、游戏口或通用串行总线(USB)。监视器47或其它类型的显示设备也通过如视频适配器48的接口连接到系统总线23。除监视器47以外,个人计算机通常包括如扬声器和打印机等其它外围输出设备(未示出)。图1的示例系统还包括主机适配器55、小型计算机系统接口(SCSI)总线56和连接到SCSI总线56的外部存储设备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,在计算机系统200的各实施例中,硬件组件202可包括中央处理单元(CPU)21、存储器(ROM24和RAM25)、基本输入/输出系统(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、MacintoshOS和其它硬件/软件接口系统中,文件夹是能作为单个信息单元被检索、移动和处理的文件的集合。这些文件夹进而被组织成称为“目录”(在后面详细讨论)的基于树的分层排列。在如Dos、z/OS和大多数基于Unix的操作系统的其它硬件/软件接口系统中,术语“目录”和/或“文件夹”是可互换使用的,早期的Apple计算机系统(如AppleIIe)使用术语“类别”来代替目录;然而在这里使用时,所有这些术语被看成是同义语并可互换使用,并旨在还包括对分层信息存储结构及其文件夹和文件组件的所有其它等价术语的引用。传统上,目录(又名文件夹的目录)是基于树的分层结构,其中文件被组合成文件夹,文件夹进而按构成目录树的相对节点位置排列。例如,如图2A所示,基于DOS的文件系统的基本文件夹(或“根目录”)212可包括多个文件夹214,其每一个可以还包括另外的文件夹(如特定文件夹的“子文件夹”)216,而这些的每一个又包括另外的文件夹218,直到无限。这些文件夹的每一个可具有一个或多个文件220,虽然在硬件/软件接口系统级上,文件夹中的各个文件除了它们在树形分层结构中的位置外没有什么共同点。不奇怪,将文件组织到文件分层结构的方法间接地反映了用于存储这些文件的典型存储介质(如硬盘、软盘、CD-ROM等)的物理组织。除上述以外,每个文件夹是对其子文件夹和其文件的容器—即,每个文件夹拥有其子文件夹和文件。例如,当文件夹被硬件/软件接口系统删除时,该文件夹的子文件夹和文件也被删除(在每个子文件夹的情况下还递归地包括它自己的子文件夹和文件)。同样,每个文件一般只由一个文件夹拥有,并且虽然文件能被复制且副本位于不同的文件夹,文件的副本本身是不同且独立单元,它与原始文件无直接连接(如对原始文件的改变在硬件/软件接口系统级上不反映到副本文件)。因此在这方面,文件和文件夹在本质上是“物理的”,因为文件夹类似于物理容器来处理,而文件作为这些容器中不同且独立的物理元素来处理。II.用于组织、搜索和共享数据的新存储平台本发明针对用于组织、搜索和共享数据的存储平台。本发明的存储平台在上文讨论的文件系统及数据库系统的种类之外扩展和拓宽了数据平台,并被设计成存储所有类型的数据,包括称为项目的新形式的数据。A.词汇表在这里及在权利要求书中使用的术语有下列意义“项目”是能存储硬件/软件接口系统可访问的信息的单元,不象简单文件,它是具有由硬件/软件接口系统外壳展现给最终用户的所有对象共同支持的基本属性集的对象。项目还具对所有项目类型共同支持的属性和关系,包括允许引入新属性和关系的特征(在下面详细讨论)。“操作系统”(OS)是担当应用程序和计算机硬件之间的中介的特殊程序。在大多数情况下,操作系统包括外壳和内核。“硬件/软件接口系统”是软件、或硬件及软件的组合,它起着计算机系统的底层硬件组件和在计算机系统上执行的应用程序之间的接口的作用。硬件/软件接口系统通常包括(在某些实施例中只包括)操作系统。硬件/软件接口系统还能包括虚拟机管理器(VMM)、公用语言运行库(CLR)或其功能等效物,Java虚拟机(JVM)或其功能等效物、或在计算机系统中代替操作系统或除操作系统外的其它软件组件。硬件/软件接口系统的目的是提供用户能执行应用程序的环境。任何硬件/软件接口系统的目标是使计算机系统便于使用,并以有效方式利用计算机硬件。B.存储平台综述参考图3,依照本发明存储平台300包括在数据库引擎314上实现的数据存储302。在一个实施例中,数据库引擎包括带有对象关系扩展的关系型数据库引擎。在一个实施例中,关系型数据库引擎314包括MicrosoftSQLServer关系型数据库引擎。数据存储302实现支持数据的组织、搜索、共享、同步和安全的数据模型304。在如模式340等模式中描述特定的数据类型,并且存储平台300提供用于采用这些模式并用于扩展这些模式的工具346,这在后面详述。在数据存储302中实现的改变跟踪机制306提供跟踪数据存储的改变的能力。数据存储302还提供安全能力308和升级/降级能力310,这些均在后文详述。数据存储302还提供一组应用程序编程接口312,以向利用该存储平台的其它存储平台组件和应用程序(如应用程序350a,350b和350c)展现数据存储302的能力。本发明的存储平台还包括应用程序编程接口(API)322,使如应用程序350a,350b,和350c等应用程序能访问存储平台的所有上述功能并能访问在模式中描述的数据。应用程序能结合如OLEDBAPI324和MicrosoftWindowsWin32API326等其它API来使用存储平台API322。本发明的存储平台300能向应用程序提供各种服务,包括便于在用户或系统之间共享数据的同步服务330。例如,同步服务330允许与具有与数据存储302相同格式的其它数据存储340的互操作,并访问具有其它格式的数据存储342。存储平台300还提供允许数据存储302与如WindowsNTFS文件系统318等现有文件系统的互操作的文件系统能力。在至少某些实施例中,存储平台320还能向应用程序提供另外的能力,以允许对数据起作用并允许与其它系统的交互。这些能力可具体化为如InfoAgent服务334和通知服务332等附加服务328的形式,以及其它实用程序336的形式。在至少某些实施例中,存储平台以计算机系统的硬件/软件接口系统来实施,或形成其完整的一部分。例如而非限制,本发明的存储平台能用操作系统、虚拟机管理器(VMM)、公用语言运行库(CLR)或其功能等效物、或Java虚拟机(JVM)或其功能等效物来实施,或形成其完整的一部分。通过其公用的存储基础和模式化的数据,本发明的存储平台使消费者、知识工人和企业作能够更有效地进行应用程序的开发。它提供了丰富和可扩展的编程表面区域,不仅可得到其数据模型中固有的能力,还能包括和扩展现有文件系统和数据库访问方法。在下述描述中及在各附图中,本发明的存储平台300可称作“WinFS”。然而使用此名字指存储平台仅是为了描述方便,并不试图作出任何限制。C.数据模型本发明的存储平台300的数据存储302实现一种数据模型,它支持对驻留在存储中的数据的组织、搜索、共享、同步和安全。在本发明的数据模型中,“项目”是存储信息的基本单元。该数据模型提供一种机制,用于声明项目和项目的扩展、用于建立项目之间的关系、以及用于将项目组织到项目文件夹和类别中,这些将在下文中更充分描述。该数据模型依赖于两个原语机制类型和关系。类型是提供支配类型的实例的形式的格式的结构。格式被表达成属性的有序组。属性是给定类型的值或一组值的名字。例如,USPostalAddress(美国邮政地址)类型具有属性Street(街道)、City(城市)、Zip(邮编)、State(州),其中Street、City和State是String类型,而Zip是Int32类型。Street可以是多值(即一组值),允许地址对Street属性具有一个以上值。系统定义能在其它类型构造中使用的某些原语类型,包括String(串)、Binary(二进制)、Boolean(布尔)、Int16(16位整数)、Int32(32位整数)、Int64(64位整数)、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。数据模型允许定义类型间的子类型—超类型关系。也称为基本类型(BaseType)关系的子类型—超类系型关系以如下方式定义,若类型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)模式中的特定类型的项目(核心模式在下面详细讨论)。Location项目具有多个属性,包括EAddress(电子邮件地址)、MetropolitanRegion(都市地区)、Neighborhood(街坊)、和PostalAddress(邮政地址)。每个项目的特定类型属性紧跟属性名表示,并用冒号(“”)与属性名分开。在类型名的右边,对该属性类型允许的值的数量在方括号(“[]”)之间表示,其中冒号(“”)右边的星号(“*”)表示未规定的和/或无限制的数量(“许多”)。冒号右边的“1”表明最多一个值。冒号左边的零(“0”)表明该属性是可任选的(可以完全没有值)。冒号左边的“1”表明必须至少有一个值(该属性是必须的)。Neighborhood和MetropolitanRegin均是“nvarchar”类型(或等效类型),它是预定义的数据类型或“简单类型”(这里用缺少大写来表示)。然而EAddress和PostalAddress分别是类型EAddress和PostalAddress的已定义类型或“复杂类型”(这里用大写标记)的属性。复杂类型是从一个或多个简单数据类型和/或从其它复杂类型导出的类型。项目的属性的复杂类型还构成“嵌套元素”,因为复杂类型的细节嵌套入直接项目中以定义其属性,而涉及这些复杂类型的信息用具有这些属性的项目来维持(在该项目的边界内,如后面讨论)。类型的这些概念是众知的,且容易被本领域的技术人员理解。图5B是示出复杂属性类型PostalAddress和EAddress的框图。PostalAddress属性类型定义属性类型PostalAddress的项目可期望有零个或一个City(城市)值、零个或一个CountryCode(国家代码)值、零个或一个MailStop(信箱代码)值、和任何数量(零到许多)PostalAddress类型等等。以此方式,定义了项目中的特定属性的数据的形状。EAddress属性类型如所示类似地定义。虽然这里在本申请中可任选地使用,表示Location项目中复杂类型的另一方法是用其中列出的每个复杂类型的各个属性得出该项目。图5C是示出Location项目的框图,在其中进一步描述其复杂类型。然而应该理解,在图5C中Location项目的另一种表示恰是对图5A中示出的同一个项目。本发明的存储平台还允许子类型化,从而一个属性类型是另一个的子类型(其中一个属性类继承另一个父属性类型的属性)。类似于但不同于属性及它们的属性类型,项目继承性地表示其自己的Item(项目)类型,它也是子分类的主题。换言之,本发明的若干实施例中的存储平台允许一个项目是另一个项目的子类型(从而一个项目继承另一个父项目的属性)。此外,对本发明的各种实施例,每个项目是“Item”项目类型的子类型,后者是在基础模式中找到的第一且基本的项目类型(基础模式也在后面详细讨论)。图6A示出一项目(在此实例中为Location项目)为在基础模式中找到的Item项目类型的子类型。在此图中,箭头表示Location项目(与所有其它项目一样)是Item项目类型的子类型。作为从中导出所有其它项目的基本项目的Item项目类型具有若干如ItemId(项目ID)等重要属性和各种时间标记,从而定义了操作系统中所有项目的标准属性。在本图中,Item项目类型的这些属性被Location所继承,并从而成为Location的属性。表示从Item项目类型继承的Location项目中属性的另一种方法是用来自其中列出的父项目的每个属性类型的各个属性得出Location。图6B是示出Location项目的框图,其中除了其直接属性外描述其继承的类型。应注意和理解,此项目是图5A中示出的同一项目,虽然在本图中,Location用所有其属性示出,包括直接属性(在本图及图5A中示出)和继承属性(在本图中示出但未在图5A中示出)(而在图5A中,通过用箭头示出Location项目是Item项目类型的子类型来引用这些属性)。项目是独立的对象,因而若删除一项目,也删除项目的所有直接和继承的属性。类似地,当检索一项目时,接收到的是该项目及其所有直接和继承的属性(包括涉及其复杂属性类型的信息)。本发明的某些实施例可使人们能在检索特定项目时请求属性的子集;然而对许多那样的实施例默认的是在检索时向项目提供所有其直接和继承的属性。此外,项目的属性也能通过添加新的属性到该项目的类型的现有属性而加以扩展。这些“扩展”其后是该项目的真实属性,且该项目类型的子类型可自动地包括扩展属性。项目的“边界”由其属性(包括复杂属性类型、扩展等)来表示。项目的边界也表示在项目上执行的操作的限制,包括复制、删除、移动、创建等。例如在本发明的若干实施例中,当复制项目时,在该项目边界之内的所有内容也被复制。对每个项目,边界包括下列·项目的项目类型,且若该项目是另一项目的子类型(如在所有项目从基础模式的单个项目和项目类型导出的本发明的若干实施例的情况下),是任何适用的子类型信息(即涉及父项目类型的信息)。若要复制的原始项目是另一项目的子类型,该副本也能是该同一项目的子类型。·项目的复杂类型属性和扩展(如果有的话)。若原始项目具有复杂类型(原来的或扩展的)的属性,副本也能具有同一复杂类型。·在“所有权关系”上的项目的记录,即,本项目(“拥有项目”)拥有什么其它项目(“目录项目”)的项目拥有列表。这特别关系到下面充分讨论的项目文件夹和下面说到的所有项目必须至少属于一个项目文件夹的规则。此外,关于嵌入项目(下面更充分讨论),嵌入项目被认为是其中嵌入如复制、删除等操作的项目的一部分。2.项目标识在全局项目空间中用ItemID唯一地标识项目。Base.Item类型定义了存储该项目身份的类型GUID的字段ItemID。一个项目必须在数据存储302中只有一个身份。a)项目引用项目引用是包含定位和标识项目的信息的数据结构。在该数据模型中,定义名为ItemReference(项目引用)的抽象类型,从中导出所有项目引用类型。ItemReference类型定义了名为Resolve(解析)的虚拟方法。Resolve方法解析ItemReference并返回一项目。此方法被ItemReference的具体子类型所覆盖,后者实现给定一引用时检索项目的功能。调用Resolve方法作为存储平台API322的一部分。(1)ItemIDReferenceItemIDReference(项目ID引用)是ItemReference的子类型。它定义了Locator(定位器)和ItemID字段。Locator字段命名(即标识)项目域。它由能将Locator的值解析到项目域的定位器解析方法来处理。ItemID字段是ItemID类型。(2)ItemPathReferenceItemPathReference(项目路径引用)是定义Locator和Path(路径)字段的ItemReference的特殊化。Locator字段标识项目域。它由能将Locator的值解析到项目域的定位器解析方法来处理。Path字段包含以由Locator提供的项目域为根的存储平台名字空间中的(相对)路径。不能在集合运算中使用此类引用。引用一般必须通过路径解析过程来解析。存储平台API322的Resolve方法提供此功能。b)引用类型分层结构上面讨论的引用形式通过图11示出的引用类型分层结构来表示。从这些类型继承的其它引用类型能在模式中定义。它们能在关系声明中用作目标字段的类型。3.项目文件夹和类别如下面将更充分讨论的,项目组能被组织成称为项目文件夹(不要与文件的文件夹混淆)的特殊项目。然而不象大多数文件系统,一个项目可属于多个项目文件夹,使得当项目在一个项目文件夹中被访问和修订时,此修订的项目随后能直接从另一项目文件夹访问。实质上,虽然对一个项目的访问可从不同的项目文件夹发生,事实上真正访问的是同一个项目。然而,项目文件夹不必拥有其所有成员项目,或简单地结合其它文件夹共同拥有项目,使得一个项目文件夹的删除不必要导致项目的删除。然而在本发明的若干实施例中,一个项目必须至少属于一个项目文件夹,使得如果特定项目的唯一项目文件夹被删除,则对某些实施例,该项目被自动被删除,或在另外实施例中,该项目自动地成为默认项目文件夹的成员(例如,“TrashCan(垃圾箱)”项目文件夹在概念上类似于在各种基于文件和文件夹的系统中使用的类似名字文件夹。)如下面更充分讨论的,项目也可属于基于共同描述的特征的类别,特征如(a)项目类型(或类型),(b)特定的直接或继承的属性(或属性),或(c)对应于项目属性的特定值(或值)。例如,包括个人联系人信息的特定属性的项目可自动属于Contact(联系人)类别,具有联系人信息属性的任何项目也自动属于此类别。同样,具有“NewYorkCity(纽约市)”值的位置属性的任何项目可自动属于NewYorkCity(纽约市)类别。类别在概念上不同于项目文件夹之处在于,项目文件夹可包括互相无关的项目(即无共同的描述的特征),而在类别中的每个项目具有对该类别描述的共同类型、属性或值(“共同性”),正是这个共同性形成对它与该类别中其它项目或那些项目之间的关系的基础。此外,虽然在特定文件夹中的项目的成员资格基于该项目的任何特定方面不是强制的,然而对某些实施例,具有在分类上与一类别相关的共同性的所有项目在硬件/软件接口系统级上可自动地成为该类别的成员。概念上,类别也能看作虚拟项目文件夹,其成员资格基于特定查询(如在数据库的上下文中)的结果,而满足此查询的条件(由类别的共同性确定)的项目应构成该类别的成员资格。图4示出在本发明各实施例中在项目、项目文件夹和类别之间的结构关系。多个项目402、404、406、408、410、412、414、416、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)基础模式为了提供创建和使用项目的通用基础,本发明的存储平台的各实施例包括建立用于创建和组织项目及属性的概念性框架的基础模式。基础模式定义了某些特定类型的项目和属性,以及从中进一步导出子类型的这些特定基本类型的特征。使用此基础模式使程序员能在概念上将项目(及其各自的类型)与属性(及其各自的类型)加以区别。此外,基础模式列出所有项目可拥有的基本属性集,因为所有项目(及其对应的项目类型)是从基础模式的此基本项目(及其对应的项目类型)导出的。如图7所示,对于本发明的若干实施例,基础模式定义三个顶层类型Item(项目)、Extension(扩展)和PropertyBase(属性基)。如图所示,通过此基本“Item”项目类型的属性定义了项目类型。相反,顶层属性类型“PropertyBase”没有预定义的属性,仅是一个定位点,从中导出所有其它属性类型,并且所有导出的属性类型通过它互相联系(共同从单个属性类型导出)。Extension类型属性定义该扩展扩展了哪个项目,并定义将一个扩展与另一个项目相区别的标识,因为一个项目可具有多个扩展。ItemFolder(项目文件夹)是Item项目类型的子类型,除了从Item继承的属性外,它表征用于建立到其成员(如果有的话)的链接的关系,尽管Identitykey(身份键)和Property(属性)均是PropertyBase的子类型。CategoryRef(目录引用)进而是IdentityKey的子类型。b)核心模式本发明的存储平台的各种实施例还包括为顶层项目类型结构提供概念框架的核心模式。图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类型(未声明),而必须引用在与关系实例相同的数据存储中的项目。·对持有和嵌入关系,目标端点字段必须是ItemIDReference类型,且它必须引用在与关系实例相同的存储中的项目。对引用关系,目标端点能是任何ItemReference类型,并能引用在其它存储平台数据存储中的项目。·能可任选地声明标量或PropertyBase类型的一个或多个字段。这些字段能包含与该关系相关联的数据。·关系实例被存储在全局关系表中。·每个关系实例唯一地由组合(源ItemID、关系ID)标识。对所有源自给定项目的关系,在给定的源ItemID中关系ID是唯一的,而不管它们的类型。源项目是关系的拥有者。而被指定为拥有者的项目控制关系的生命周期,关系本身和与它们相关的项目分开。存储平台API322提供用于展现与项目相关联的关系的机制。这里是一个关系声明的例子。<RelationshipName=″Employment″BaseType=″Reference″><SourceName=″Employee″ItemType=″Contact.Person″/><TargetName=″Employer″ItemType=″Contact.Organization″ReferenceType=″ItemIDReference″/><PropertyName=″StartDate″Type=″thestorageplatformTypes.DateTime″/><PropertyName=″EndDate″Type=″thestorageplatformTypes.DateTime″/><PropertyName=″Office″Type=″thestorageplatformTypes.DateTime″/></Relationship>这是引用关系的例子。若由源引用所引用的个人项目不存在,则不能创建该关系。而且若该个人项目被删除,在个人和组织之间的关系实例也被删除。然而若组织项目被删除,关系不被删除,而它是悬挂的。b)持有关系持有关系用于基于目标项目的生命周期管理来对引用计数建模。项目可以是项目的零个或多个关系的源端点。不是嵌入项目的项目可以是在一个或多个持有关系中的目标。目标端点引用类型必须是ItemIDReference,且它必须引用在与关系实例相同的存储中的项目。持有关系实施目标端点的生命周期管理。持有关系实例和作为目标的项目的创建是原子操作。可以创建将同一项目作为目标的另外的持有关系实例。当具有给定项目作为目标端点的最后一个持有关系实例被删除时,该目标项目也被删除。在关系声明中指定的端点项目的类型一般在创建该关系的实例时强制。在关系建立之后端点项目的类型不能改变。持有关系在形成项目的名字空间中起着关键作用。它们包含“Name”属性,它定义目标项目相对于源项目的名字。对所有源自给定项目的持有关系,相对名字是唯一的。从根项目开始到给定项目的相对名字的有序列表形成该项目的全名。持有关系形成一有向非循环图(DAG)。在创建持有关系时,系统确保不产生回路,从而确保项目的名字空间形成DAG。虽然持有关系控制目标项目的生命周期,它不控制目标端点项目的操作的一致性。目标项目在操作上独立于通过持有关系拥有它的项目。在作为持有关系的源的项目上的复制、移动、备份和其它操作不影响作为同一关系的目标的项目—例如,备份文件夹项目不自动地备份该文件夹中所有项目(FolderMember(文件夹成员)关系中的目标)。下面是持有关系的例子<RelationshipName=″FolderMembers″BaseType=″Holding”><SourceName=″Folder″ItemType=″Base.Folder″/><TargetName=″Item″ItemType=″Base.Item″ReferenceType=″ItemIDReference″/></Relationship>FolderMember关系使文件夹的概念成为项目的类属集合。c)嵌入关系嵌入关系将目标项目的生命周期的排外控制的概念模型化。它们允许合成项目的概念。嵌入关系实例和作为目标的项目的创建是原子操作。项目能是零个或多个嵌入关系的源。然而一个项目能是一个且仅是一个嵌入关系的目标。作为嵌入关系的目标的项目不能是持有关系的目标。目标端点引用类型必须是ItemIDReference,且它必须引用在与关系实例相同数据存储中的项目。在关系声明中指定的端点项目的类型一般在创建该关系的实例时强制。在关系建立之后端点项目的类型不能改变。嵌入关系控制该目标端点的操作一致性。例如,串行化项目的操作可包括串行化所有源自该项目及所有其目标的所有嵌入关系;复制项目也复制所有其嵌入项目。下面是示例声明<RelationshipName=″ArchiveMembers″BaseType=″Embedding”><SourceName=″Archive″ItemType=″Zip.Archive″/><TargetName=″Member″ItemType=″Base.Item″ReferenceType=″ItemIDReference″/><PropertyName=″ZipSize″Type=″thestorageplatformTypes.bigint″/><PropertyName=″SizeReduction″Type=″thestorageplatformTypes.float″/></Relationship>d)引用关系引用关系不控制它引用的项目的生命周期。尤其是,引用关系不保证目标的存在,也不保证目标的类型如关系声明中指定的那样。这意味着引用关系能是悬挂的。而且引用关系能引用在其它数据存储中的项目。引用关系能看作类似于网页上的链接的概念。下面是引用关系声明的例子<RelationshipName=″DocumentAuthor″BaseType=″Reference″><SourcItemType=″Document″ItemType=″Base.Document″/><TargetItemType=″Author″ItemType=″Base.Author″ReferenceType=″ItemIDReference″/><PropertyType=″Role″Type=″Core.CategoryRef″/><PropertyType=″DisplayName″Type=″thestorageplatformTypes.nvarchar(256)″/></Relationship>在目标的端点允许任何引用类型。参与引用关系的项目可以是任何项目类型。引用关系用于对项目之间的大多数非生命周期管理关系建模。因为不强制目标的存在,引用关系便于对松散耦合的关系建模。引用关系能用于在其它存储,包括在其它计算机上的存储中的目标项目。e)规则和约束下列附加规则和约束应用于关系1.项目必须是(仅一个嵌入关系)或(一个或多个持有关系)的目标。一个例外是根项目。项目能是零个或多个引用关系的目标。2.作为嵌入关系目标的项目不能是持有关系的源。它能是引用关系的源。3.项目若是从文件升级,则不能是持有关系的源。它能是嵌入关系和引用关系的源。4.从文件升级的项目不能是嵌入关系的目标。f)关系的排序在至少一个实施例中,本发明的存储平台支持关系的排序。通过在基本关系定义中的名为“Order(排序)”的属性来完成排序。在Order字段中无唯一性约束。不保证带有同一“Order”属性值的关系的次序,然而保证它们能排序在带较低“Order”值的关系之后并在带较高“Order”字段值的关系之前。应用程序通过在组合(SourceItemID,RelationshipID,Order)上排序得到默认次序的关系。源自给定项目的所有关系实例被排序成单个集合,而不管在集合中关系的类型。然而这保证给定类型(如,FolderMembers)的所有关系是给定项目的关系集合的已排序子集。用于操纵关系的数据存储API312实现一组支持关系的排序的操作。引入下列术语帮助解释那些操作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(或)”来描述属性的逻辑表示,其中由类别描述成员组是具有属性AORB的项目。如本领域的技术人员所理解的,也能使用类似的逻辑运算符(包括但不限于单独的“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类型<TypeName=″Base.Extension″IsAbstract=″True″><PropetyName=″ItemID″Type=″thestorageplatformTypes.uniqueidentified″Nullable=″false″MultiValued=″false″/><PropertyName=″ExtensionID″Type=″thestorageplatformTypes.uniqueidentified″Nullable=″false″MultiValued=″false″/></Type>ItemID字段包含与该扩展关联的项目的ItemID。带此ItemID的项目必须存在。若带给定ItemID的项目不存在,则不能创建扩展。当项目被删除,带同一ItemID的所有扩展被删除。元组(ItemID,ExtensionID)唯一地标识了扩展实例。扩展类型的结构类似于项目类型的结构扩展类型具有字段;字段可以是原语或嵌套元素类型;以及扩展类型可被子分类。下列限制应用于扩展类型扩展不能是关系的源和目标;扩展类型实例不能独立于项目存在;以及扩展类型不能用作在存储平台类型定义中的字段类型对能与给定的项目类型关联的扩展的类型没有约束。任何扩展类型允许扩展任何项目类型。当多个扩展实例被附加到一个项目,它们在结构和行为上彼此独立。扩展实例被分别存储并从项目访问。所有扩展类型实例可从全局扩展视图访问。能组成一有效的查询,它将返回给定类型的扩展的所有实例,而不管它们与什么类型的项目相关联。存储平台API提供可存储、检索和修改项目扩展的编程模型。扩展类型可以是使用存储平台的单个继承模型来子类型化的类型。从一个扩展类型导出创建新的扩展类型。一个扩展的结构或行为不能覆盖或替代项目类型分层结构的结构或行为。类似于项目类型,扩展类型实例能通过与该扩展类型相关联的视图来直接访问。扩展的ItemID表明它们属于哪个项目,并能用于从全局项目视图检索对应的项目对象。为操作一致性的目的,扩展被考虑成项目的一部分。复制/移动、备份/恢复和存储平台定义的其它常用操作可以在作为项目的一部分的扩展上操作。考虑下述例子。在Windows类型集中定义Contact类型。<TypeName=″Contact″BaseType=“Base.Item”><PropertyName=″Name″Type=″String″Nullable=″false″MultiValued=″false″/><PropertyName=″Address″Type=″Address″Nullable=″true″MultiValued=″false″/></Type>CRM应用程序开发者喜欢将CRM应用程序扩展附加到存储在存储平台中的联系人。应用程序开发者定义包含应用程序能处理的附加数据结构的CRM扩展。<TypeName=″CRMExtension″BaseType=″Base.Extension″><PropertyName=″CustomerID″Type=″String″Nullable=″false″MultiValued=″false″/>…</Type>HR应用程序开发者希望也将附加数据附加到联系人。此数据独立于CRM应用程序数据。应用程序开发者还可创建扩展<TypeName=″HRExtension″EBaseType=″Base.Extension″><PropertyName=″EmployeeID″Type=″String″Nullable=″false″MultiValued=″false″/>…</Type>CRMExtension和HRExtension是能附加到联系人项目的两个独立扩展。它们能彼此独立地创建和访问。在上述例子中,CRMExtension类型的字段和方法不能覆盖联系人分层结构的字段和方法。应注意,CRMExtension类型的实例能被附加到不同于联系人的项目类型。在检索联系人项目时,不自动地检索其项目扩展。给定联系人项目,可通过查询全局扩展视图以寻找带同一ItemID的扩展来访问其有关的项目扩展。可通过CRMExtension类型视图来访问系统中所有的CRMExtension扩展,而不论它们属于什么项目。一个项目的所有项目扩展共享同一项目ID。在上述例子中,Contact项目实例和附加的CRMExtension和HRExtension实例共享同一ItemID。下表总结了在Item(项目)、Extension(扩展)和NestedElement(嵌套元素)类型之间的相似性和差别Item、ItemExtension与NestedElementb)扩展NestedElement类型嵌套元素类型不用与项目类型相同的机制来扩展。嵌套元素的扩展用与嵌套元素类型字段相同的机制来存储和访问。数据模型定义了名为Element(元素)的嵌套元素类型的根<TypeName=″Element″IsAbstract=″True″><PropertyName=″ElementID″Type=″thestorageplatformTypes.uniqueidentifier″Nullable=″false″MultiValued=″false″/></Type>NestedElement类型从此类型继承。NestedElement元素类型另外定义一字段,它是多集元素。<TypeName=″NestedElement″BaseType=″Base.Element″IsAbstract=″True″><PropertyName=″Extensions″Type=″Base.Element″Nullable=″false″MultiValued=″true″/></Type>NestedElement扩展在以下方面不同于项目扩展嵌套元素扩展不是扩展类型。它们不属于以Base.Extension类型为根的扩展类型分层结构。嵌套元素扩展与该项目的其它字段一起存储,且不是全局可访问的—不能组成检索给定扩展类型的所有实例的查询。如存储其它嵌套元素(或项目)一样地存储这些扩展。如其它的嵌套集,NestedElement扩展被存在UDT中。它们可通过嵌套元素类型的Extension(扩展)字段来访问。用于访问多值属性的集合接口也用于在类型扩展集上的访问和迭代。下面的表总结和比较了Item扩展和NestedElement扩展。Item扩展与NestedElement扩展D.数据库引擎如上提到,数据存储在数据库引擎上实现。在本实施例中,数据库引擎包括诸如MicrosoftSQLServer引擎等实现SQL查询语言、带有对象关系扩展的关系型数据库引擎。本节按照本实施例描述了数据存储实现的数据模型到关系存储的映射,在逻辑API上提供由存储平台的客户机使用的信息。然而可以理解,当采用不同的数据库引擎时可采用不同的映射。确实,除了在关系型数据库引擎上实现存储平台概念数据模型之外,也可在其它类型数据库上实现,如面向对象和XML数据库。面向对象(OO)数据库系统为编程语言对象(如C++、Java)提供持续性和事务。“项目”的存储平台概念可很好地映射到面向对象系统中的对象,虽然嵌入的集合必须添加给对象。类似继承性和嵌套元素类型等其它存储平台类型概念也映射到面向对象类型的系统。面向对象系统通常已经支持对象身份;因此,项目身份可被映射到对象身份。项目的行为(操作)很好地映射到对象方法。然而,面向对象的系统通常缺乏组织能力并在搜索方面很差。而且,面向对象的系统不提供对非结构化和半结构化数据的支持。为支持这里描述的完全存储平台数据模型,如关系、文件夹和扩展等概念需要添加到对象数据模型。此外,需要实现如升级、同步、通知和安全性等机制。类似于面向对象的系统,基于XSD(XML模式定义)的XML数据库支持基于单继承类型的系统。本发明的项目类型系统可映射到XSD类型模型。XSD也不提供对行为的支持。项目的XSD必须增添项目的行为。XML数据库处理单个XSD文档并缺乏组织和拓宽搜索能力。如面向对象数据库那样,为支持这里描述的数据模型,如关系和文件夹等其它概念需要被结合到该XML数据库;而且需要实现如同步、通知和安全性等机制。1.使用UDT的数据存储实现在本实施例中,在一个实施例中包括MicrosoftSQLServer引擎的关系型数据库引擎314支持内建的标量类型。内建的标量类型是“原有”且“简单”的。它们是原有的意义是,用户不能定义他们自己的类型;它们是简单的意义是,用户不能封装复杂的结构。用户定义的类型(下文称为UDT)通过使用户能通过定义复杂的结构化类型来扩展类型系统,提供了一种用于超过或超越原有的标量类型系统的类型可扩展性的机制。一旦由用户定义,UDT能用于可以使用内建标量类型的类型系统中的任何地方。按本发明的一个方面,存储平台模式被映射到数据库引擎存储中的UDT类。数据存储项目被映射到从Base.Item类型导出的UDT类。类似于项目,扩展也能映射到UDT类并使用继承。根扩展类型是Base.Extension,从它导出所有扩展类型。UDT是CLR类,它具有状态(即数据字段)和行为(即例程)。使用任何受管语言(c#、VB.NET等)定义UDT。UDT方法和操作符能在T-SQL中针对该类型的实例调用。UDT能是行中列的类型、T-SQL中例程的参数的类型、或在T-SQL中变量的类型。以下示例示出了UDT的基础。假定MapLib.dll具有称为MapLib的程序集。在该程序集中,在名字空间BaseTypes下,存在称为Point的类namespaceBaseTypes{publicclassPoint{//返回离指定点的距离。publicdoubleDistance(Pointp){//返回点p和该点之间的距离}//该类中的其它内容}}以下T-SQL代码将类Point绑定到称为Point的SQLServerUDT。第一步调用“CreateAssembly”(创建程序集),它将MapLib程序集加载到数据库。第二步调用“CreateType”(创建类型),以创建用户定义类型“Point”,并将其绑定到受管类型BastTypes.PointCREATEASSEMBLYMaplibFROM′\\myserv\share\MapLib.dll′goCREATETYPEPointEXTERNALNAME′BaseTypes.Point′go一旦被创建,“Point”UDT可用作表中的列,且该方法可以在T-SQL中如下所示地调用CreatetableCities(Namevarchar(20),Statevarchar(20),LocationPoint)--检索城市到坐标(32,23)的距离Declare@ppoint(32,23),@distancefloatSelectLocation::Distance(@p)FromCities存储平台模式到UDT类的映射在高级别上完全是直接的。一般而言,存储平台模式被映射到CLR名字空间。存储平台类型被映射到CLR类。CLR类的继承镜象了存储平台类型的继承,且存储平台属性被映射到CLR类属性。图29所示的项目分层结构在本文档中用作一个示例。它示出了从其中导出所有项目类型的Base.Item类型,以及一组导出的项目类型(例如,Contact.Person和Contact.Employee),其中继承由箭头指示。2.项目映射为了希望项目能够被全局地搜索,并在本实施例的关系型数据中支持继承以及类型可替代性,对在数据库存储中的项目存储的一种可能的实现是在带有类型Base.Item的列的单个表中存储所有项目。使用类型可替代性,能存储所有类型的项目,且可按使用Yukon的“isof(类型)”的操作符的项目类型和子类型来过滤搜索。然而,由于在本实施例中牵涉到与这一方法相关联的额外开销,按顶级类型划分各项目,使得每个类型“家族”的项目存储到单独的表中。在此划分模式中,对每个直接从Base.Item继承的项目类型创建一个表。如上所述,继承下面这些的类型使用类型的可替代性存储在合适的类型家族表中。只有来自Base.Item的第一级继承被专门地处理。对于图29所示的示例项目分层结构,这可得到以下类型家族表createtabeleContact.[Table!Person](_ItemContact.Personnotnull{Changetrackinginformation})createtableDoc.[Table!Document](_ItemDoc.Documentnotnull,{Changetrackinginformation})使用“阴影”表存储所有项目的全局可搜索属性的副本。此表可由存储平台API的Update()方法维护,通过此方法作出所有数据的改变。不象类型家族表,此全局项目表只包含该项目的顶级标量属性,而不是全UDT项目对象。全局项目表的结构如下createtableBase[Table!Item](ItemIDuniqueidentifiernotnullconstraint[PK_Clu_Item!ItemID]pnmarykeyclustered,TypeIDuniqueidentifiernulnull,{AdditionalPropertiesofBase.Item},{Changetrackinginformation})全局项目表允许通过展现ItemID和TypeID(类型ID)导航到存储在类型家族表中的项目对象。ItemID通常唯一地标识数据存储中的项目。可使用这里未予描述的元数据将TypeID映射到类型名和包含该项目的视图。由于通过其ItemID寻找项目在全局项目表的上下文及其它情况下都是常用操作,因此给定了项目的ItemId,提供GetItem()函数来检索项目对象。该函数具有以下声明Base.ItemBase.GetItem(uniqueidentifierItemID)为便于访问和尽可能地隐藏实现的细节,项目的所有查询可以对照在上述项目的表上构建的视图进行。具体而言,对每个项目类型针对合适类型的家族表创建视图。这些类型视图可选择相关联的类型,包括子类型的所有项目。为方便起见,除了UDT对象,视图能对包括继承字段的该类型的所有顶级域展现列。对图29所示的示例项目分层结构的视图如下createviewContact.Personasselect_Item.ItemID,{Base.Item的属性},{Contact.Person的属性},{改变跟踪信息},_ItemfromContact.[Table!Person]--注意Contact.Employee视图使用“where″判定--来限制对Contact.Employee的实例的所找到的项目集createviewContact.Employeeasselect_Item.ItemID,{Base.Item的属性},{Contact.Person的属性},{Contact.Employee的属性},{改变跟踪信息},cast(_ItemasContact.Employee)fromContact.[Table!Person]where_Itemisof(Contact.Employee)createviewDoc.Documentasselect_Item.ItemID,{Base.Item的属性},{Doc.Document的属性},{改变跟踪信息},_ItemfromDoc[Table!Document]--注意Doc.WordDocument视图使用“where”判定--来限制对DocWordDocument的实例的所找到的项目集createviewDoc.WordDocumentasselect_Item.ItemID,{Base.Item的属性},{Doc.Document的属性},{Doc.WordDocument的属性},{改变跟踪信息},cast(_ItemasDoc.WordDocument)fromDoc.[Table!Document]where_Itemisof(Doc.WordDocument)为完整性起见,视图也可在全局项目表上创建。该视图最初可展示与表相同的列createviewBase.ItemasselectItemID,TypeID,{Base.Item的属性},{改变跟踪信息}fromBase.[Table!Item]3.扩展映射扩展非常类似于项目,且具有某些相同要求。如支持继承性的另一根类型,扩展受到存储中许多同样的考虑和折衷比较。为此,对扩展应用类似的类型家族映射,而不是单个表方法。当然,在其它实施例中,可使用单个表方法。在本实施例中,扩展通过ItemID仅与一个项目关联,并包含在项目的上下文中唯一的ExtensionID。扩展表具有以下定义createtableBase.[Table!Extension](ItemIDuniqueidentifiernotnull,ExtensionIDuniqueidentifiernotnull,TypeIDuniqueidentifiernotnull,{Base.Extension的属性},{改变跟踪信息},constraiint[PK_Clu_Extension!ItemID!ExtensionED]primarykeyclustered(ItemIDascExtensionIDasc))如同项目一样,给定包括ItemID和ExtensionID对的身份,可提供一函数用于检索扩展。该函数具有以下声明Base.ExtensionBase.GetExtension(uniqueidentifierItemID,uniqueidentifierExtensionID)类似于项目类型视图,对每个扩展类型可创建视图。假定扩展分层结构与示例项目分层结构平行,具有以下类型Base.Extension、Contact.PersonExtension、Contact.EmployeeExtension。可创建以下视图createviewBase.ExtensionasselectItemID,ExtensionID,TypeID,{Base.Extension的属性},{改变跟踪信息}fromBase.[Table!Extension]createviewContact.[Extension!PersonExtension]asselect_Extension.ItemID,_Extension.ExtensionID,{Base.Extension的属性},{Contact.PersonExtension的属性},{改变跟踪信息},_ExtensionfromBase.[Table!PersonExtension]createviewContact.[Extension!EmployeeExtension]asselect_Extension.ItemID,_Extension.ExtensionID,{Base.Extension的属性},{Contact.PersonExtension的属性},{Contact.EmployeeExtension的属性},{改变跟踪信息},cast(_ExtensionasContact.EmployeeExtension)fromBase.[Table!PersonExtension]where_Extensionisof(Contact.EmployeeExtension)4.嵌套元素映射嵌套元素是可嵌入到项目、扩展、关系、或其它嵌套元素以形成深嵌套结构的类型。类似于项目和扩展,嵌套元素作为UDT实现,但它们存储在项目和扩展中。因此,嵌套元素没有超越它们的项目和扩展容器的存储映射。换言之,在系统中没有直接存储NestedElement类型的实例的表,且没有专门用于嵌套元素的视图。5.对象身份在数据模型中的每一实体,即每个项目、扩展和关系具有唯一的键值。一个项目由其ItemId唯一地标识。扩展由合成键(ItemId,ExtensionId)唯一地标识。关系由合成键(ItemId,RelationId)标识。ItemId,ExtensionId和RelationshipId均是GUID值。6.SQL对象命名在数据存储中创建的所有对象可存储在从存储平台模式名字导出的SQL模式名字中。例如,存储平台基础模式(常称“Base”)可产生在“[System.Storage]”SQL模式中的类型,如“[System.Storage].Item”。生成的名字可用限定词加前缀以消除命名的冲突。在合适处可使用惊叹号(!)作为名字的每个逻辑部分的分隔符。下面的表概括了在数据存储用于对象的命名约定。与用于访问数据存储中的实例的修饰的命名约定一起列出每个模式元素(项目、扩展、关系和视图)。7.列命名当映射任一对象模型到存储时,由于与应用程序对象一起存储的附加信息,有可能发生命名冲突。为避免命名冲突,所有非类型的特定列(不直接映射到类型声明中的命名的属性的列)用下划线字符(_)加前缀。在本实施例中,下划线字符(_)不允许作为任何标识符属性的开始字符。此外,为统一在CLR和数据存储之间的命名,存储平台类型或模式元素的所有属性(关系等)应具有大写的第一字符。8.搜索视图由存储平台提供视图,用于搜索存储的内容。对每个项目和扩展类型提供SQL视图。此外,提供视图以支持关系和视图(由数据模型定义)。所有SQL视图和在存储平台中的底层表是只读的。如下面将更充分描述的,使用存储平台API的Update()方法可存储或改变数据。在存储平台模式中明确定义的每个视图(由模式设计者定义,而非由存储平台自动地生成)可由命名的SQL视图[<模式名>].[View!<视图名>]来访问。例如,在模式“AcmePublisher.Books”中名为“BookSales”的视图可使用名字“[AcmePublisher.Books].[View!BookSales]来访问。因为视图的输出格式在每一视图的基础上是自定义的(由定义视图的那一方提供的任意查询定义),列基于模式视图定义被直接映射。存储平台数据存储中的所有SQL搜索视图使用列的下述排序约定1.如ItemId、ElementId、RelationshipId等的视图结果的逻辑“键”列2.如Typeld等关于结果类型的元数据信息。3.如CreateVersion(创建版本)、UpdateVersion(更新版本)等改变跟踪列4.类型专用的列(声明的类型的属性)5.类型专用的视图(家族视图)也包含返回对象的对象列每个类型家族的成员可使用一系列项目视图来搜索,在数据存储中每个项目类型有一个视图。a)项目每个项目搜索视图对特定类型或其子类型的项目的每个实例包含一行。例如,文档的视图能返回Document(文档)、LegalDocument(合法文档)和ReviewDocument(审阅文档)的实例。给定此例,能如图28所示那样概念化项目视图。(1)主项目搜索视图存储平台数据存储的每个实例定义称为主项目视图(MasterItemView)的特殊项目视图。此视图提供关于数据存储中每个项目的综述信息。视图对每个项目类型属性提供一列,其中一列描述项目的类型,若干列用于提供改变跟踪和同步信息。在数据存储中使用名字“[System.Storage].[Master!Item]”来标识主项目视图。(2)类型化的项目搜索视图每个项目类型也具有搜索视图。尽管类似于根项目视图,但此视图还提供通过“_Item”列对项目对象的访问。在数据存储中使用名字[模式名].[项目类型名]标识每个类型化的项目搜索视图。例如[AcmeCorp.Dod].[OfficeDoc]。b)项目扩展WinFs存储中的所有项目扩展也可使用搜索视图来访问。(1)主扩展搜索视图数据存储的每个实例定义一称为主扩展视图(MasterExtensionView)的特殊扩展视图。此视图提供关于数据存储中每个扩展的综述信息。该视图对每个扩展属性有一列,其中一列描述扩展的类型,而若干列用于提供改变跟踪和同步信息。使用名字“[System.Storage].[Master!Extension]”在数据存储中标识主扩展视图。(2)类型化的扩展搜索视图每个扩展类型还具有搜索视图。尽管类似于主扩展视图,但此视图还提供通过_Extension列对项目对象的访问。在数据存储中使用名字[模式名].[Extension!扩展类型名]标识每个类型化的扩展搜索视图。例如[AcmeCorp.Doc].[Extension!OfficeDocExt]。c)嵌套的元素所有嵌套的元素存储在项目、扩展或关系实例之中。因此,它们能通过查询合适的项目、扩展或关系搜索视图来访问。d)关系如上讨论,关系形成在存储平台数据存储中各项目之间链接的基本单元。(1)主关系搜索视图每个数据存储提供一主关系视图。此视图提供关于数据存储中所有关系实例的信息。在数据存储中使用名字“[System.Storage].[Master!Relationship]”来标识主关系视图。(2)关系实例搜索视图每个声明的关系也有返回该特定关系的所有实例的搜索视图。尽管类似于主关系视图,但此视图对该关系数据的每个属性提供命名的列。在数据存储中使用名字[模式名].[Relationship!关系名]来标识每个关系实例搜索视图。例如[AcmeCorp.Doc].[Relationship!DocumentAuthor]。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的类型定义是<TypeName=″ChangeTrackingInfo″BaseType=″Base.NestedElement″><FieldPropertyName=″CreationLocalTS″Type=″SqlTypes.SqlInt64″Nullable=″False″/><FieldPropertyName=″CreatingPartnerKey″Type=″SqlTypes.SqlInt32″Nullable=″False″/><FieldPropertyName=″CreatingPartnerTS″Type=″SqlTypes.SqlInt64″Nullable=″False″/><FieldPropertyName=″LastUpdateLocalTS″Type=″SqlTypes.SqlInt64″Nullable=″False″/><FieldPropertyName=″LastUpdatingPartnerKey″Type=″SqlTypes.SqlInt32″Nullable=″False″/><FieldPropertyName=″LastUpdatingPartnerTS″Type=″SqlTypes.SqlInt64″Nullable=″False″/></Type>这些属性包含下述信息(2)“类型化的”搜索视图中的改变跟踪除了提供与全局搜索视图相同信息外,每个类型化的搜索视图提供记录在同步拓扑中每个元素的同步状态的附加信息。b)墓碑数据存储为项目、扩展和关系提供墓碑信息。墓碑视图提供一个地方中有关活和墓碑实体两者(项目、扩展和关系)的信息。项目和扩展墓碑视图不提供对对应对象的访问,而关系墓碑视图提供对关系对象的访问(在墓碑关系的情况下关系对象为空)。(1)项目墓碑通过视图[System.Storage].[Tombstone!item]从系统检索项目墓碑。(2)扩展墓碑使用视图[System.Storage].[Tombstone!Extension]从系统检索扩展墓碑。扩展改变跟踪信息类似于为项目提供的添加了ExtensionId属性的信息。(3)关系墓碑通过视图[System.Storage].[Tombstone!Relationship]从系统检索关系墓碑。关系墓碑信息类似于对扩展提供的信息。然而,在关系实例的目标ItemRef上提供附加信息。此外,还选择关系对象。(4)墓碑清除为防止墓碑信息无限制地增长,数据存储提供墓碑清除任务。此任务确定什么时候可以舍弃墓碑信息。该任务计算本地创建/更新版本的界限,并随后通过舍弃所有更早的墓碑版本而截断墓碑信息。11.助手API和函数基础映射还提供若干助手函数。提供这些函数以帮助在该数据模型上的公用操作。a)函数[System.Storage].GetItem//给定ItemId返回一项目对象ItemGetItem(ItemIdItemId)b)函数[System.Storage].GetExtension//给定ItemId和ExtensionId返回一扩展对象ExtensionGetExtension(ItemIdItemId,ExtensionIdExtensionId)c)函数[System.Storage].GetRelationship//给定ItemId和RelationshipId返回一关系对象RelationshipGetRelationship(ItemIdItemId,RelationshipIdRelationshipId)12.元数据有两类在存储中表示的元数据实例元数据(项目的类型等),和类型元数据。a)模式元数据模式元数据作为来自元模式的项目类型的实例存储在数据存储中。b)实例元数据应用程序使用实例元数据来查询项目的类型,并寻找与项目相关联的扩展。给定项目的ItemId,应用程序可查询全局项目视图,以返回该项目的类型,并使用此值来查询Meta.Type视图以返回关于该项目的声明的类型的信息。例如,//对给定的项目实例返回元数据项目对象SELECTm._ItemASmetadataInfoObjFROM[System.Storage].[Item]iINNERJOIN[Meta].[Type]mONi._TypeId=m.ItemIdWHEREi.ItemId=@ItemIdE.安全性本节描述了依照一个实施例用于本发明的存储平台的安全模型。1.综述依照本实施例,指定和强制实施存储平台的安全策略的粒度是在给定数据存储中的项目上的各种操作级上;没有从整体中分离地保护项目的各部分的能力。该安全模型通过访问控制列表(ACL)指定了可以被授予或拒绝访问以在项目上执行这些操作的主体集。每一ACL是访问控制条目(ACE)的有序集合。用于项目的安全策略可以完全由自由选择的访问控制策略和系统访问控制策略来描述。这些的每一个是一组ACL。第一组(DACL)描述了由项目的所有者授予各种主体的自由选择的访问权限,而第二组ACL被称为SACL(系统访问控制列表),它指定了当以某些方式操纵对象时如何完成系统监察。除这些之外,数据存储中的每一项目与对应于项目的所有者的SID(所有者SID)相关联。用于在存储平台数据存储中组织项目的主要机制是包含分层结构的机制。包含分层结构是使用项目之间的持有关系来实现的。两个项目A和B之间被表达为“A包含B”的持有关系使得项目A能够影响项目B的生命周期。一般而言,数据存储中的项目在具有从另一项目到该项目的持有关系之前无法存在。除控制项目的生命周期之外,持有关系提供了传播项目的安全策略所必需的机制。为每一项目指定的安全策略由两个部分组成—为该项目明确指定的部分以及在数据存储中从该项目的父项目继承的部分。任何项目的明确定义的安全策略由两个部分组成—支配对考虑中的项目的访问的部分,以及影响由包含分层结构中所有其子孙继承的安全策略的部分。由子孙继承的安全策略是由明确定义的策略和继承的策略来决定的。由于安全策略是通过持有关系来传播的,且也可在任何项目处被覆盖,因此有必要指定如何确定项目的有效安全策略。在本实施例中,数据存储包含分层结构中的项目沿从存储的根到该项目的每一路径继承ACL。在对任何给定路径继承的ACL中,ACL中的各ACE的排序确定了强制实时的最终安全策略。以下表示法用于描述ACL中ACE的排序。ACL中由项目继承的ACE的排序是由以下两条规则来确定的—第一条规则满足了在从包含分层结构的根到项目I的路径中从各项目继承的ACE。从较接近的容器继承的ACE优先于从较远的容器继承的条目。直观上,这允许管理员能够覆盖从包含分层结构中较远处继承的ACE。该规则如下对于项目I上所有继承的ACLL对于所有项目I1、I2对于L中所有ACEA1和A2I1是I2的祖先,以及I2是I3的祖先,以及A1是从I1继承的ACE,以及A2是从I2继承的ACE意味着A2在L中优先于A1第二条规则将拒绝对项目的访问的ACE排序在授予对项目的访问的ACE之前。对于项目I上所有继承的ACLL对于所有项目I1对于L中所有ACEA1和A2,I1是I2的祖先,以及A1是从I1继承的ACCESS_DENIED_ACE,以及A2是从I1继承的ACCESS_GRANTED_ACE意味着A1在L中优先于A2在包含分层结构为树的情况下,从树的根到该项目只有一条路径,且该项目只有一个继承的ACL。在这些情况下,按照其中ACE的相对排序,由项目继承的ACL与由现有Windows安全模型中的文件(项目)继承的ACL相匹配。然而,数据存储中的包含分层结构是有向非循环图(DAG),因为对项目允许多个持有关系。在这些情况下,从包含分层结构的根节点到项目有多条路径。由于项目沿每一路径承ACL,因此每一项目与ACL的集合而非单个ACL相关联。注意,这与传统的文件系统模型不同,在该模型中,只有一个ACL与文件或文件夹相关联。当包含分层结构是DAG而非树时,通常有两个方面要详细阐述。需要描述关于当项目从其父节点继承一个以上ACL时如何为其计算有效安全策略,并且如何组织和表示项目对于存储平台数据存储的安全模型的管理有直接的意义。以下算法评估一给定主体对给定项目的访问权限。在整篇文档中,以下表示法用于描述与项目相关联的ACL。Inherited_ACLs(ItemId)—由其项目身份为ItemId的项目从存储中其父项目继承的一组ACL。Explicit_ACL(ItemId)—为其身份为ItemID的项目明确地定义的ACL。NTSTATUSACLAccessCheck(PSIDpOwnerSid,PDACLpDacl,DWORDDesiredAccess,HANDLEClientToken,PPRIVILEGE_SETpPrivilegeSet,DWORD*pGrantedAccess)如果期望的访问权限未被明确地拒绝,则上述例程返回STATUS_SUCCESS,且pGrantedAccess确定用户期望的权限中的哪些由该指定的ACL授予。如果期望访问权限被明确地拒绝,则该例程返回STATUS_ACCESS_DENIED。NTSTATUSItemAccessCheck(OS_ITEMIDItemId,DWORDDesiredAccess,HANDLEClientToken,PPRIVILEGE_SETpPrivilegeSet){STATUSStatus;PDACLpExplicitACL=NULL;PDACLpInheritedACLs=NULL;DWORDNumberOfInheritedACLs=0;pExplicitACL=GetExplicitACLForItem(ItemId);GetInheritedACLsForItem(ItemId,&pInheritedACLs,&NumberOfInheritedACLs)Status=ACLAccessCheck(pOwnerSid,pExplicitACL,DesiredAccess,ClientToken,pPrivilegeSet,&GrantedAccess);if(Status!=STATUS_SUCCESS)returnStatus;if(DesiredAccess==GrantedAccess)returnSTATUS_SUCCESS;for(i=0;(i<NumberOfInheritedACLs&&Status==STATUS_SUCCESS);i++){GrantedAccessForACL=0;Status=ACLAccessCheck(pOwnerSid,pExplicitACL,DesiredAccess,ClientToken,pPrivilegeSet,&GrantedAccessForACL);if(Status==STATUS_SUCCESS){GrantedAccess|=GrantedAccessForACL;}}If((Status==STATUS_SUCCESS)&&(GrantedAccess!=DesiredAccess)){Status=STATUS_ACCESS_DENIED;}returnStatus;}在任一项目处定义的安全策略的影响范围覆盖在数据存储上定义的包含分层结构中该项目的子孙。对于定义了显式策略的所有项目,则效果类似于定义由包含分层结构中其所有子孙所继承的策略。由所有子孙继承的有效ACL可通过取由该项目继承的ACL,并将显式ACL中可继承的ACE添加到该ACL的开头来获得。这被称作与该项目相关联的可继承ACL集。当根节点在文件夹项目处的包含分层结构中缺少安全性的显式指定时,文件夹的安全性指定应用于包含分层结构中该项目的所有子孙。因而,对其提供了显式安全策略指定的每一项目定义了类似地受保护的项目的区域,且对于该区域内的所有项目的有效ACL是该项目的可继承ACL集。在包含分层结构是树的情况下,这将完整地定义区域。如果每个区域都要与一号码相关联,那么仅将项目所属的区域随该项目一起包括在内就足够了。然而,对于是DAG的包含分层结构,包含分层结构中有效安全策略改变所处的点一般由两类项目确定。第一类是已对其指定显式ACL的项目。通常,这些是包含分层结构中管理员显式地指定ACL的点。第二类是具有一个以上父节点,且各个父节点具有与其相关联的不同安全策略的项目。通常,这些是为卷指定的安全策略的汇合点的项目,并指示了一新安全策略的开始。采用该定义,数据存储中的各项目落入两个类别之一—是类似地受保护的安全区域的根节点的那些项目,以及不是该根节点的那些项目。未定义安全区域的项目一般仅属于一个安全区域。如在树的情况下,项目的有效安全性可通过指定项目所属的区域以及该项目来指定。这导致一种用于基于存储中各个类似地受保护的区域来管理存储平台数据存储的安全性的直截了当的模型。2.安全模型的详细描述本节通过描述安全描述符及其包含的ACL内的各个权限如何影响各种操作提供了关于项目如何被保护的细节。a)安全描述符结构在描述安全模型的细节之前,关于安全描述符的基本讨论是有帮助的。安全描述符包含与可保护对象相关联的安全信息。安全描述符由SECURITY_DESCRIPTOR(安全描述符)结构及其相关联的安全信息构成。安全描述符可包括下列安全信息1.对象的所有者及主要群组的SID。2.指定对特定用户或用户组允许或拒绝的访问权限的DACL。3.指定为对象生成监察记录的访问尝试的类型的SACL。4.限定安全描述符或其个别成员含义的一组控制位。较佳地,应用程序不能直接操纵安全描述符的内容。存在用于设置和检索对象的安全描述符中的安全信息的函数。另外,存在用于为新对象创建及初始化安全描述符的函数。自由选择的访问控制列表(DACL)标识了被允许或拒绝访问可保护对象的受托者。当进程企图访问可保护对象时,系统核查该对象的DACL中的ACE,来确定是否对其授予访问权限。如果该对象没有DACL,则系统可对每个人授予完全访问权限。如果该对象的DACL没有ACE,则系统拒绝访问该对象的企图,因为该DACL不允许任何访问权限。系统依次核查ACE,直到找到允许所请求的所有访问权限的一个或多个ACE,或直到任一所请求的访问权限被拒绝。系统访问控制列表(SACL)使管理员能将访问受保护对象的企图记入日志。每个ACE指定了一指定受托者的访问企图的类型,该访问企图使得系统在安全事件日志中生成一个记录。当访问企图失败、当它成功或两者,SACL中的ACE可生成监察记录。当未经授权的用户企图获得对于对象的访问权限时,SACL提出警报。所有类型的ACE包含下面的访问控制信息1.标识向其应用ACE的受托者的安全标识符(SID)。2.指定由该ACE控制的访问权限的访问掩码。3.指示该ACE的类型的标志。4.确定子容器或对象能否从ACL所附的主要对象继承ACE的一组位标志。下面的表格列出由所有可保护对象所支持的三种ACE类型。(1)访问掩码格式所有可保护对象可使用在图26中所示的访问掩码格式来安排其访问权限。在此格式中,较低的16位用于对象专用访问权限,接下来的7位用于应用于大多数类型对象的标准访问权限,最高的4位用于指定每一对象类型可映射到一组标准和对象专用权限的类属访问权。ACCESS_SYSTEM_SECURITY(访问系统安全)位对应于访问该对象的SACL的权限。(2)类属访问权限类属权限在掩码内的4个最高位中指定。每一类可护对象将这些位映射到其一组标准和对象专用访问权限。例如,一文件对象可将GENERIC_READ位映射到READ_CONTROL和SYNCHRONIZE标准访问权限,及映射到FILE_READ_DATA、FILE_READ_EA和FILE_READ_ATTRIBUTES对象专用访问权限。其它类型的对象将GENERIC_READ位映射到适用于该类对象的访问权限组。当打开对象的句柄时,类属访问权限可用于指定所需的访问类型。这通常比指定所有对应的标准和专用权限要简单。下面的表格示出了为类属访问权限定义的常量。(3)标准访问权限每一类可护对象有一组对应于对该类对象专用的操作的访问权限。除了这些对象专用访问权限之外,还有一组对应于对大多数类型的可保护对象公用的操作的标准访问权限。下面的表格示出了为标准访问权限定义的常量。b)项目专用权限在图26的访问掩码结构中,项目专用权限被放置在对象专用权限段(较低的16位)中。由于在本实施例中,存储平台展现了两组API来管理安全性—Win32和存储平台API,因此必须考虑文件系统对象专用权限以激发对存储平台对象专用权限的设计。(1)文件和目录对象专用权限考虑下表参考上表,注意文件系统在文件和目录之间做出了基本的差别,这就是文件和目录权限为何能在相同的位上重叠的原因。文件系统定义了非常粒度化的权限,从而允许应用程序控制在这些对象上的行为。例如,它们允许应用程序在与文件相关联的属性(FILE_READ/WRITE_ATTRIBUTES)、扩展属性和数据流之间进行区分。本发明的存储平台的安全模型的目标是简化权限分配模型,因此例如在数据存储项目(联系人、电子邮件等)上操作的应用程序一般无需在属性、扩展属性和数据流之间区分。然而,对于文件和文件夹,粒度Win32权限被保存,且定义了通过存储平台的访问语义,使得可提供与Win32应用程序的兼容性。这一映射对以下指定的每一项目权限讨论。以下项目权限是用其相关联的可允许操作来指定的。也提供了这些项目权限的每一个背后的等效的Win32权限。(2)WinFSItemRead该权限允许对项目的所有元素的读访问,包括通过嵌入关系链接到项目的项目。它也允许枚举通过持有关系链接到该项目的项目(也称为目录清单)。这包括通过引用关系链接的项目的名称。这一权限映射到文件(FILE_READ_DATA|SYNCHRONIZA)文件夹(FILE_LIST_DIRECTORY|SYNCHRONIZE)语义是安全应用程序可设置WinFSItemReadData(WinFS项目读数据),并指定权限掩码为以上指定的文件权限的组合。(3)WinFSItemReadAttributes该权限允许对项目的基本属性的读访问,这非常象基本文件属性和数据流之间的文件系统区分。较佳地,这些基本属性是驻留在从中导出所有项目的基本项目中的那些属性。该权限映射到文件(FILE_READ_ATTRIBUTES)文件夹(FILE_READ_ATTRIBUTES)(4)WinFSItemWriteAttributes该权限允许对项目的基本属性的写访问,这非常象基本文件属性和数据流之间的文件系统区分。较佳地,这些基本属性驻留在从中导出所有项目的基本项目中的那些属性。该权限映射到文件(FILE_WRITE_ATTRIBUTES)文件夹(FILE_WRITE_ATTRIBUTES)(5)WinFSItemWrite该权限允许对项目的所有元素进行写的能力,包括通过嵌入关系链接的项目。该权限也允许添加或删除到其它项目的嵌入关系的能力。该权限映射到文件(FILE_WRITE_DATA)文件夹(FILE_ADD_FILE)在存储平台数据存储中,在项目和文件夹之间没有区别,因为项目也可以具有到数据存储中的其它项目的持有关系。因此,如果具有FILE_ADD_SUBDIRECTORY(或FILE_APPEND_DATA)权限,则可使项目为到其它项目的关系的源。(6)WinFSItemAddLink该权限允许添加到存储中的项目的持有关系的能力。应当注意,由于用于多个持有关系的安全模型改变项目上的安全性,且如果是来自分层结构中的较高点,则改变可绕过WRITE_DAC,因此在目的地项目上要求WRITE_DAC以能够创建到其的关系。该权限映射到文件(FILE_APPEND_DATA)文件夹(FILE_ADD_SUBSIRECTORY)(7)WinFSItemDeleteLink该权限即使在未向主体授予删除项目的权限时也允许删除到该项目的持有关系的能力。这与文件系统模型相一致,且有助于清除。该权限映射到文件(FILE_DELETE_CHILD)—注意,文件系统没有等效于该权限的文件,但是有了具有到其它项目的持有关系的概念,并因此也可对非文件夹实现该权限。文件夹(FILE_DELETE_CHILD)(8)删除项目的权限如果到项目的最后一个持有关系消失,则该项目被删除。没有对删除项目的显式表示法。存在删除到项目的所有持有关系的清除操作,但是它是较高级工具且不是系统原语。如果满足以下两个条件之一,则使用路径指定的任何项目可被取消链接(1)沿该路径的父项目向该项目授予写权限,或者(2)该项目本身上的标准权限授权DELETE。当移除最后一个关系时,该项目从系统中消失。如果项目本身上的标准权限授权DELETE,则使用ItemID指定的任何项目可被取消链接。(9)复制项目的权限如果主体被授权项目上的WinFSItemRead和目的地文件夹上的WinFSItemWrite,则项目可从源复制到目的地文件夹。(10)移动项目的权限在文件系统中移动文件仅要求源文件上的DELETE权限和目的地目录上的FILE_ADD_FILE,因为它保存了目的地上的ACL。然而,可在MoveFileEx调用(MOVEFILE_COPY_ALLOWED)中指定让应用程序指定在跨卷移动的情况下可容忍CopyFile语义的标志。对于在移动之后对安全描述符发生了什么有四个可能的选择1.与文件一起携带整个ACL—默认的卷内移动语义。2.与文件一起携带整个ACL并将ACL标记为受保护的。3.仅携带显式ACE跨越,并在目的地上重新继承。4.不携带任何东西,并在目的地上重新继承—默认的卷间移动语义—与复制文件一样。在本安全模型中,如果应用程序指定了MOVEFILE_COPY_ALLOWED标志,则对卷内和卷间两种情况都执行第四个选项。如果该标志未指定,则执行第二个选项,除非目的地也在同一安全区域中(即,同一继承语义)。存储平台级移动也实现第四个选项,且要求源上的READ_DATA,与复制所要求的一样。(11)查看项目上的安全策略的权限如果项目向主体授予标准权限READ_CONTROL,则可查看项目的安全性。(12)改变项目上的安全策略的权限如果项目向主体授予标准权限WRITE_DAC,则可改变项目的安全性。然而,由于数据存储提供隐式继承,因此这具有可以如何在分层结构上改变安全性的含意。规则是如果分层结构的根授权WRTIE_DAC,则在整个分层结构上改变安全策略,而不论分层结构(或DAG)中的特定项目是否不向主体授权WRITE_DAC。(13)没有直接等效物的权限在本实施例中,FILE_EXECUTE(用于目录的FILE_TRAVERSE)在存储平台中没有直接等效物。该模型为Win32兼容性保存这些权限,但是没有基于这些权限为项目做出任何访问决策。如同FILE_READ/WRITE_EA一样,由于数据存储项目没有扩展属性的表示法,因此未提供该位的语义。然而,为Win32兼容性保留该位。3.实现定义同样受保护的区域的所有项目在安全表中具有与其相关联的条目。安全表定义如下项目身份条目是同样受保护的安全区域的根的项目身份。项目有序路径是与同样受保护的安全区域的根相关联的有序路径(ordpath)。显式项目ACL条目是为同样受保护的安全区域的根定义的显式ACL。在某些情况下,这可以为空,例如,当由于项目具有属于不同区域的多个父项目而定义新安全区域时。路径ACL是由项目继承的ACL集,区域ACL条目是为与项目相关联的同样受保护的安全区域定义的ACL集。对给定存储中的任何项目的有效安全性的计算充分利用了该表。为确定与项目相关联的安全策略,获取与项目相关联的安全区域,并检索与该区域相关联的ACL。当通过直接添加显式ACL或通过间接添加导致形成新安全区域的持有关系来改变与项目相关联的安全策略时,使该安全表保持最新,以确保上述用于确定项目的有效安全性的算法是有效的。对存储的各种改变以及维护安全表的随附算法如下a)在容器中创建新项目当在容器中新创建项目时,它继承与该容器相关联的所有ACL。由于新创建的项目只有一个父项目,因此它与其父项目属于同一区域。由此,无需在安全表中创建新条目。b)向项目添加显式ACL当ACL被添加到项目时,它为包含分层结构中属于与给定项目本身相同的安全区域的所有其子孙定义新安全区域。对于包含分层结构中属于其它安全区域但是为给定项目的子孙的所有项目,安全区域保持不变,但是与该区域相关联的有效ACL被改变,以反映新ACL的添加。对该新安全区域的引入可触发对具有与跨越旧安全区域和新定义的安全区域的祖先的多个持有关系的所有项目进一步定义区域。对于所有这样的项目,需要定义新的安全区域,并重复该过程。图27(a)、(b)和(c)描绘了通过引入新的显式ACL从现有安全区域中划分出来的新的同样受保护的安全区域。这是由标记为2的节点指示的。然而,对该新区域的引入导致创建另外的区域3,因为项目具有多个持有关系。以下对安全表的更新序列反映了对同样受保护的安全区域的分解。c)向项目添加持有关系当向项目添加持有关系时,它引发三种可能性之一。如果持有关系的目标,即考虑中的项目是安全区域的根,则与该区域相关联的有效ACL被改变,且无需对该安全表的进一步修改。如果新持有关系的源的安全区域与项目的现有父项目的安全区域相同,则无需任何改变。然而,如果项目现在具有属于不同安全区域的父项目,则形成新的安全区域,以给定项目作为该安全区域的根。这一改变通过修改与该项目相关联的安全区域被传播到包含分层结构中的所有项目。属于与考虑中的项目相同的安全区域的所有项目及其在包含分层结构中的子孙都需要改变。一旦做出了改变,需要检查具有多个持有关系的所有项目以确定是否需要进一步的改变。如果这些项目中的任一个具有不同安全区域的父项目,则需要进一步的改变。d)从项目删除持有关系当从项目删除持有关系时,如果满足某些条件,可能用其父区域来折叠安全区域。更精确地,这可以在以下条件下完成(1)如果持有关系的移除导致有一个父项目的项目且没有为该项目指定显式ACL;(2)如果持有关系的移除导致其父项目都在同一安全区域内的项目,且没有为该项目定义显式ACL。在这些情况下,这些安全区域可被标记为与父项目相同。这一标记需要应用于其安全区域对应于所折叠的区域的所有项目。e)从项目中删除显式ACL当从项目中删除显式ACL时,可能用其父项目的安全区域来折叠根为该项目的安全区域。更精确地,如果显式ACL的移除导致其在包含分层结构中的父项目属于同一安全区域的项目,则可实现这一过程。在这些情况下,可将安全区域标记为与父项目相同,且改变被应用于其安全区域对应于所折叠的区域的所有项目。f)修改与项目相关联的ACL在这一情形中,不需要对安全表进行任何新的添加。与该区域相关联的有效ACL被更新,且将该新的ACL改变传播到被它所影响的安全区域。F.通知和改变跟踪按本发明的另一方面,存储平台提供允许应用程序跟踪数据改变的通知能力。此特征主要供保持易失状态或执行数据改变事件上的业务逻辑的应用程序使用。应用程序注册在项目、项目扩展及项目关系上的通知。在提交了数据改变之后通知被异步地传送。应用程序可按项目、扩展和关系类型以及操作类型来过滤通知。按一个实施例,存储平台API322为通知提供两类接口。第一,应用程序注册由对项目、项目扩展和项目关系的改变触发的简单数据改变事件。第二,应用程序创建“监视程序”对象来监视项目、项目扩展和项目之间关系的组。在系统失败或系统离线超过延长的时间段之后,可保存和重新创建监视程序对象的状态。单个通知可反映多个更新。1.存储改变事件本节提供了如何使用由存储平台API322提供的通知接口的若干示例。a)事件项目、项目扩展和项目关系展现了由应用程序用于注册数据改变通知的数据改变事件。以下代码示例示出了Item基类上ItemModified(项目修改)和ItemRemoved(项目移除)事件处理程序的定义。//事件publiceventItemModifiedEventHandlerItemItemModified;publiceventItemRemovedEventHandlerItemItemRemoved;所有通知都携带足够的数据以从数据存储中检索改变的项目。以下代码示例示出了如何注册项目、项目扩展或项目关系上的事件myItem.ItemModified+=newItemModifiedEventHandler(this.onItemUpdate);myItem.ItemRemoved+=newItemRemovedEventHandler(this.onItemDelete);在本实施例中,存储平台确保如果自从最后一次传送通知以来相应的项目被修改或删除,或在自从最后一次从数据存储中取出以来的新注册的情况下将通知应用程序。b)监视程序在本实施例中,存储平台定义了用于监视与(I)文件夹或文件夹分层结构,(2)项目上下文,或(3)特定项目相关联的对象的监视程序类。对于这三个类别中的每一个,存储平台提供了监视相关联的项目、项目扩展或项目关系的特定监视程序类,例如,存储平台提供相应的FolderItemWatcher(文件夹项目监视程序)、FolderRelationshipWatcher(文件夹关系监视程序)以及FolderExtensionWatcher(文件夹扩展监视程序)类。当创建监视程序时,应用程序可对预先存在的项目,即项目、扩展或关系请求通知。该选项大多数用于维护专用项目高速缓存的应用程序。如果未请求,则应用程序接收对发生在创建了监视程序对象之后的所有更新的通知。连同传送通知一起,存储平台提供“WatcherState(监视程序状态)”对象。WatcherState可被串行化并保存在磁盘上。监视程序状态随后可用于在失败或当在离线之后重新连接时重新创建相应的监视程序。新的重新创建的监视程序将重新生成未确认的通知。应用程序通过在相应的监视程序状态上调用提供对通知的引用的“Exclude(排除)”方法来指示通知的送达。存储平台向每一事件处理程序传送监视程序状态的单独副本。在同一事件处理程序的随后的调用上接收到的监视程序状态假定所有先前接收的通知的送达。作为示例,以下代码示例示出了FolderItemWatcher的定义。publicclassFolderItemWatcherWatcher{//构造函数publicFolderItemWatcher_Constructor(Folderfolder);publicFolderItemWatcher_Constructor1(Folderfolder,TypeitemType);publicFolderItemWatcher_Constructor2(ItemContextcontext,ItemIdfolderId);publicFolderItemWatcher_Constructor3(Folderfolder,TypeitemType,FolderItemWatcherOptionsoptions);publicFolderItemWatcher_Constructor4(ItemContextcontext,ItemIdfolderId,TypeitemType);publicFolderItemWatcher_Constructor5(ItemContextcontext,ItemId,folderId,TypeitemType,FolderItemWatcherOptionsoptions);//属性publicItemIdFolderItemWatcher_FolderId{get;}publicTypeFolderItemWatcher_ItemType{get;}publicFolderItemWatcherOptionsFolderItemWatcher_Options{get;}//事件publiceventItemChangedEventHandlerFolderItemWatcher_ItemChanged;}以下代码示例示出了如何创建用于监视文件夹的内容的文件夹监视程序对象。监视程序在添加新音乐项目或更新或删除现有音乐项目时生成通知,即事件。文件夹监视程序监视文件夹分层结构中的特定文件夹或所有文件夹。myFolderItemWatcher=newFolderItemWatcher(myFolder,typeof(Music));myFolderItemWatcher.ItemChanged+=newItemChangedEventHandler(this.onItemChanged);2.改变跟踪和通知生成机制该存储平台提供了一种简单而有效的机制来跟踪数据改变和生成通知。客户机在用于检索数据的同一连接上检索通知。这极大程度上简化了安全检查、移除了可能网络配置上的延时和约束。通知是通过发出选择语句来检索的。为防止轮询,客户机可使用由数据库引擎314提供的“等待(wairfor)”特征。图13示出了基本存储平台通知概念。等待查询可同步地执行,在该情况下,调用线程被阻断,直到结果可用;或者可异步地执行,在该情况下,线程不被阻断,且当结果可用时在单独的线程上返回结果。“等待”和“选择”的组合对于监视适合特定数据范围的数据改变是有吸引力的,因为改变可通过在相应的数据范围上设置通知锁来监视。这适用于许多常见的存储平台情形。对于个别项目的改变可以通过在相应的数据范围上设置通知锁来监视。对文件夹和文件夹树的改变可通过在路径范围上设置通知锁来监视。对类型及其子类型的改变可通过在类型范围上设置通知锁来监视。一般而言,有三个与处理通知相关联的不同阶段(1)数据改变或甚至检测,(2)订阅匹配,以及(3)通知送达。排除同步通知送达,即作为执行数据改变的事务的一部分的通知送达,存储平台可实现以下两种形式的通知送达1)直接事件检测执行事件检测和订阅匹配作为更新事务的一部分。通知被插入到由订户监视的表中;以及2)推迟的事件检测在提交了更新事务之后执行事件检测和订阅匹配。随后实际的订户或中介检测事件并生成通知。直接事件检测要求执行额外的代码作为更新操作的一部分。这允许捕捉所有感兴趣的事件,包括指示相对状态改变的事件。推迟的事件检测移除向更新操作添加额外代码的要求。事件检测是由最终订户来完成的。推迟的事件检测通常对事件检测和事件送达进行批处理,且很好地适用于数据库引擎314(例如,SQLServer)的查询执行基础结构。推迟的事件检测依赖于更新操作留下的日志或跟踪。存储平台为删除的数据项目维护一组逻辑时间标记以及墓碑。当扫描数据存储中的改变时,客户机提供定义用于检测改变的低水印的时间标记以及防止重复通知的一组时间标记。应用程序可能接收到对在由低水印指示的时间之后发生的所有改变的通知。能够访问核心视图的复杂应用程序还可通过创建专用参数和重复过滤器表,来优化和减少监视一组可能很大的项目所需的SQL语句的数量。具有特殊需求的应用程序,诸如必须支持丰富视图的应用程序可使用可用的改变跟踪框架来监视数据改变并刷新其专用快照。因此,较佳地,在一个实施例中,存储平台实现推迟的时间检测方法,如下文更完整地描述的。a)改变跟踪所有项目、扩展和项目关系定义携带唯一的标识符。改变跟踪为所有数据项目维护一组逻辑时间标记来记录创建、更新和删除时间。墓碑条目用于表示删除的数据项目。应用程序使用该信息来有效地监视自从应用程序最后一次访问数据存储以来是否新添加、更新或删除了特定的项目、项目扩展或项目关系。以下示例示出了该机制。createtable[item-extension-relationship-table-template](identifieruniqueidentifiernotnulldefaultnewid()createdbigint,notnull,--@@当创建时存入updatedbignit,notnull,--@@当最后一次更新时存入……)所有删除的项目、项目扩展和关系被记录在对应的墓碑表中。一个模板示出如下。createtable[item-extension-relationship-tombstonetable-template](identifieruniqueidentifiernotnull,deletedbigint,notnull,--@@当删除时存入,createdbigint,notnull,--@@当创建时存入,updatedbigint,notnull,--@@当最后一次更新时存入……)为效率原因,存储平台为项目、项目扩展、关系和路径名维护一组全局表。这些全局查找表可以由应用程序用于有效地监视数据范围和检索相关联的时间标记和类型信息。b)时间标记管理逻辑时间标记对于数据库存储,即存储平台卷是“本地的”。时间标记是单调递增的64位值。保留单个时间标记通常足以检测在最后一次连接到存储平台卷之后是否发生了数据改变。然而,在最真实的情形中,需要保存稍多一些的时间标记来检查重复。原因解释如下。关系型数据库表是构建在一组物理数据结构上的逻辑抽象,即B树、堆等。向新创建或更新的记录分配时间标记不是原子动作。将该记录插入到底层数据结构可能在不同的时刻发生,由此应用程序可能会看到记录是无序的。图14示出了将新记录插入到同一B树中的两个事务。由于事务T3在调度事务T2的插入之前插入其记录,因此扫描B树的应用程序可能会看到由事务T3插入的记录在由T2插入的事务之前。由此,读者可能不正确地假定他看到了在时刻“10”之前创建的所有记录。为解决这一问题,数据库引擎314提供了一种返回低水印的功能,在该低水印之前,提交了所有的更新且所有更新都被插入到各自的底层数据结构中。在上述示例中,返回的低水印是“5”,假定读者在提交事务T2之前启动。由数据库引擎314提供的低水印允许应用程序在扫描数据库或数据范围内的数据改变时有效地确定要忽略哪些项目。一般而言,ACID事务被假定为持续非常短的时间,由此,预期低水印非常接近于最近分发的时间标记。在存在长持续时间的事务的情况下,应用程序可能必须保存个别的时间标记来检测和丢弃重复。c)数据改变检测—事件检测当查询数据存储时,应用程序获得低水印。随后,应用程序使用该水印来扫描数据存储中其创建、更新或删除时间标记大于返回的低水印的条目。图15示出了该过程。为防止重复通知,应用程序记住大于返回的低水印的时间标记,并使用这些时间标记来滤除重复。应用程序创建会话本地临时表,以有效低处理一大组重复时间标记。在发出选择语句之前,应用程序插入所有先前返回的重复时间标记,并删除比返回的最后一个低水印更老的时间标记,如下所示。deletefrom$dupilcateswherets<@oldLowWaterMarklinsertinto$duplicates(ts)values(...),...,(...);waitfor(select*,getLowWaterMark()asnewLowWaterMarkfrom[global!items]whereupdated>=@oldLowWaterMarkandupdatednotin(select*from$duplicates))G.同步依照本发明的另一方面,该存储平台提供同步服务330,它(I)允许存储平台的多个实例(每个有自己的数据存储302)按一组灵活的规则来同步它们的内容的各部分,以及(ii)为第三方提供基础结构以将本发明的存储平台的数据存储与实现专有协议的其它数据源同步。存储平台到存储平台的同步在一组参与的复制品之间发生。例如,参考图3,希望在多半是在不同的计算机系统上运行的存储平台的另一实例的控制下提供在存储平台300的数据存储302和另一远程数据存储338之间的同步。该组的总成员资格不必在任何给定时间被任何给定复制品知道。不同的复制可以独立地(即并发地)作出改变。将同步过程定义成使每个复制品知道由其它复制品作出的改变。此同步能力本质上是多主的(multi-master)。本发明的同步能力允许各复制品·确定另一复制品知道什么改变;·请求关于此复制品不知道的改变的信息;·传达关于其它复制品不知道的改变的信息;·确定两个改变何时互相冲突;·本地应用改变;·传达冲突分解到其它复制品以确保收敛性;以及·基于对冲突分解指定的策略分解冲突。1.存储平台到存储平台的同步本发明的存储平台的同步服务300的主要应用是同步存储平台(每个带有它自己的数据存储)的多个实例。同步服务在存储平台模式级上操作(而不是在数据库引擎314的底层表中)。因此,例如“范围(Scope)”用于定义下面讨论的同步组。同步服务按“纯改变(netchange)”的原则操作。不是记录和发送各个操作(如事务复制那样),同步服务而是发送这些操作的最终结果,因此常将多个操作的结果合并成单个最终结果。同步服务通常不考虑事务边界。换言之,若在单个事务中对存储平台数据存储作出两个改变,不保证这些改变原子地应用到所有其它复制品上—可以示出一个改变而不示出其它改变。此原则的例外是,若在同一事务中对同一项目作出两个改变,则这些改变保证被原子地发送和应用到其它复制品。因此,项目是同步服务的一致性单元。a)同步(Sync)控制应用程序任一应用程序可连接到同步服务并启动同步操作。那样的应用程序提供执行同步(见下面同步概况)所需的所有参数。那样的应用程序在这里被称为同步控制应用程序(SCA)。在同步两个存储平台实例时,在一侧由SCA启动同步。该SCA通知本地同步服务与远程伙伴同步。在另一侧,同步服务通过由来自发起机器的同步服务发出的消息唤醒。它基于在目标机器上存在的持久配置信息(见下文的映射)作出响应。同步服务能按时间表或响应于事件运行。在这些情况下,实现时间表的同步服务成为SCA。为启用同步,需要采取两个步骤。首先,模式设计者必须用合适的同步语义注释存储平台模式(如下文所述的指定改变单元)。其次,同步必须在具有参与同步的存储平台的实例的所有机器上正确地配置(如下所述)。b)模式注释同步服务的基本概念是改变单元(ChangeUnit)的概念。改变单元是由存储平台个别地跟踪的最小的模式片段。对每个改变单元,同步服务能确定自从最后一次同步以来它是被改变还是未被改变。指定模式中的改变单元达到若干目的。首先,它确定了在线的同步服务如何罗嗦。当在改变单元内作出改变时,整个改变单元被发送到其它复制品,因为同步服务不知道改变单元的哪部分被改变。其次,它确定了冲突检测的粒度。当对同一改变单元作出两个并发的改变(这些术语在后继章节中详细定义),同步服务引起冲突;另一方面,若对不同改变单元作出并发改变,则无冲突发生,且改变被自动地合并。第三,它严重地影响了由系统保持的元数据的量。对每个改变单元保持许多同步服务元数据;因此,使改变单元更小会增加同步的额外开销。定义改变单元需要找出正确的折衷。为此,同步服务允许模式设计者参与此过程。在一个实施例中,同步服务不支持大于一个元素的改变单元。然而,它支持让模式设计者指定比一个元素更小的改变单元的能力—即,将一个元素的多个属性组合到单独的改变单元中。在该实施例中,这是使用下述句法实现的<TypeName=″Appointment″MajorVersion=″1″MinorVersion=″0″ExtendsType=″Base.Item″ExtendsVersion=″1″><FieldName=″MeetingStatus″Type=″thestorageplatformTypes.uniqueidentifierNullable=″False″/><FileldName=″OrganizerName″Type=″thestorageplatformTypes.nvarchar(512)″Nullable=″False″/><FiledName=″OrganizerEmail″Type=″thestorageplatformTypes.nvarchar(512)″TypeMajorVersion=″1″MultiValued=″True″/>…<ChangeUnitName=″CU_Status″><FieldName=″MeetingStatus″/></ChangeUnit><ChangeUnitName=″CU_Organizer″/><FieldName=″OrganizerName″/><FieldName=″OrganizerEmail″/></ChangeUnit>…</Type>c)同步配置希望保持它们数据的某些部分同步的一组存储平台伙伴被称为同步共同体。虽然共同体的成员希望保持同步,它们不需要以完全相同的方式表示数据;换言之,同步伙伴可转换他们正在同步的数据。在对等情况下,让对等方对所有它们的伙伴维持转换映射是不现实的。相反,同步服务采取定义“共同体文件夹”的方法。共同体文件夹是代表所有共同体成员正在与之同步的假设的“共享文件夹”的抽象。此概念最好用一例子说明。若Joe希望保持他的若干计算机的MyDocuments(我的文档)文件夹同步,Joe定义一共同体文件夹,如称为JoeDocuments。随后在每台计算机上,Joe在假设的JoeDocuments文件夹和本地MyDocuments文件夹之间配置一映射。从这点出发,当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)时间表在一个实施例中,同步服务不提供它自己的调度基础结构。相反,它依赖于另一组件来完成此任务—在MicrosoftWindows操作系统中可得到的WindowsScheduler。同步服务包括命令行实用程序,它担当SCA并基于保存在XML文件中的同步概况触发同步。该实用程序使得按时间表或者响应于如用户登录或登出等事件来配置WindowsScheduler运行同步变得非常容易。d)冲突处理同步服务中的冲突处理被划分成三个阶段(1)发生在改变应用时的冲突检测—此步骤判断是否可安全地应用改变;(2)自动冲突分解并记入日志—在此步骤(发生在紧接着冲突检测之后)资咨询自动冲突分解器以查看冲突是否能被分解—若不能,可选地将冲突记入日志;以及(3)冲突检查与分解—若某些冲突已被记入日志,且发生在同步会话的环境之外,则采取此步骤—此时,被记入日志的冲突能被分解并从日志中移除。(1)冲突检测在本实施例中,同步服务检测两种类型的冲突基于知识的冲突和基于约束的冲突。(a)基于知识的冲突当两个复制品对同一改变单元进行独立的改变时,会造成基于知识的冲突。如果两个改变是在彼此没有知识的情况下进行的,则这两个改变被称作为是独立的—换言之,第一个的版本没有被第二个的知识覆盖,反之亦然。基于如以上所述的复制品的知识,所述同步服务自动地检测所有的这种冲突,并且处理这些冲突,在此如下面所述。有时,将冲突认为是改变单元的版本历史中的分叉是有帮助的。如果在改变单元的生命中没有冲突发生,则其版本历史就是一个简单的链—每个改变都在之前的一个后面发生。在基于知识的冲突的情况中,两个改变并行发生,使得所述链分裂并且变成版本树。(b)基于约束的冲突存在一些情况,在这些情况下,当一起被应用时,独立的改变违反了完整性约束。例如,在相同目录中创建具有相同名称的文件的两个复制品会使得这样的冲突发生。基于约束的冲突涉及两个独立的改变(正如用于基于知识的冲突一样);然而,它们不影响相同改变单元。相反,它们影响不同改变单元,但在它们之间存在约束。同步服务在改变应用时检测约束违反,并自动引发基于约束的冲突。分解基于约束的冲突通常要求以不违反约束的方式来修改改变的自定义代码;同步服务不提供用于完成此过程的通用机制。(2)冲突处理当检测到冲突时,同步服务可以采取3个动作中的一个(由同步概况中的同步启动器选择)(1)拒绝改变,将其返回给发送者;(2)将冲突记录到冲突日志中;或者(3)自动分解冲突。如果拒绝改变,那么如果改变没有到达所述复制品,则同步服务起作用。否定确认被发送回启动器。这种分解策略主要在无头复制品(例如文件服务器)上有用,其中冲突日志记录是不可行的。相反,这种复制品强迫其它复制品通过拒绝改变来处理冲突。同步启动器配置其同步概况中的冲突分解。同步服务支持在单个概况中通过以下方法来组合多个冲突分解器—首先,指定冲突处理器列表一个接一个地进行尝试,直到其中一个成功为止;其次,将冲突处理器与冲突类型相关联,例如,将更新—更新基于知识的冲突指向一个冲突处理器,而将所有其它冲突指向日志。(a)自动冲突分解同步服务提供多种默认的冲突分解器。该列表包括·本地优胜如果与本地储存的数据冲突,则丢弃传入改变;·远程优胜如果与传入改变冲突,则丢弃本地数据;·最后写入者优胜基于改变的时间标记挑选本地优胜者或者远程优胜者的任一个(注意,通常同步服务不依赖于时钟值;这种冲突分解器对于那个规则是惟一例外);·确定性的以保证在所有复制品上相同的方式挑选优胜者,但不是另外有意义的—同步服务的一个实施例可能使用伙伴ID的字典式比较来实现这个特征。另外,ISV可以实现并且安装其自己的冲突处理器。自定义冲突处理器可以接受配置参数;这种参数必须由同步概况的冲突分解部分中的SCA来指定。当冲突分解器处理冲突时,它将需要执行的操作的列表(代替冲突改变)返回给运行时间。然后,同步服务应用这些操作,适当地调整远程知识,以便包括冲突处理器已经考虑过的信息。可能在应用分解的同时检测到了另一个冲突。在这种情况下,在重新进行原始处理之前,新的冲突必须被分解。当将冲突看作项目的版本历史中的分支时,冲突分解可以被看作接点—组合两个分支以便形成单独的点。因此,冲突分解将版本历史转为有向非循环图(DAG)。(b)冲突日志记录一种非常特定类型的冲突处理器是冲突日志记录器。同步服务将冲突记录在日志中作为类型ConflictRecord的项目。这些记录反过来与冲突的项目有关(除非项目本身已经被删除)。每个冲突记录包含引发冲突的传入改变;冲突的类型更新—更新、更新—删除、删除—更新、插入—插入,或者约束;以及传入改变的版本和发送它的复制品的知识。记入日志的冲突可用于如下所述的检查和分解。(c)冲突检查和分解同步服务提供用于应用程序检查冲突日志并且建议对其中的冲突的分解方法的API。API允许应用程序枚举所有冲突或者与给定的项目有关的冲突。它还允许这些应用程序以3种方式中的一种来分解被记入日志的冲突(1)远程优胜—接受被记入日志的改变并且覆盖相冲突的本地改变;(2)本地优胜—忽略被记入日志的改变的冲突部分;以及(3)建议新的改变—其中应用程序建议一种合并,该合并在其看法中分解所述冲突。一旦由应用程序分解了冲突,同步服务就将它们从日志中删除。(d)复制品的收敛和冲突分解的传播在复杂的同步情形中,在多个复制品上可以检测到相同的冲突。如果发生了这种情形,则许多事情都可能发生(1)在一个复制品上分解冲突,而分解被发送给另一个;(2)在两个复制品上自动分解冲突;或者(3)在两个复制品上手动分解冲突(通过冲突检查API)。为了确保收敛,同步服务将冲突分解传递给其它复制品。当分解冲突的改变到达复制品时,同步服务自动地找到日志中通过该更新分解的任意冲突记录,并且删除它们。在这种情况下,一个复制品上的冲突分解将绑定在所有其它复制品上。如果对于相同的冲突,由不同的复制品选择不同的优胜者,则同步服务应用绑定冲突分解的原理,并且自动地挑选两种分解中优于另一种的一种分解。以确定的方式挑选出优胜者,该确定方式保证在所有的时候都产生相同的结果(一个实施例使用复制品ID字典式比较)。如果对相同的冲突,不同的复制品建议不同的“新改变”,则同步服务将这种新的冲突看作特殊的冲突,并且使用冲突日志记录器来防止它传播到其它复制品。这种情况通常会引起手动冲突分解。2.对非存储平台数据存储的同步按本发明的存储平台的另一方面,存储平台提供ISV用于实现同步适配器的体系结构,同步适配器使存储平台能与如MicrosoftExchange、AD、Hotmail等传统系统同步。同步适配器得益于由下述同步服务提供的许多同步服务。不管其名称如何,同步适配器不需要作为某个存储平台体系结构的插件来实现。在需要时,“同步适配器”能简单地是利用同步服务运行库接口来获得如改变枚举和应用等服务的任何应用程序。为了使其他人能更容易地配置和运行到给定后端的同步,鼓励同步适配器的编写者展现标准同步适配器接口,它在给定上述的同步概况时运行同步。概况提供配置信息给适配器,适配器将某些信息传送到同步运行库以控制运行库服务(如,要同步的文件夹)。a)同步服务同步服务向适配器编写者提供若干同步服务。在本节余下部分,方便地将存储平台在其上完成同步的机器称为“客户机”,而适配器正与其对话的非存储平台后端称为“服务器”。(1)改变枚举基于由同步服务维持的改变跟踪数据,改变枚举允许同步适配器容易地枚举自从最后一次与该伙伴试图作出同步以来对数据存储文件夹发生的改变。基于“定位点”的概念来枚举改变—这是表示有关最后一次同步的信息的不透明的结构。如以前章节所述,定位点采取存储平台知识的形式。利用改变枚举服务的同步适配器落入两大类别使用“存储的定位点”的适配器和使用“提供的定位点”的适配器。区别基于关于最后一次同步的信息存储在哪里—在客户机上还是在服务器上。适配器常常容易地存储此信息在客户机上—后端往往不能容易地存储此信息。另一方面,若多个客户机与同一后端同步,则将此信息存储在客户机上是低效且在某些情况下是不正确的—这使一个客户机不知道其它客户机已推到服务器的改变。若适配器希望使用服务器存储的定位点,则适配器需要在改变枚举时将其送回到存储平台。为了让存储平台维护定位点(用于本地或远程存储),存储平台需要知道成功地应用在服务器上的改变。这些且只有这些改变能包括在定位点中。在改变枚举期间,同步适配器使用确认(Acknowledgement)接口,以报告哪个改变已被成功地应用。在同步结束时,使用提供的定位点的适配器必须读出新定位点(它结合了所有成功应用的改变)并将其发送到它们的后端。各适配器常常需要存储适配器专用数据以及插入到存储平台数据存储中的各项目。该数据存储的常见例子是远程ID和远程版本(时间标记)。同步服务提供用于存储此数据的机制,而改变枚举提供接收此额外数据以及要返回的改变的机制。在大多数情况下,这消除了适配器重新查询数据库的需求。(2)改变应用改变应用允许同步适配器将从它们的后端接收的改变应用到本地存储平台。期望适配器将改变转换到存储平台模式。改变应用的主要功能是自动检测冲突。如在存储平台到存储平台同步的情况下,冲突被定义成在互相不知道时作出的两个重叠的改变。当适配器使用改变应用时,它们必须指定对其执行冲突检测的定位点。若检测到未被适配器的知识覆盖的重叠的本地改变,则改变应用引起冲突。类似于改变枚举,适配器可使用存储的或提供的定位点。改变应用程序支持适配器专用元数据的有效存储。那样的数据可由适配器将其附加到要应用的改变上,且可被同步服务存储。数据可在下次改变枚举时返回。(3)冲突分解上述冲突分解机制(包括日志记录和自动分解选项)也对同步适配器可用。在应用改变时,同步适配器能指定用于冲突分解的策略。若指定,则冲突可被传递到指定的冲突处理程序并予以分解(若可能)。冲突也能被记入日志。当试图将本地改变应用到后端时,适配器可检测冲突。在那样情况下,适配器仍可以将冲突传递到同步运行库,以按策略分解。此外,同步适配器可请求任何由同步服务检测的冲突发回给它们以便处理。在后端能存储或分解冲突的情况下这特别方便。b)适配器实现虽然某些“适配器”简单地是利用运行库接口的应用程序,然而鼓励适配器实现标准的适配器接口。这些接口允许同步控制应用程序请求适配器按给定的同步概况执行同步;取消正进行的同步;以及接收关于正进行同步的进展报告(完成百分比)。3.安全性同步服务努力将尽可能少的同步引入到由存储平台实现的安全模式中。不是对同步定义新的权限,而是使用现有的权限。具体地,·能读数据存储项目的任何人可枚举对该项目的改变;·能写到数据存储项目的任何人可向该项目应用改变;以及·能扩展数据存储项目的任何人可将同步元数据与该项目关联。同步服务不维护安全授权信息。当在复制品A由用户U作出改变,且将其转发到复制品B时,该改变最初在A处(由U)作出的事实丢失了。若B将此改变转发到复制品C,则这是在B的授权而不是在A的授权下完成的。这就导致下述限制若不信任一个复制品对一个项目作出它自己的改变,它不能转发由其它复制品作出的改变。在启动同步服务时,由同步控制应用程序完成。同步服务人格化SCA的身份,并在该身份下完成所有操作(本地的和远程的)。作为说明,观察到用户U不能使本地同步服务从远程存储平台检索对用户U不具有读访问的项目的改变。4.可管理性监视复制品的分布式共同体是复杂的问题。同步服务可使用“扫描”算法来收集和分发关于该复制品的状态的信息。扫描算法的属性确保关于所有所配置的复制品的信息最终被收集,且检测到该失败(无响应)的复制品。在每个复制品上可得到共同体范围的监视信息。可在任意选取的复制品上运行监视工具,以检查此监视信息并作出管理决策。在受影响的复制品上必须直接作出配置改变。G.传统文件互操作性如上提到,至少在某些实施例中,本发明的存储平台旨在被实施为计算机系统的硬件/软件接口系统的整体部分。例如,本发明的存储平台可被实施为如MicrosoftWindows家族操作系统的操作系统整体部分。在这方面,存储平台API成为操作系统API的一部分,应用程序通过它与操作系统交互。因此,存储平台成为装置,应用程序通过它将信息存到操作系统上,且从而基于项目的存储平台的数据模型替代了这一操作系统的传统文件系统。例如,当在MicrosoftWindows家族操作系统中实施时,存储平台可替代在该操作系统中实现的NTFS文件系统。当前,应用程序通过由Windows家族操作系统展现的Win32API来访问NTFS文件系统的服务。然而,应认识到,完全用本发明的存储平台替代NTFS文件系统需要重新编码现有的基于Win32的应用程序,且那样的重新编码可能是不合需要的,因此本发明的存储平台提供与如NTFS等现有文件系统的某种互操作性是有益的。从而,在本发明的一个实施例中,存储平台使依赖于Win32编程模型的应用程序能同时访问存储平台的数据存储以及传统的NTFS文件系统的内容。为此,存储平台使用作为Win32命名约定的超集的命名约定以便于容易的互操作性。此外,存储平台支持通过Win32API访问存储在存储平台卷中的文件和目录。1.互操作性模型依照本发明的这一方面,且依照上述示例性实施例,存储平台实现了一种名字空间,其中可组织非文件和文件项目。采用该模型,可获得以下优点1.数据存储中的文件夹可包含文件和非文件项目,由此为文件和模式化的数据呈现了单个名字空间。此外,它也为所有用户数据提供了同一的安全、共享和管理模型。2.由于文件和非文件项目都可使用存储平台API来访问,且该方法中没有为文件施加特殊规则,因此它为应用程序开发者提出了一种更清楚的编程模型来工作。3.所有名字空间操作都通过存储平台,且因此被同步地处理。重要的是注意,深层的属性升级(文件内容的驱散)仍异步地发生,但是同步操作为用户和应用程序提供了更可预测的环境。作为该模型的结果,在本实施例中,可能不在被合并到存储平台数据存储的数据源上提供搜索能力。这包括可移动媒体、远程服务器和本地磁盘上的文件。提供了为驻留在外部文件系统中的项目显示存储平台中的代理服务器项目(快捷方式+升级的元数据)的同步适配器。代理服务器项目不试图按照数据源的名字空间层次或安全性来模仿文件。在文件和非文件内容之间的名字空间和编程模型上实现的对称性提供了应用程序用于随时间的推移将来自文件系统的内容移植到存储平台数据存储中的更结构化的项目的更好路径。通过提供存储平台数据存储中的本机文件项目类型,应用程序可将文件数据转移到存储平台,同时仍能够通过Win32来操纵该数据。最终,应用程序可能完全移植到存储平台API,且按照存储平台项目而非文件来结构化其数据。2.数据存储特征为提供期望的互操作性等级,在一个实施例中,实现存储平台数据存储的以下特征。a)非卷存储平台数据存储不被展现为单独的文件系统卷。存储平台充分利用了直接主存在NTFS上的FILESTREAM。由此,没有对盘上格式的改变,由此消除了在卷级将存储平台展现为新文件系统的需求。相反,数据存储(名字空间)是对应于NTFS卷来构造的。后退名字空间的该部分的数据库和FILESTREAM位于与存储平台数据存储相关联的NTFS卷上。也提供了对应于系统卷的数据存储。b)存储结构存储的结构最好用一个示例来说明。作为一个示例,考虑名为HomeMachine的机器的系统卷上的目录树,如图16所示。依照本发明的文件系统互操作性特征,对应于c\drive,存在通过例如称为“WiinFSOnC”的UNC共享展现给Win32API的存储平台数据存储。这使得相关联的数据存储可通过以下UNC名来访问\\HomeMachine\WinFSOnC。在该实施例中,文件和/或文件夹需要从NTFS显式地移植到存储平台。因此,如果用户希望将MyDocuments文件夹移至存储平台数据存储以利用由存储平台提供的所有额外的搜索/分类特征,则该分层结构将如图17所示。重要的是注意,这些文件夹在本示例中实际移动。另一点要注意的是,名字空间移至存储平台中,实际的流被重命名为FILESTREAM,在存储平台内挂钩适当的指针。c)不移植所有文件对应于用户数据或需要存储平台提供的搜索/分类的文件是移植到存储平台数据存储的候选者。较佳地,为限制与存储平台的应用程序兼容性问题,在MicrosoftWindows操作系统的上下文中,移植到本发明的存储平台的该组文件被限于MyDocuments文件夹中的文件、InternetExplorer(IE)Favorites、IEHistory和DocumentsandSettings目录中的Desktop.ini文件。较佳地,移植Windows系统文件是不允许的。d)对存储平台文件的NTFS名字空间访问在此处所描述的实施例中,期望移植到存储平台的文件不能通过NTFS名字空间来访问,即使实际文件流是以NTFS储存的。以此方式,避免了由多线程实现引起的复杂锁定和安全性问题。e)期望的名字空间/驱动器字母对存储平台中的文件和文件夹的访问是通过\\<机器名>\<WinFS共享名>形式的UNC名来提供的。对于需要驱动器字母用于操作的应用程序类,可将驱动器字母映射到该UNC名。I.存储平台API如上所述,存储平台包括API,它使应用程序能访问上面讨论的存储平台的特征和能力,并访问存储在数据存储中的项目。本节描述本发明的存储平台的存储平台API的一个实施例。图19示出按本实施例的存储平台API的基本体系结构。存储平台API使用SQL客户机1900与本地数据存储302对话,并还使用SQL客户机1900与远程数存储(如数据存储340)对话。本地存储还可使用DQP(分布式查询处理器)或通过上述的存储平台同步服务(“Sync”)与远程数据存储340对话。存储平台API322还担当数据存储通知的桥接器API,将应用程序的下标传送到通知引擎332,并如上所述将通知路由到应用程序(如应用程序350a、350b或350c)。在一个实施例中,存储平台API322还定义受限制的“提供者”体系结构,使得它能访问MicrosoftExchange和AD中的数据。1.综述本发明的存储平台API的本实施例的数据访问机制解决了四个领域查询、导航、动作、事件。查询在一个实施例中,存储平台数据存储是在关系型数据库引擎314上实现的;结果,SQL语言的完全表达性能力在存储平台中是固有的。较高级查询对象提供了用于查询存储的简化模型,但是可能不封装存储的完全表达性能力。导航存储平台数据模型在底层数据库抽象上构建了一种丰富的、可扩展的类型系统。对于开发者而言,存储平台数据是项目的网。存储平台API允许通过过滤、关系、文件夹等在项目之间导航。这是比基本SQL查询更高级的抽象;同时,它允许对熟悉的CLR编码模式使用丰富的过滤和导航能力。动作存储平台API展现所有项目上公用的动作—Create(创建)、Delete(删除)、Update(更新);这些被展现为对象上的方法。另外,诸如SendMail(发送邮件)、CheckFreeBusy(检查空闲和忙碌)等域专用动作也作为方法可用。API框架使用ISV可用于通过定义附加动作来添加值的良好定义的模式。事件存储平台中的数据是动态的。为使应用程序在存储中的数据改变时做出反应,API向开发者展现了丰富的事件、订阅和通知能力。2.命名和范围在名字空间和命名之间进行区分是有用的。如常用的,术语名字空间指的是某一系统中可用的所有名字的集合。系统可以是XML模式、程序、web、所有ftp站点(及其内容)的集合等等。命名是用于向名字空间内所有感兴趣的条目分配唯一名字的过程或算法。由此,命名是感兴趣的,因为期望无岐义地涉及名字空间内的给定单元。由此,如此处所使用的,术语“名字空间”指的是全域中所有存储平台示例中可用的所有名字的集合。项目是存储平台名字空间中的命名实体。UNC命名约定用于确保项目名字的唯一性。全域中每一存储平台存储中的每一项目可通过UNC名字来寻址。存储平台名字空间中的最高组织级别是服务—它仅仅是存储平台的一个实例。组织的下一级是卷。卷是项目的最大匿名容器。每一存储平台实例包含一个或多个卷。在卷内的是项目。项目是存储平台中的数据原子。真实世界中的数据几乎总是依照在给定领域中有意义的某一系统来组织。在所有这样的数据组织模式下的是将数据的全域划分成命名组的概念。如上所述,这一概念在存储平台中由文件夹的概念来建模。文件夹是一种特殊类型的项目;有两种类型的文件夹包含文件夹和虚拟文件夹。参考图18,包含文件夹是一个项目,它包含与其它项目的持有关系,且与通常概念的文件系统文件夹等价。每个项目“包含”在至少一个包含文件夹中。虚拟文件夹是组织项目集合的更动态方法;它仅仅是给定一组项目的名字—该组项目是显式地枚举或通过查询指定的。虚拟文件夹本身是项目,且可以被认为是表示与一组项目的一组(非持有)关系。有时候,需要对包含的更紧密概念进行建模;例如,嵌入在电子邮件消息中的Word文档在某种意义上比例如包含在文件夹中的文件更紧密地绑定到其容器。这一概念是由嵌入项目的概念来表达的。嵌入项目具有一种特殊的关系,它引用另一项目;引用的项目可仅绑定到包含项目或仅在包含项目的上下文中操纵。最后,存储平台提供了类别的概念作为对项目和元素的分类的方式。存储平台中的每一项目或元素可具有与其相关联的一个或多个类别。类别本质上只是被标记到项目/元素上的名字。该名字可以在搜索中使用。存储平台数据模型允许定义类别的分层结构,从而允许数据的树状分类。项目的一种无岐义的名字是三元组(<服务名>,<卷ID>,<项目ID>)。某些项目(尤其是文件夹和虚拟文件夹)是其它项目的集合。这引起一种标识项目的替换方式(<服务名>,<卷ID>,<项目路径>)。存储平台名字包括服务上下文的概念服务上下文是映射到(<卷名>,<路径>)对的名字。它标识了一个项目或一组项目—例如,文件夹、虚拟文件夹等。对于服务上下文,用于存储平台名字空间中的任何项目的UNC名成为\\<服务名>\<服务上下文>\<项目路径>用户可创建和删除服务上下文。同样,每一卷中的根目录具有预定义的上下文卷名$。项目上下文通过限制返回给存活在指定路径中的项目的结果来定查询(例如,查找操作)的范围。3.存储平台API组件图20示意性地表示依照本发明的本实施例的存储平台API的各种组件。存储平台API包括下列组件(1)数据类2002,它代表存储平台元素和项目类型;(2)运行库架构2004,它管理对象的持久性并提供支持类2006;以及(3)工具2008,它用于从存储平台模式生成CLR类。依照本发明的一个方面,在设计时,模式作者向一组存储平台API设计时向工具2008提交模式文档2010以及用于域方法的代码2012。这些工具生成客户机方数据类2002和存储模式2014以及该模式的存储类定义2016。“域”指的是特定的模式;例如,谈论联系人模式中的类的域方法等等。这些数据类2002在运行时由应用程序开发者与存储平台API运行库架构类2006协作使用来操纵存储平台数据。为说明本发明的存储平台API的各方面,基于示例性联系人模式呈现了若干示例。该示例性模式的图示表示在图21A和21B中示出。4.数据类依照本发明的一方面,存储平台数据存储中的每一项目、项目扩展和元素类型以及每一关系在存储平台API中具有对应的类。大致上,类型的字段映射到类的字段。存储平台中的每一项目、项目扩展和元素作为存储平台API中的对应类的对象可用。开发者可查询、创建、修改或删除这些对象。存储平台包括一组初始模式。每一模式定义了一组项目和元素类型,以及一组关系。以下是用于从这些模式实体生成数据类的算法的一个实施例对于每一模式S对于S中的每一项目I,生成名为System.Storage.S.I的类。该类具有以下成员·重载的构造函数,包括允许指定新项目的初始文件夹和名字的构造函数。·I中每一字段的属性。如果字段是多值的,则属性将是对应的元素类型的集合。·找出匹配过滤器的多个项目的重载的静态方法(例如,名为“FindAll”的方法)。·找出匹配过滤器的单个项目的重载的静态方法(例如,名为“FindOne”的方法)。·给定其ID找出项目的静态方法(例如,名为“FindByID”的方法)。·给定其相对于项目上下文的名字找出项目的静态方法(例如,名为“FindByName”的方法)。·保存对项目的改变的方法(例如,名为“Update”的方法)。·创建项目的新实例的重载的静态Create方法。这些方法允许以各种方式指定项目的初始文件夹。对于S中的每一元素E,生成名为System.Storage.S.E的类。该类具有以下成员·E中的每一字段的属性。如果字段是多值的,则属性将是对应的元素类型的集合。对于S中的每一元素E,生成名为System.Storage.S.ECollection的类。该类遵循用于强类型化的集合类的通用.NET构架方针。对于基于关系的元素类型,该类还将包括以下成员·找出匹配隐式地包括其中集合在源角色中出现的项目的过滤器的项目的多个对象的重载的方法。重载包括允许基于项目子类型的过滤的某些方法(例如,名为“FindAllTargetItems”的方法)。·找出匹配隐式地包括其中集合在源角色中出现的项目的过滤器的单个项目对象的重载的方法。重载包括允许基于项目子类型来过滤的某些方法(例如,名为“FindOneTargetItem”的方法)。·找出匹配隐式地包括其中集合在源角色中出现的项目的过滤器的嵌套元素类型的对象的重载的方法(例如,名为“FindAllRelationships”的方法)。·找出匹配隐式地包括其中集合在源角色中出现的项目的过滤器的嵌套元素类型的对象的重载的方法(例如,名为“FindAllRelationshipsForTarget”方法)。·找出匹配隐式地包括其中集合在源角色中出现的项目的过滤器的嵌套元素类型的单个对象的重载的方法(例如,名为“FindOneRelationship”的方法)。·找出匹配隐式地包括其中集合在源角色中出现的项目的过滤器的嵌套元素类型的单个对象的重载的方法(例如,名为“FindOneRelationshipForTarget”的方法)。对于S中的关系R,生成名为System.Storage.S.R的类。该类具有一个或两个子类,取决于是一个还是两个关系角色指定了端点字段。也可以此方式为所创建的每一项目扩展创建类。数据类存在于System.Storage.<模式名>名字空间中,其中<模式名>是对应的模式的名字—诸如Contacts(联系人)、Files(文件)等。例如,对应于联系人模式的所有类在System.Storage.Contacts名字空间中。作为示例,参考图21A和21B,联系人模式导致包含在System.Storage.Contact名字空间中的以下类·项目Item、Folder、WellKnownFolder、LocalMachineDataFolder、UserDataFolder、Principal、Service、GroupService、PersonService、PresenceService、ContactService、ADService、Person、User、Group、Organization、HouseHold·元素NestedElementBase、NestedElement、IdentityKey、SecurityID、EAddress、ContactEAddress、TelephoneNumber、SMTPEAddress、InstantMessagingAddress、Template、TemplateRelationship、LocationRelationship、FamilyEventLocationRelationship、HouseHoldLocationRelationship、RoleOccupancy、EmployeeData、GroupMemberShip、OrganizationLocationRelationship、HouseHoldMemberData、FamilyData、SpouseData、ChildData作为另一示例,如在联系人模式中定义的Person类型的详细结构以XML示出如下<TypeName=″Person″MajorVersion=″1″MinorVersion=″0″ExtendsType=″Core.Principal″ExtendsVersion=″1″><FieldName=″Birthdate″Type=″thestorageplatformTypes.datetime″Nullable=″true″TypeMajorVersion=″1″/><FieldName=″Gender″Type=″Base.CategoryRef″Nullable=″true″MultiValued=″false″TypeMajorVersion=″1″/><FieldName=″PersonalNames″Type=″Contact.FullName″Nullable=″true″MultiValued=″true″TypeMajorVersion=″1″/><FieldName=″PersonalEAddresses″Type=″Core.EAddress″Nullable=″true″MultiValued=″true″TypeMajorVersion=″1″/><FieldName=″PersonalPostalAddresses″Type=″Core.PostalAddress″Nullable=″true″MultiValued=″true″TypeMajorVersion=″1″/><FieldName=″PersonalPicture″Type=″thestorageplatformTypes.image″Nullable=″true″TypeMajorVersion=″1″/><FieldName=″Notes″Type=″Core.RichText″Nullable=″true″MultiValued=″true″TypeMajorVersion=″1″/><FieldName=″Profession″Type=″Base.CategoryRef″Nullable=″true″MultiValued=″true″TypeMajorVersion=″1″/><FieldName=″DataSource″Type=″Base.IdentityKey″Nullable=″true″MultiValued=″true″TypeMajorVersion=″1″/><FieldName=″ExpirationDate″Type=″thestorageplatformTypes.datetime″Nullable=″true″TypeMajorVersion=″1″/><FieldName=″HasAllAddressBookData″Type=″thestorageplatformTypes.bit″Nullable=″true″TypeMajorVersion=″1″/><FieldName=″EmployeeOf″Type=″Contact.EmployeeData″Nullable=″true″MultiValued=″true″TypeMajorVersion=″1″/></Type>该类型导致以下类(仅示出了公有成员)partialpublicclassPersonSystem.Storage.Core.Principal,System.Windows.Data.IDataUnit{publicSystem.Data.SqlTypes.SqlDateTimeBirthdate{get;set;}publicSystem.Storage.Base.CategoryRefGender{get;set}publicSystem.Storage.Contact.FullNameCollectionPersonalNames{get;}publicSystem.Storage.Core.EAddressCollectionPersonalEAddresses{get;}publicSystem.Storage.Core.PostalAddressCollectionPersonalPostalAddresses{get;}publicSystem.Data.SqlTypes.SqlBinaryPersonalPicture{get;set;}publicSystem.Storage.Core.RichTextCollectionNotes{get;}publicSystem.Storage.Base.CategoryRefCollectionProfession{get;}publicSystem.Storage.Base.IdentityKeyCollectionDataSource{get;}publicSystem.Data.SqlTypes.SqlDateTimeExpirationDate{get;set;}publicSystem.Data.SqlTypes.SqlBooleanHasAllAddressBookData{get;set;}publicSystem.Storage.Contact.EmployeeDataCollectionEmployeeOf{get;}publicPerson();publicPerson(System.Storage.Base.Folderfolder,stringname);publicstaticnewSystem.Storage.FindResultFindAll(System.Storage.ItemStorestore);publicstaticnewSystem.Storage.FindResultFindAll(System.Storage.ItemStorestore,stringfilter);publicstaticnewPersonFindOne(System.Storage.ItemStorestore,stringfilter);publicneweventSystem.Windows.Data.PropertyChangedEventHandlerPropertyChangedHandler;publicstaticnewPersonFindByID(System.Storage.ItemStorestore,longitem_key);}作为又一示例,联系人模式中定义的TelephoneNumber类型的详细结构以XML示出如下<TypeName=″TelephoneNumber″ExtendsType=″Core.EAddress″MajorVersion=″1″MinorVersion=″0″ExtendsVersion=″1″><FieldName=″CountryCode″Type=″thestorageplatformTypes.nvarchar(50)″Nullable=″true″MultiValued=″false″TypeMajorVersion=″1″/><FieldName=″AreaCode″Type=″thestorageplatformTypes.nvarchar(256)″Nullable=″true″TypeMajorVersion=″1″/><FieldName=″Number″Type=″thestorageplatformTypes.nvarchar(256)″Nullable=″true″TypeMajorVersion=″1″/><FieldName=″Extension″Type=″thestorageplatformTypes.nvarchar(256)″Nullable=″true″TypeMajorVersion=″1″/><FieldName=″PIN″Type=″thestorageplatformTypes.nvarchar(50)″Nullable=″true″TypeMajorVersion=″1″/></Type>该类型导致以下类(仅示出了公有成员)partialpublicclassTelephoneNumberSystem.Storage.Core.EAddress,System.Windows.Data.IDataUnit{publicSystem.Data.SqlTypes.SqlStringCountryCode{get;set;}publicSystem.Data.SqlTypes.SqlStringAreaCode{get;set;}publicSystem.Data.SqlTypes.SqlStringNumber{get;set;}publicSystem.Data.SqlTypes.SqlStringExtension{get;set;}publicSystem.Data.SqlTypes.SqlStringPIN{get;set;}从给定模式得到的类的分层结构直接反映了该模式中的分层结构。作为一个示例,考虑联系人模式中定义的Item类型(见图21A和21B)。在存储平台API中对应于该类型的类分层结构如下ObjectDataClassElementBaseRootItemBaseItemPrincipalGroupHouseholdOrganizationPersonUserServicePresenceServiceContactServiceADServiceRootNestedBase…(元素类)又一模式,即允许表示系统中的所有音频/视频媒体(断开的音频文件、音频CD、DVD、家庭视频等)的模式使用户/应用程序能够存储、组织、搜索和操纵不同种类的音频/视频媒体。基本媒体文档模式足够一般以表示任何媒体,且对该基本模式的扩展被设计成为音频和视频媒体分开处理域专用属性。该模式以及许多其它模式被构想为直接或间接在核心模式下操作。5.运行时架构基本存储平台API编程模型是对象持久性的。应用程序在存储上执行搜索,并在存储中检索表示数据的对象。应用程序修改检索的对象或创建新对象,然后使其改变被传播到存储。该过程是由ItemContext(项目上下文)对象来管理的。搜索使用ItemSearcher(项目搜索器)对象来执行,且搜索结果可通过FindResult(寻找结果)对象来访问。a)运行时架构类依照本发明的另一发明性方面,运行时架构实现多个类来支持数据类的操作。这些架构类为数据类定义了一组公共的行为,且连同数据类一起为存储平台API提供了基本编程模型。运行时架构中的类属于System.Storage名字空间。在本实施例中,架构类包括以下主要类ItemContext、ItemSearcher和FindResult。也可提供其它次要类、枚举值以及代表。(1)ItemContextItemContext对象(i)表示应用程序希望搜索的一组项目域,(ii)为每一对象维护表示从存储平台中检索的数据的状态的状态信息,以及(iii)管理当与存储平台交互时使用的事务以及可与存储平台互操作的任何文件系统。作为对象持久性引擎,ItemContext提供了以下服务1.将从存储中读取的数据反串行化成对象。2.维护对象身份(同一对象用于表示给定的项目,而无论该项目被包括在查询结果中多少次)。3.跟踪对象状态。ItemContext也执行对存储平台唯一的多个服务1.生成和执行持久保存改变所需的存储平台更新元素操作。2.创建允许引用关系的无缝导航并允许从多域搜索中检索要修改和保存的对象所需的到多个数据存储的连接。3.确保当对象的改变表示要保存该项目时支持文件的项目被正确地更新。4.管理跨多个存储平台连接的事务,并且在更新储存在支持文件的项目中的数据以及文件流属性时管理以事务方式处理的文件系统。5.执行将存储平台关系语义、支持文件的项目以及流类型化的属性考虑在内的创建、复制、移动和删除操作。附录A提供了依照其一个实施例列出ItemContext类的源代码。(2)ItemSearcherItemSearcher类支持简单的搜索,该搜索返回整个Item对象、Item对象的流、或从Item对象投影的值的流。ItemSearcher封装了对以下所有公共的核心功能应目标类型的概念以及应用于该目标类型的参数化的过滤器。ItemSearcher也允许预编译或准备搜索器,作为在以多种类型执行同一操作时的优化。附录B提供了依照其一个实施例列出ItemSearcher类和若干紧密相关的类的源代码。(a)目标类型搜索目标类型是在构造ItemSearcher时设置的。目标类型是映射到可由数据存储查询的范围的CLR类型。具体地,它是映射到项目、关系和关系扩展类型以及模式化视图的CLR类型。当使用ItemContext.GetSearcher方法检索搜索器时,搜索器的目标类型被指定为参数。当在项目、关系或项目扩展类型上调用静态GetSeacher方法(例如,Person.GetSearcher)时,目标类型是项目、关系或项目扩展类型。ItemSearcher中提供的搜索表达式(例如,搜索过滤器和通过查询操作,或投影定义)总是相对于搜索目标类型。这些表达式可指定目标类型的属性(包括嵌套元素的属性),并可指定到如别处所描述的关系和项目扩展的联结。搜索目标类型可通过只读属性(例如,Item.Searcher.Type属性)获得。(b)过滤器ItemSearcher包含指定过滤器的属性(例如,名为“Filters”的属性,作为SearchExpression对象的集合),该过滤器定义了搜索中使用的过滤器。集合中的所有过滤器在执行搜索时使用逻辑和运算符来组合。过滤器可包含参数引用。参数值是通过Parameters属性来指定的。(c)准备搜索在可能仅用一个参数改变来重复执行同一搜索的情况下,可通过预编译或准备搜索来提高某些性能。这是用ItemSearcher上的一组准备方法(例如,准备返回一个或多个项目的Find(查找)的方法,可能名为“PrepareFind”;以及准备返回投影的Find的方法,可能名为“PrepareProject”)来实现的。例如ItemSearchersearcher=…;PreparedFindpf=searcher.PrepareFind();…result=pf.FindAll();…result=pf.FindAll();(d)查找选项存在可应用于简单搜索的多个选项。这些可在例如FindOptions(查找选项)对象中指定并被传递到Find方法。例如ItemSearchersearcher=Person.GetSearcher(context);FindOptionsoptions=newFindOptions();options.MaxResults=10;options.SortOptions.Add(“PersonalNames.Surname”,SortOrder.Ascending);FindResultresult=searcher.FindAll(options);作为一种便利,也可将排序选项直接传递给Find方法ItemSearchersearcher=Person.GetSearcher(context);FindResultresult=searcher.FindAll(newSortOption(“PersonalNames.Surname”,SortOrder.Ascending));DelayLoad(延迟负载)选项确定当检索搜索结果时是否加载大二进制属性的值,或者是否将加载延迟到它们被引用之后。MaxResults(最大结果)选项确定了返回的结果的最大数量。这等效于在SQL查询中指定TOP。它通常结合排序来使用。SortOption(排序选项)对象的序列可被指定(例如,使用FindOptions.SortOptions属性)。搜索结果将如由第一个SortOption对象所指定的那样排序,然后如由第二个SortOption对象所指定的排序,依此类推。SortOption指定了指示将用于排序的属性的搜索表达式。表达式指定了以下之一1.搜索目标类型中的标量属性;2.可通过遍历单值属性从搜索目标类型到达的嵌套元素中的标量属性;或者3.具有有效自变量的集合函数的结果(例如,Max应用于可通过遍历多值属性或关系从搜索目标类型到达的嵌套元素中的标量属性)。例如,假定搜索目标类型是System.Storage.Contact.Person1.“Birthdate”—有效,Birthdate是Person类型的标量属性;2.“PersonalNames.Surname”—无效,PersonalNames是多值属性,且未使用任何集合函数;3.“Count(PersonalNames)”—有效,PersonalNames的计数;4.“Case(Contact.MemberOfHousehold).Household.HouseholdEAddresses.StartDate”—无效,使用了关系和多值属性,而没有集合函数。5.“Max(Cast(Contact.MemberOfHousehold).Household.HouseholdEAddresses.StartDate)”—有效,最近的家庭电子地址起始日期。(3)项目结果流(“FindResult”)ItemSearcher(例如,通过FindAll方法)返回可用于访问由搜索返回的对象的对象(例如,“FindResult”对象)。附录C提供了依照其一个实施例列出FindResult类和若干紧密相关的类的源代码。存在用于从FindResult对象获得结果的两种不同的方法使用由IObjectReader(对象读取器接口)(以及IAsyncObjectReader(异步对象读取器接口))定义的读取器模式,以及使用IEnumerable(可枚举接口)和IEnumerator(枚举器接口)定义的枚举器模式。枚举器模式是CLR中的标准,且支持如C#的foreach等语言构造。例如ItemSearchersearcher=Person.GetSearcher(context);searcher.Filters.Add(“PersonalNames.Surname=‘Smith’”);FindResultresult=searcher.FindAll();foreach(Personpersoninresult)…;支持读取器模式,因为它允许通过在某些情况下消除数据副本来更有效地处理结果。例如ItemSearchersearcher=Person.GetSearcher(context);searcher.Filters.Add(“PersonalNames.SurName=‘Smith’”);FindResultresult=searcher.FindAll();while(result.Read()){Personperson=(Person)result.Current;…}另外,读取器模式支持异步操作ItemSearchersearcher=Person.GetSearcher(context);searcher.Filters.Add(“PersonalNames.SurName=‘Smith’”);FindResultresult=searcher.FindAll();IAysncResultasyncResult=result.BeginRead(newAsyncCallback(MyCallback));voidMyCallback(IAsyncResultasyncResult){if(result.EndRead(asyncResult)){Personperson=(Person)result.Current;…}}在本实施例中,FindResult在它不再需要时应当被关闭。这可以通过调用Close(关闭)方法或使用诸如C#所使用的语句等语言构造来完成。例如ItemSearchersearcher=Person.GetSearcher(context);searcher.Filters.Add(“PersonalNames.SurName=‘Smith’”);using(FindResultresult=searcher.FindAll()){while(result.Read()){Personperson=(Person)result.Current;…}}b)操作中的运行时架构图22示出了操作中的运行时架构。该运行时架构如下操作1.应用程序350a、350b或350c绑定到存储平台中的项目。2.架构2004创建对应于绑定的项目的ItemContext(项目上下文)对象2202,并将其返回给应用程序。3.应用程序在该ItemContext上提交Find以获得项目集合;所返回的集合在概念上是对象图2204(由于关系)。4.应用程序改变、删除和插入数据。5.应用程序通过调用Update()方法保存改变。c)公共编程模式本节提供了存储平台API架构类如何能够用于操纵数据存储中的项目的各种示例。(1)打开和关闭ItemContext对象应用程序例如通过调用静态的ItemContext.Open方法并提供标识将与ItemContext相关联的项目域的一个或多个路径来获得它将用于与数据存储交互的ItemContext对象。项目域定使用ItemContext所执行的搜索的范围,使得仅域项目和包含在该项目中的项目将遭受搜索。示例如下打开在本地计算机上具有DefaultStore存储平台共享的ItemContextItemContextic=ItemContext.Open()打开具有给定存储平台共享的ItemContextItemContextic=ItemContext.Open(@″\\myserver1\DefaultStore″);打开具有在存储平台共享下的项目的ItemContextItemContextic=ItemContext.Open(@″\\myserver1\WinFSSpecs\api\m6″);打开具有多个项目域的ItemContextItemContextic=ItemContext.Open(@″\\myserver1\MyDocuments″,@″\\jane1\MyDocuments″,@″\\jane2\MyDocuments″);当不再需要ItemContext时,它必须被关闭。显式地关闭ItemContextItemContextic=ItemContext.Open();…ic.Close();使用具有ItemContext的语句来关闭using(ItemContextic=ItemContext.Open()){…;}(2)搜索对象依照本发明的另一方面,存储平台API提供了使得应用程序员能够基于数据存储中的项目的各种属性,以将应用程序员与底层数据库引擎的查询语言的细节隔离的方式来形成查询的简化的查询模型。应用程序可跨在使用由ItemContext.GetSearcher方法返回的ItemSearcher对象打开ItemContext时指定的域执行搜索。搜索结果使用FindResult对象来访问。假定对以下示例的以下声明ItemContextic=…;ItemSearchersearcher=null;FindResultresult=null;Itemitem=null;Relationshiprelationship=null;ItemExtensionitemExtension=null;基本搜索模式涉及使用通过调用GetSearcher(获得搜索器)方法从ItemContext检索到的ItemSearcher对象。搜索给定类型的所有项目searcher=ic.GetSearcher(typeof(Person));result=searcher.FindAll();foreach(结果中的Personp)…;搜索满足过滤器的给定类型的项目searcher=ic.GetSearcher(typeof(Person));searcher.Filters.Add(″PersonalNames.Surname=′Smith′″);result=searcher.FindAll();foreach(结果中的Personp)…;使用过滤器串中的参数searcher=ic.GetSearcher(typeof(Person));searcher.Filters.Add(″Birthdate<@Date″);searcher.Parameters[″Date″]=someDate;result=searcher.FindAll();foreach(结果中的Personp)…;搜索给定类型且满足过滤器的关系searcher=ic.GetSearcher(typeof(EmployeeEmployer));searcher.Filters.Add(″StartDate<=@DateAND(EndDate>=@DateORisnull(EndDate))″);searcher.Parameters[″Date″]=someDate;result=searcher.FindAll();Foreach(结果中的EmployeeEmployeree)…;搜索具有给定类型且满足过滤器的关系的项目searcher=ic.GetSearcher(typeof(Folder));searcher.Filters.Add(″MemberRelationships.Namelike′A%′″);//见[ApiRel]result=searcher.FindAll();Foreach(结果中的Folderf)…;搜索给定类型且满足过滤器的项目扩展searcher=ic.GetSearcher(typeof(ShellExtension));searcher.Filters.Add(″Keywords.Value=′Foo′″);result=searcher.FindAll();foreach(结果中的ShellExtensionse)…;搜索具有给定类型且满足过滤器的项目扩展的项目searcher=ic.GetSearcher(typeof(Person));searcher.Filters.Add(″Extensions.Cast(@Type).Keywords.Value=′Foo′″);//见[ApiExt]searcher.Parameters[″Type″]=typeof(ShellExtension);result=searcher.FindAll();foreach(结果中的Personp)…;(a)搜索选项可在执行搜索时指定各种选项,包括排序、延迟加载以及限制结果数。排序搜索结果searcher=ic.GetSearcher(typeof(Person));searcher.Filters.Add(″PersonalNames.Surname=′Smith′″);SearchOptionsoptions=newSearchOptions();options.SortOptions.Add(newSortOption(″Birthdate″,SortOrder.Ascending));result=searcher.FindAll(options);foreach(结果中的Personp)…;//有快捷方式可用searcher=ic.GetSearcher(typeof(Person));searcher.Filters.Add(″PersonalNames.Surname=′Smith′″);result=searcher.FindAll(newSortOption(″Birthdate″,SortOrder.Ascending));foreach(结果中的Personp)…;限制结果计数searcher=ic.GetSearcher(typeof(Person));searcher.Filters.Add(″PersonalNames.Surname=′Smith′″);SearchOptionsoptions=newSearchOptions();options.MaxResults=10;result=searcher.FindAll(options);foreach(结果中的Personp)…;(b)FindOne和FindOnly有时仅检索第一个结果是有用的,尤其是当指定排序准则的时候。另外,期望某些搜索仅返回一个对象,且不期望它不返回任何对象。搜索一个对象searcher=ic.GetSearcher(typeof(Person));searcher.Filters.Add(″PersonalNames.Surname=’Smith’″);Personp=searcher.FindOne(newSortOption(″Birthdate″SortOrder.Ascending))asPerson;if(p!=null)…;搜索期望总是存在的单个对象searcher=ic.GetSearcher(typeof(Person));searcher.Filters.Add(″PersonalNames[Surname=’Smith’ANDGivenname’John’]″);try{Personp=searcher.FindOnly();…;}catch(Exceptione){…;}(c)搜索ItemContext上的快捷方式ItemContext上也有使得简单的搜索尽可能容易的若干快捷方式。使用ItemContext.FindAll快捷方式搜索result=ic.FindAll(typeof(Person),″PersonalNames.Surname=′Smith′″);foreach(结果中的Personp)…;使用Item.Context.FindOne快捷方式搜索Personp=ic.FindOne(typeof(Person),″PersonalNames.Surname=′Smith′″)asPerson;(d)按照ID或路径查找另外,可通过提供其id来检索项目、关系以及项目扩展。项目也可按照路径来检索。给定id获得项目、关系以及项目扩展item=ic.FindItemById(iid);relationship=ic.FindRelationshipById(iid,rid);itemExtension=ic.FindItemExtensionById(iid,eid);给定路径获得项目//仅单个域item=ic.FindItemByPath(@″temp\foo.txt″);//单个或多个域result=ic.FindAllItemsByPath(@″temp\foo.txt″);foreach(结果中的ItemI)…;(e)GetSearcher模式在存储平台API中有许多期望提供在另一对象的上下文中或用特定的参数来执行搜索的助手方法的许多地方。GetSearcher模式允许这些情形。在API中有许多GerSearcher方法。其每一个都返回预先被配置成执行给定搜索的ItemSearcher。例如searcher=itemContext.GetSearcher();searcher=Person.GetSearcher();searcher=EmployeeEmployer.GetSearcherGivenEmployer(organization);searcher=person.GetSearcherForReports();可在执行搜索之前添加其它过滤器searcher=person.GetSearcherForReports();searcher.Filters.Add(″PersonalNames.Sumame=’Smith’″);可选择如何希望结果FindResultfindResult=searcher.FindAll();Personperson=searcher.FindOne();(3)更新存储一旦通过搜索检索了对象,它可按应用程序所需修改。也可创建新对象并与现有对象相关联。一旦应用程序做出了形成逻辑组的所有改变,应用程序调用ItemContext.Update来将这些改变持久保存到存储中。依照本发明的存储平台API的又一方面,API收集由应用程序对项目做出的改变,然后将它们组织成其上实现数据存储的数据库引擎(或任何种类的存储引擎)所需的正确更新。这使得应用程序员能够对存储器中的项目做出改变,而将数据存储更新的复杂性留给API。保存对单个项目的改变Personp=ic.FindItemById(pid)asPerson;p.DisplayName=″foo″;p.TelephoneNumbers.Add(newTelephoneNumber(″425-555-1234″));ic.Update();保存对多个项目的改变Householdh1=ic.FindItemById(hid1)asHousehold;Householdh2=ic.FindItemById(hid2)asHousehold;Personp=ic.FindItemById(pid)asPerson;h1.MemberRelationships.Remove(p);h2.MemberRelationships.Add(p);ic.Update();创建新项目Folderf=ic.FindItemById(fid)asFolder;Personp=newPerson();p.DisplayName=″foo″;f.Relationships.Add(newFolderMember(p,″foo″));ic.Update();//或使用快捷方式…Folderf=ic.FindItemById(fid)asFolder;Personp=newPerson();p.DisplayName=″foo″;f.MemberRelationships.Add(p,″foo″);ic.Update();删除关系(以及可能的目标项目)searcher=ic.GetSearcher(typeof(FolderMember));searcher.Filters.Add(″SourceItemId=@fid″);searcher.Filters.Add(″TargetItemId=@pid″);searcher.Parameters.Add(″fid″,fid);searcher.Parameters.Add(″pid″,pid);foreach(searcher.FindAll()中的FolderMemberfm)fm.MarkForDelete();ic.Update();//或使用快捷方式…Folderf=ic.FindItemById(fid)asFolder;f.MemberRelationships.Remove(pid);ic.Update();添加项目扩展Itemitem=ic.FindItemById(iid);MyExtensionme=newMyExtension();me.Foo=″bar″;item.Extensions.Add(me);ic.Update();删除项目扩展searcher=ic.GetSearcher(typeof(MyExtension));searcher.Filters.Add(″ItemId=@iid″);searcher.Parameters.Add(″iid″,iid);foreach(searcher.FindAll()中的MyExtensionme)me.MarkForDelete();ic.Update();//或使用快捷方式…Itemi=ic.FindItemById(iid);i.Extensions.Remove(typeof(MyExtension));ic.Update();6.安全性参考上文的第II.E节(安全性),在存储平台API的本实施例中,在项目上下文上有五种方法可用于检索和修改与存储中的项目相关联的安全策略。这些方法是1.GetItemSecurity;2.SetItemSecurity;3.GetPathSecurity;4.SetPathSecurity;以及5.GetEffectiveItemSecurity。GetItemSecurity和SetItemSecurity提供了检索和修改与项目相关联的显式ACL的机制。该ACL独立于所存在的到项目的路径,且在进行中独立于具有该项目作为目标的持有关系。这使得管理员能够如所期望的独立于所存在的到项目的路径推断出项目的安全性。GetPathSecurity和SetPathSecurity提供了用于检索和修改由于来自另一文件夹的持有关系而存在于项目上的ACL的机制。该ACL由考虑中的路径从各个祖先的ACL到该项目以及对该路径的显式ACL(如果提供的话)组成。该ACL和前一情况下的ACL之间的差别在于该ACL仅当对应的持有关系存在时才在进行中保留,而显式项目ACL独立于对该项目的任何持有关系。可以在项目上用SetItemSecurity和SetPathSecurity设置的ACL被限于可继承的和对象专用的ACE。它们不能包含被标记为继承的任何ACE。GetEffectiveItemSecurity基于ACL以及项目上的显式ACL来检索各种路径。这反映了给定项目上有效的授权策略。7.对关系的支持如上所述,存储平台的数据模型定义了允许项目彼此相关的“关系”。当生成模式的数据类时,为每一关系类型产生以下类1.表示关系本身的类。该类从Relationship类导出,且包含对关系类型专用的成员。2.强类型化的“虚拟”集合类。该类从VirtualRelationshipCollection(虚拟关系集合)导出,且允许创建和删除关系实例。本节描述了存储平台API中对关系的支持。a)基础关系类型存储平台API提供了System.Storage名字空间中形成关系API的基础的多种类型。这些类型是1.Relationship(关系)—所有关系类的基础类型2.VirtualRelationshipCollection(虚拟关系集合)—所有关系集合的基础类型3.ItemReference(项目引用)、ItemIdReference(项目ID引用)、ItemPathReference(项目路径引用)—表示项目引用类型;这些类型之间的关系在图11中示出。(1)Relationship类publicabstractclassRelationshipStoreObject{//用默认值创建protectedRelationship(ItemIDReferencetargetItemReference);//通知关系它被添加到关系集合。对象将询问集合来确定源项目、项目上下文等。internalAddedToCollection(virtualRelationshipCollectioncollection);//关系的IDpublicRelationshipIdRelationshipId{get;}//源项目的IDpublicItemIdSourceItemId{get;}//获得源项目publicItemSourceItem{get;}//对目标项目的引用publicItemIdReferenceTargetItemReference{get;}//获得目标项目(调用TargetItemReference.GetItem())publicItemTargetItem{get;}//确定ItemContext是否已经具有到目标项目的域的连接//(调用TargetItemReference,IsDomainConnected)publicboolisTargetDomainConnected{get;}//目标项目在名字空间中的名字。该名字必须在所有源项目的持有关系上是唯一的publicOptionalValue<string>Name{get;set;}//确定这是持有还是引用关系publicOptionalValue<bool>IsOwned{get;set;}}(2)ItemReference类以下是项目引用类型的基类。publicabstractclassItemReferenceNestedElement{//用默认值创建protectedItemReference();//返回引用的项目publicvirtualItemGetItem();//确定是否建立了到引用的项目的域的连接publicvirtualboolIsDomainConnected();}ItemReference对象可标识存在于除项目引用本身所驻留的存储之外的存储中的项目。每一导出的类型指定了如何构造和使用对远程存储的引用。导出类中GetItem和IsDomainConnected的实现使用ItemContext的多域支持来从所需的域中加载项目,并确定是否已建立了到该域的连接。(3)ItemIdReference类以下是ItemIdReference类—使用项目ID来标识目标项目的项目引用。publicclassItemIdReferenceItemReference{//用默认值构造新的ItemIdReferencepublicItemIdReference();//构造对指定项目的新ItemIdReference。与该项目相关联的域用作定位符publicItemIdReference(Itemitem);//用空定位符和给定的目标项目ID构造新的ItemIdReferencepublicItemIdReference(ItemIditemId);//用给定定位符和项目ID值构造新的ItemIdReferencepublicItemIdReference(stringlocator,ItemIditemId);//目标项目的IDpublicItemIdItemId{get;set;}//标识在其域中包含目标项目的WinFS项目的路径。如果为空,则包含该项目的域是未知的。publicOptionalValue<string>Locator{get;set;}//确定是否建立了到所引用的项目的域的连接publicoverrideboolIsDomainConnected();//检索所引用的项目publicoverrideItemGetItem();}GetItem和IsDomainConnected使用ItemContext的多域支持来从所需的域中加载项目,并确定是否已经建立了到该域的连接。该特征尚未实现。(4)ItemPathReference类ItemPathReference类是使用路径来标识目标项目的项目引用。用于该类的代码如下publicclassItemPathReferenceItemReference{//用默认值构造项目路径引用publicItemPathReference();//不用任何定位符但用给定路径构造项目路径引用publicItemPathReference(stringpath);//用给定定位符和路径构造项目路径引用publicItemPathReference(stringlocator,stringpath);//标识在其域中包含目标项目的WinFS项目的路径publicOptionalValue<string>Locator{get;set;}//相对于由定位符指定的项目域的目标项目路径publicstringPath{get;set;}//确定是否已经建立了到所引用的项目的域的连接publicoverrideboolIsDomainConnected();//检索所引用的项目publicoverrideItemGetItem();}GetItem和IsDomainConnected使用ItemContext的多域支持来从所需的域中加载项目,并确定是否已经建立了到该域的连接。(5)RelationshipId结构RelationshipId结构封装了关系IDGUID。publicclassRelationshipId{//生成新的关系IDGUIDpublicstaticRelationshipIdNewRelationshipId();//用新的关系IDGUID初始化publicRelationshipId();//用指定的GUID初始化publicRelationshipId(GuidId);//用GUID的串标识初始化publicRelationshipId(stringid);//返回关系IDGUID的串标识publicoverridestringToString();//将System.Guid实例转换成RelationshipId实例publicstaticimplicitoperatorRelationshipId(Guidguid);//将RelationshipId实例转换成System.Guid实例publicstaticimplicitoperatorGuid(RelationshipIdrelationshipId);}该值类型包装了GUID,使得参数和属性可被强类型化为关系ID。OptionalValue<RelationshipId>应当在关系ID可为空时使用。诸如由System.Guid.Empty提供的空值不被展现。RelationshipId不能用空值来构造。当使用默认的构造函数来创建RelationshipId时,创建新的GUID。(6)VirtualRelationshipCollection类VirtualRelationshipCollection类实现了包括来自数据存储的对象加上被添加到集合的新对象,但不包括从存储中移除的对象的关系对象的集合。给定源项目ID的指定关系类型的对象被包括在该集合中。这是为每一关系类型生成的关系集合类的基类。该类可用作源项目类型中的属性的类型,以提供对给定项目的关系的访问和简易操纵。枚举VirtualRelationshipCollection的内容可能要求从存储中加载大量的关系对象。应用程序应当在枚举该集合的内容之前使用Count(计数)属性来确定可加载多少关系。向集合添加对象/从集合移除对象不需要从存储中加载关系。为效率起见,较佳的是应用程序搜索满足特定准则的关系,而非使用VirtualRelationshipCollection对象枚举所有的项目关系。向集合添加关系对象使得在调用ItemContext.Update时在存储中创建所表示的关系。从集合中移除关系对象使得当调用ItemContext.Update时在存储中删除所表示的关系。虚拟集合包含正确的对象集,而不管是否通过Item.Relationships集合或该项目上的任何其它关系集合添加/移除了关系对象。以下代码定义了VirtualRelationshipCollection类publicabstractclassVirtualRelationshipCollectionICollection{//该集合包含由项目itemId标识的项目所拥有的类型的关系protectedVirtualRelationshipCollection(ItemContextitemContext,ItemIditemId,TyperelationshipType);//枚举器将返回从存储中检索到的所有对象减去除具有状态Inserted(已插入)的对象//之外的具有状态Deleted(已删除)的任何对象publicIEnumeratorGetEnumerator();//返回由枚举器返回的关系对象的数目的计数。该计数无需从存储中检索所有对象即可计算。publicintCount{get;}//总是返回假publicboolIcollection.IsSynchronized(){get;}//总是返回该对象publicobjectICollection.SyncRoot{get;}//搜索存储中的所需对象publicvoidRefresh();//向集合添加指定的关系。对象必须具有状态Constructed(已构造)或Removed(已移除)。//如果状态为Constructed,它被改为Added(已添加)。如果状态是Removed,则它适当地//改为Retrieved(已检索)或Modified(已修改)。关系的源项目ID必须与当构造集合时//提供的源项目ID相同。protectedvoidAdd(Relationshiprelationship);//从集合中移除指定的关系。对象的状态必须是Added、Retrieved或Modified。//如果对象状态是Added,它将被设为Constructed。如果对象状态是Retrieved或Modifieed,//它将被设为Removed。关系的源项目ID必须与当构造集合时提供的源项目ID相同。protectedvoidRemove(Relationshiprelationship);//从集合中移除的对象publicICollectionRemovedRelationships{get;}//被添加到集合的对象publicICollectionAddedRelationshipas{get;}//从存储中检索的对象。该集合将为空,直到枚举了VirtualRelationshipCollection//或调用了Refresh之后(获得该属性的值不导致填满该集合)。publicICollectionStoredRelationships{get;}//匿名方法publicIAsyncResultBeginGetCount(IAsyncCallbackcallback,objectstate);publicintEndGetCount(IAsyncResultasyncResult);publicIAsyncResultBeginRefresh(IAsyncCallbackcallback,objectstate);publicvoidEndRefresh(IAsyncResultasyncResult);}b)生成的关系类型当为存储平台模式生成类时,为每一关系声明生成一个类。除表示关系本身的类之外,也为每一关系生成关系集合类。这些类用作关系的源或目标项目类中的属性类型。本节描述了使用若干“原型”类生成的类。即,给定指定的关系声明,描述了生成的类。重要的是注意,原型类中使用的类、类型和端点名是关系模式中指定的名字的占位符,且不应当在文字上解释。(1)生成的关系类型本节描述了为每一关系类型生成的类。例如<RelationshipName=″RelationshipPrototype″BaseType=″Holding″><SourceName=″Head″ItemType=″Foo″/><TargetName=″Tail″ItemType=″Bar″ReferenceType=″ItemIDReference″/><PropertyName=″SomeProperty″Type=″WinFSTypes.String″/></Relationship>给定该关系定义RelationshipPrototype(关系原型),将生成RelationshipPrototypeCollection(关系原型集合)类。RelationshipPrototype类表示关系本身。RelationshipPrototypeCollection类提供了对具有指定的项目作为源端点的RelationshipPrototype实例的访问。(2)RelationshipPrototype类这是用于名为“HoldingRelationshipPrototype(持有关系原型)”的持有关系的原型关系类,其中源端点名为“Head”,且指定了“Foo”项目类型,而目标端点名为“Tail”,且指定了“Bar”项目类型。它定义如下publicclassRelationshipPrototypeRelationship{publicRelationshipPrototype(BartailItem);publicRelationshipPrototype(BartailItem,stringname);publicRelationshipPrototype(BartailItem,stringname,boolIsOwned);publicRelationshipPrototype(BartailItem,boolIsOwned);publicRelationshipPrototype(ItemIdReferencetailItemReference);//获得Head项目(调用base.SourceItem)publicFooHeadItem{get;}//获得Tail项目(调用base.TargetItem)publicBarTailItem{get;}//表示关系模式中声明的其它属性。这些是正如项目或嵌套元素类型中的属性那样生成的。publicstringSomeProperty{get;set;}publicstaticItemSearcherGetSearcher(ItemContextitemContext);publicstaticItemSearcherGetSearcher(FooheadItem);publicstaticFindResultFindAll(stringfilter);publicstaticRelationshipPrototypeFindOne(stringfilter);publicstaticRelationshipPrototypeFindOnly(stringfilter);}(3)RelationshipPrototpyeCollection类这是用RelationshipPrototype类生成的原型类,它维护由指定的项目拥有的RelationshipPrototype关系实例的集合。它定义如下publicclassRelationshipPrototypeCollectionVirtualRelationshipCollection{publicRelationshipPrototypeCollection(ItemContextitemContext,ItemIdheadItemId);publicvoidAdd(RelationshipPrototyperelationship);publicRelationshipPrototypeAdd(Barbar);publicRelationshipPrototypeAdd(Barbar,stringname);publicRelationshipPrototypeAdd(Barbar,stringname,boolIsOwned);publicRelationshipPrototypeAdd(Barbar,boolIsOwned);publicvoidRemove(RelationshipPrototyperelationship);publicvoidRemove(Barbar);publicvoidRemove(ItemIdbarItemId);publicvoidRemove(RelationshipIdrelationshipId);publicvoidRemove(stringname);}c)Item类中的关系支持Item类包含提供对其中该项目是关系的源的关系的访问的Relationships属性。Relationships属性具有类型RelationshipCollection。(1)Item类以下代码示出了Item类的关系上下文属性publicabstractclassItemStoreObject{…//其中该项目是源的关系的集合publicRelationshipCollectionRelationships{get;}…}(2)RelationshipCollection类该类提供了对其中给定项目是关系的源的关系实例的访问。它定义如下publicclassRelationsnipCollectionVirtualRelationshipCollection{publicRelationshipCollection(ItemContextitemContext,ItemIdheadItemId);publicvoidAdd(Relationshiprelationship);publicRelationshipAdd(Barbar);publicRelationshipAdd(Barbar,stringname);publicRelationshipAdd(Barbar,stringname,boolIsOwned);publicRelationshipAdd(Barbar,boolIsOwned);publicvoidRemove(Relationshiprelationship);publicvoidRemove(Barbar);publicvoidRemove(ItemIdbarItemId);publicvoidRemove(RelationshipIdrelationshipId);publicvoidRemove(stringname);}d)搜索表达式中的关系支持可能在搜索表达式中指定关系和相关项目之间的联结的遍历。(1)从项目遍历到关系当搜索表达式的当前上下文是一组项目时,项目和其中该项目是源的关系实例之间的联结可使用Item.Relationships属性来完成。联结到特定类型的关系可使用搜索表达式的Cast(类型强制转换)运算符来指定。强类型化的关系集合(例如,Folder.MemberRelationships)也可在搜索表达式中使用。到关系类型的类型强制转换是隐式的。一旦建立了该组关系,该关系的属性可用于判定或作为投影的目标。当用于指定投影的目标时,将返回该组关系。例如,以下语句将找出涉及其中关系的StartDate属性具有大于或等于“1/1/2000”的值的组织的所有人。FindResultresult=Person.FindAll(context,″Relationships.Cast(Contact.EmployeeOfOrganization).StartDate>’1/1/2000’″);如果Person类型具有类型为EmployeeSideEmployerEmployeeRelationships的属性EmployerContext(对EmployeeEmployer关系类型生成的),则这将被写为FindResultresult=Person.FindAll(context,″EmployerRelationships.StartDate>’1/1/2000’″);(2)从关系遍历到项目当搜索表达式的当前上下文是一组关系时,可通过指定端点名来遍历从关系到关系的任一端点的联结。一旦建立了该组相关项目,那些项目的属性可用于判定或作为投影的目标。当用于指定投影的目标时,将返回该组项目。例如,以下语句将找出其中雇员的姓是名字“Smith”的所有EmployeeOfOrganization(组织的雇员)关系(而不论组织是什么)FindResultresult=EmployeeOfOrganization.FindAll(context,“Employee.PersonalNames[SurName=’Smith’]”);搜索表达式Cast运算符可用于过滤端点项目的类型。例如,为找出其中成员是具有姓“Smith”的Person项目的所有MemberOfFoler(文件夹成员)关系实例FindResultresult=MemberOfFolder.FindAll(context,“Member.Cast(Contact.Person).PersonalNames[Surname=’Smith’]”);(3)组合关系遍历前两种模式,即从项目遍历到关系以及从关系遍历到项目可被组合以实现任意复杂的遍历。例如,为找出具有姓为“Smith”的雇员的所有组织FindResultresult=Organization.FindAll(context,“EmployeeRelationships.”+“Employee.”+“PersonalNames[SurName=‘Smith’]”);以下示例将找出表示生活在“NewYork”区域的家庭的人的所有Person项目(计划项目这不再支持……它是一种替换)。FindResultresult=Person.FindAll(context,“Relationships.Cast(Contact.MemberOfHousehold).”+“Household.”+“Relationships.Cast(Contact.LocationOfHousehold).”+“MetropolitonRegion=‘NewYork’“);e)关系支持的示例使用以下是如何使用存储平台API中的关系支持来操纵关系的示例。对于以下示例,假定以下声明ItemContextic=…;ItemIdfid=…;//文件夹项目的IDFolderfolder=Folder.FindById(ic,fid);ItemIdsid=…;//源项目的IDItemsource=Item.FindById(ic,sid);ItemIdtid=…;//目标项目的IDItemtarget=Item.FindById(ic,tid);ItemSearchersearcher=null;(1)搜索关系可能搜索源或目标关系。可使用过滤器来选择指定类型且具有给定属性值的关系。也可使用过滤器来选择基于关系的相关项目类型或属性值。例如,可执行以下搜索其中给定项目是源的所有关系searcher=Relationship.GetSearcher(folder);foreach(searcher.FindAll()中的Relationshiprelationship)…;其中给定项目是具有匹配“A%”的名字的源的所有关系searcher=Relationship.GetSearcher(folder);searcher.Filters.Add(″Namelike′A%′″);foreach(searcher.FindAll()中的Relationshiprelationship)…;其中给定项目是源的所有FolderMember关系searcher=FolderMember.GetSearcher(folder);foreach(searcher.FindAll()中的FolderMemberfolderMember)…;其中给定项目是源且名如“A%”的所有FolderMember关系searcher=FolderMember.GetSearcher(folder);searcher.Filters.Add(″Namelike′A%′″);foreach(searcher.FindAll()中的FolderMemberfolderMember)…;其中目标项目是Person的所有FolderMember关系searcher=FolderMember.GetSearcher(folder);searcher.Filters.Add(″MemberItem.Cast(Person)″);foreach(searcher.FindAll()中的FolderMemberfolderMember)…;其中目标项目是姓为“Smith”的Person的所有FolderMember关系searcher=FolderMember.GetSearcher(folder);searcher.Filters.Add(″MemberItem.Cast(Person).PersonalNames.Surname=′Smith′″);foreach(searcher.FindAll()中的FolderMemberfolderMember)…;除以上示出的GerSearcherAPI之外,每一关系类支持静态FindAll、FineOne以及FindOnlyAPI。另外,关系类型可以在调用ItemContext.GetSearcher、ItemContext.FindAll、ItemContext.FindOne或ItemContext.FindOnly时指定。(2)从关系导航到源和目标项目一旦通过搜索检索了关系对象,可能“导航”到目标或源项目。基本关系类提供了返回Item对象的SourceItem(源项目)和TargetItem(目标项目)属性。所生成的关系类提供了等效强类型化和命名的属性(例如,FolderMember.FolderItem和FolderMember.MemberItem)。例如导航到名为“Foo”的关系的源和目标项目searcher=Relationship.GetSearcher();searcher.Filters.Add(″Name=′Foo′″);foreach(searcher.FindAll()中的Relationshiprelationship){Itemsource=relationship.SourceItem;Itemtarget=relationship.TargetItem;}导航到目标项目searcher=FolderMember.GetSearcher(tolder);searcher.Filters.Add(″Namelike′A%′″);foreach(searcher.FindAll()中的FolderMemberfolderMember){Itemmember=folderMember.TargetItem;…}导航到目标项目即使在目标项目不在其中找到关系的域中也可运作。在这一情况下,存储平台API打开到所需的目标域的连接。应用程序可在检索目标项目之前确定是否需要连接。检查未连接的域中的目标项目searcher=Relationship.GetSearcher(source);foreach(searcher.FindAll()中的Relationshiprelationship){if(relationship.IsTargetDomaiinConnected){Itemmember=relationship.TargetItem;…}}(3)从源项目导航到关系给定项目对象,可能导航到该项目为其源的关系,而无需执行显式的搜索。这可使用Item.Relationships集合属性或诸如Folder.MemberRelationships等强类型化的集合属性来完成。从关系中,可能导航到目标项目。这一导航即使在目标项目不在与源项目的ItemContext相关联的项目域中时也能运作,包括当目标项目不在与源项目相同的存储中的时候。例如从源项目导航到关系再到目标项目Console.WriteLine(″Item{0}isthesourceofthefollowingrelationships″,source.ItemId);foreach(source.Relationships中的Relationshiprelationship){Itemtarget=relationship.TargetItem;Console.WriteLine(″{0}==>{1}″,relationship.RelationshipId,target.ItemId);}从文件夹项目导航到文件夹成员关系再到目标项目console.WriteLine(″Item{0}isthesourceofthefollowingrelationships″,folder.ItemId);foreach(folder.MemberRelationships中的FolderMemberfolderMember){Itemtarget=folderMember.GetMemberItem();Console.WriteLine(″{0}==>{1}″,folderMember.RelationshipId,target.ItemId);项目可具有许多关系,因此应用程序在枚举关系集合时应谨慎使用。一般而言,应使用搜索来标识感兴趣的特定关系而非枚举整个集合。然而,对关系具有基于集合的编程模型以及足够有价值,且具有许多关系的项目少得足以证明开发者滥用的风险。应用程序可检查集合中的关系的数目,并在需要时使用不同的编程模型。例如检查关系集合的大小if(folder.MemberRelationships.Count>1000){Console.WriteLine(″Toomanyrelationships!″);}else{…}上述关系集合在它们实际上不用表示每一关系的对象来填充的意义上是“虚拟的”,除非应用程序试图枚举该集合。如果该集合被枚举,则结果反映了存储中有什么,加上应用程序添加但没有保存了什么,但不反映由应用程序移除但没有保存的任何关系。(4)创建关系(以及项目)新关系通过创建关系对象、将其添加到源项目中的关系集合、并更新项目上下文来创建。为创建新项目,必须创建持有或嵌入关系。例如向现有文件夹添加新项目Barbar=newBar();folder.Relationships.Add(newFolderMember(bar,″name″));ic.Update();//或者Barbar=newBar();folder.MemberRelationships.Add(newFolderMember(bar,″name″));ic.Update();//或者Barbar=newBar();folder.MemberRelationships.Add(bar,name);ic.Update();向现有文件夹添加现有项目folder.MemberRelationships.Add(target,″name″);ic.Update();向新文件夹添加现有项目FolderexistingFolder=ic.FindItemById(fid)asFolder;FoldernewFolder=newFolder();existingFolder.MemberRelationships.Add(newFolder,″aname″);newFolder.MemberRelationships.Add(target,″aname″);ic.Update();向新文件夹添加新项目FolderexistingFolder=ic.FindItemById(fid)asFolder;FoldernewFolder=newFolder();existingFolder.MemberRelationships.Add(newFolder,″aname″);Barbar=newBar();newFolder.MemberRelationships.Add(bar,″aname″);ic.Update();(5)删除关系(以及项目)删除持有关系//如果源项目和关系ID已知…RelationshipIdrid=…;Relationshipr=ic.FindRelationshipById(fid,rid);r.MarkForDelete;ic.Update();//否则…folder.MemberRelationships.Remove(target);ic.Update();8.“扩展”存储平台API如上所述,每一存储平台模式都导致一组类。这些类具有诸如Find*等标准方法,且还具有用于设置和获得字段值的属性。这些类和相关联的方法形成了存储平台API的基础。a)域行为除这些标准方法之外,每一模式具有一组用于该模式的域专用方法。将这些方法成为域行为。例如,联系人模式中某些域行为是·电子邮件地址是否有效?·给定文件夹,获得该文件夹的所有成员的集合。·给定项目ID,获得表示该项目的对象。·给定人,获得其在线状态。·助手函数创建新联系人或临时联系人。·等等。重要的是注意,尽管在“标准”行为(Find*等)和域行为之间做出了区别,但是它们对程序员仅仅表现为方法。这些方法之间的区别在于标准行为是由存储平台API设计时工具从模式文件自动生成的,而域行为是硬编码的。就其最本性而言,域行为应当是手工制作的。这导致一个实际问题C#的初始版本要求类的整个实现在单个文件内。由此,这迫使自动生成的类文件必须被编辑以添加域行为。这本身就是一个问题。在C#中为诸如此类的问题引入一种称为局部类的特征。最基本地,局部类允许类实现跨越多个文件。局部类与常规的类相同,不同之处在于其声明前有关键字partialpartialpublicclassPersonDerivedItemBase{//实现}现在,Person的域行为可以被放置在不同的文件中,如partialpublicclassPerson{publicEmailAddressPrimaryEmailAddress{get{/*实现*/}}}b)增值行为具有域行为的数据类形成了应用程序开发者在其上进行构建的基础。然而,数据类展现与该数据有关的每一可想到的行为是不可能也是不合需要的。存储平台允许开发者在由存储平台API提供的基础功能上进行构建。此处的基础模式是编写其方法采用存储平台数据类的一个或多个作为参数的类。例如,用于使用MicrosoftOutlook或使用MicrosoftWindowsMessenger来发送电子邮件的增值类可以如下MailMessagem=MailMessage.FindOne(…);OutlookEMailServices.SendMessage(m);Personp=Person.FindOne(…);WindowsMessagerServicesm=newWindowsMessagerServices(p);m.MessageReceived+=newMessageReceivedHandler(f);m.SendMessage(″Hello″);这些增值类可以向存储平台注册。注册数据与存储平台为每一安装的存储平台类型维护的模式元数据相关联。该元数据作为存储平台项目储存,且可被查询。增值类的注册是一种强大的特征;例如,它允许以下情形Shell资源管理器中的Person对象上右键点击,且可从对Person注册的增值类中导出允许的该组动作。c)作为服务提供者的增值行为在本实施例中,存储平台API提供了一种机制,其中增值类可被注册为给定类型的“服务”。这使得应用程序能够设置和获得给定类型的服务提供者(=增值类)。希望利用这一机制的增值类应当实现一种公知的接口;例如interfaceIChatServices{voidSendMessage(stringmsg);eventMessageReceivedHandlerMessageReceived;}classWindowsMessengerServicesIChatServices{…}classYahooMessengerServicesIChatServices{…}所有存储平台API数据类实现ICachedServiceProvider(高速缓存的服务提供者)接口。该接口扩展了System.IServiceProvider接口,如下interfaceICachedServiceProviderSystem.IServiceProvider{voidSetService(System.Typetype,Objectprovider);voidRemoteService(System.Typetype);}使用该接口,应用程序可设置服务提供者示例以及请求特定类型的服务提供者。为支持该接口,存储平台数据类维护以类型作为键的服务提供者的散列表。当请求服务提供者时,实现首先在散列表中查看是否设置了指定类型的服务提供者。如果否,则使用注册的服务提供者基础结构来标识指定类型的服务提供者。然后创建该提供者的实例,将其添加到散列表,并返回。注意,也可能由数据类上的共享方法请求服务提供者,并将操作转发到该提供者。例如,这可用于提供使用由用户指定的电子邮件系统的邮件消息类上的Send方法。9.设计时架构本节描述了依照本发明的本实施例,存储平台模式如何转换成客户机上的存储平台API以及服务器上的UDT类。图24的图示出了所涉及的组件。参考图24,模式中的类型包含在XML文件(框1)中。该文件也包含与模式相关联的字段级和项目级约束。存储平台类生成器(xfs2cs.exe—框2)采用该文件,并生成存储UDT的局部类(框5)以及客户机类的局部类(框3)。对于每一模式域,存在其它方法—称为域行为。存在在存储(框7)、客户机(框6)和两者中(框4)有意义的域行为。框4、6和7中的代码是手写的(不是自动生成的)。框3、4和6中的局部类共同形成了存储平台API域类的完整类实现。框3、4和6被编译(框8)以形成存储平台API类—框11(实际上,存储平台API是编译从所有初始模式域所得的框3、4和6的结果)。除域类之外,也存在实现增值行为的其它类。这些类利用一个或多个模式域中的一个或多个类。这是由框10表示的。框4、5和7中的局部类共同形成了服务器UDT类的完整类实现。框4、5和7被编译(框9)以形成服务器方的UDT程序集—框12(实际上,服务器方的UDT程序级是编译器加编译从所有初始模式域所得的框4、5和7的结果)。DDL命令生成器模块(框13)采用该UDT程序集(框12)以及模式文件(框1),并将它们安装在数据存储上。该过程涉及表的生成以及每一模式中的类型的查看等等。10.查询形式当被精简到基础时,在使用存储平台API时应用程序的模式为打开ItemContext;以过滤器准则使用Find来检索期望的对象;在对象上操作;以及将改变发送回存储。本节涉及对于什么进入过滤器串的句法。当查找存储平台数据对象时提供的过滤器串描述了对象的属性必须满足以被返回的约束。由存储平台API使用的句法支持类型强制转换和关系遍历。a)过滤器基础过滤器串要么为空,指示要返回指定类型的所有对象;要么是每一返回的对象必须满足的布尔表达式。表达式引用对象的属性。存储平台API运行库知道这些属性名如何映射到存储平台类型字段名,并最终映射到由存储平台存储维护的SQL视图。考虑以下示例//找出所有人FindResultres1=Person.FindAll(ctx)//找出其Gender(性别)属性值等于“Male”(男)的所有人FindResultres2=Person.FindAll(ctx,″Gender=′Male′″)//找出其Gender属性值等于“Male”且在上一世纪出生的人FindResultres3=Person.FindAll(ctx,″Gender=′Male′AndBirthdate<′1/1/2001″″)嵌套对象的属性也可在过滤器中使用。例如//找出在上24小时中修改的所有人FindResultres1=Person.FindAll(ctx,String.Format(″Item.Modified>′{0}′″,DateTime.NowSubstract(nesTimeSpan(24,0,0))));对于集合,可能使用方括号中的条件来过滤成员。例如//找出名为“John”且姓为“Smith”的所有人FindResultres1=Person.FindAll(ctx,″PersonalNames[GivenName=′John′AndSurname=′Smith′]″)//找出实时地址来自提供者“x”且在线状态类别为“y”的所有人FindResultres2=Person.FindAll(ctx,″PersonalRealtimeAddress[ProviderURI=′x′].BasicPresence″+″OnlineStatus.Category=′y′″)以下示例列出了自从12/31/1999以来出生的所有人ItemContextctx=ItemContext.Open(″WorkContacts″);FindResultresults=Person.FindAll(ctx,″Birthdate>′12/31/1999′″);foreach(results中的Personperson)Console.WriteLine(person.DisplayName);ctx.Close();第1行创建了新的ItemContext对象来访问本地计算机上存储平台共享上的“WorkContacts(工作联系人)”。第3行和第4行获得其中Birthdate(生日)属性满足晚于12/31/1999的日期的Person对象的集合,如由表达式“Birthdate>′12/31/1999′”所指定的。该FindAll操作的执行在图23中示出。b)类型强制转换情况通常是储存在属性中的值的类型是从属性声明的类型导出的。例如,Person中的PersonalEAddress(个人电子地址)属性包含从诸如EMailAddress(电子邮件地址)和TelephoneNumber(电话号码)等EAdress(电子地址)中导出的类型的集合。为基于电话区号过滤,必须从EAddress类型强制转换到TelephoneNumber类型//找出电话号码425区号中的所有人FindResultres1=Person.FindAll(ctx,″PersonalEAddresses.″+″Cast(System.Storage.Contact.TelephoneNumber)).″+″AreaCode=’425’″);//或者,可如下传递类型名FindResultres1=Person.FindAll(ctx,String.Format(″PersonalEAddresses.Cast({0})).AreaCode=’425’″,typeof(TelephoneNumber).FullName))c)过滤器句法以下是依照一个实施例由存储平台API支持的过滤器句法的描述。过滤器::=空过滤器|条件空过滤器::=条件::=简单条件|复合条件|加括号的条件简单条件::=存在检查|比较存在检查::=属性引用比较::=属性引用比较运算符常量复合条件::=简单条件布尔运算符条件加括号的条件::=′(′条件′)′比较运算符::=′!=′|′==′|′=′|′<′|′>′|′>=′|′<=′布尔运算符::=′And′|′&&′|′Or′|′‖′常量::=串常量|数字常量串常量::=(任何Unicode字符)*注意嵌入的′字符通过复制来转义数字常量::=0-9*属性引用::=简单属性名|复合属性名简单属性名::=(除′.′和空格之外的所有Unicode字符)*过滤器?过滤器::=′(′条件′)′复合属性名::=(类型强制转换|关系遍历|简单属性名)′.′属性引用类型强制转换::=′Cast(′类型名′)′关系遍历::=遍历到源遍历到目标遍历到源::=′Source(′完整关系名′)′遍历到目标::=′Target(′完整关系名′)′类型名::=完全合格的CLR类型名完整关系名::=模式名′.′关系名模式名::=存储平台名关系名::=存储平台名存储平台名::=如[模式定义]中所定义的11.遥控a)API中的本地/远程透明性存储平台中的数据访问的目标为本地存储平台实例。如果查询(或其部分)涉及远程数据,则本地实例用作路由器。由此,API层提供了本地/远程透明性在本地和远程数据访问之间没有结构上的API差别。它纯粹是由所请求的范围来决定的。存储平台数据存储也实现了分布式查询;由此,可能连接到本地存储平台实例,并执行包括来自不同卷的项目的查询,其中某一些项目在本地存储上,而其它项目在远程存储上。存储对结果执行并操作,并将其呈现给应用程序。从存储平台API的观点(因此是应用程序开发者的观点)来看,任何远程访问完全是无缝和透明的。存储平台API允许应用程序使用IsRemote属性确定给定的ItemContext对象(如由ItemContext.Open方法返回的)是表示本地还是远程连接,该属性是ItemContext对象上的属性。尤其是,应用程序可能希望提供视频反馈来帮助为性能、可靠性等设置用户期望。b)遥控的存储平台实现存储平台数据存储使用特殊的OLEDB提供者来彼此交谈,该提供者在HTTP上运行(默认的OLEDG提供者使用TDS)。在一个实施例中,分布式查询通过关系型数据库引擎的默认OPENROWSET功能。提供一种特殊的用户定义函数(UDF)DoRemoteQuery(server,queryText),以完成实际的遥控。c)访问非存储平台存储在本发明的存储平台的一个实施例中,不存在允许任何存储参与存储平台数据访问的非一般提供者体系结构。然而,为MicrosoftExchange和MicrosoftActiveDirectory(AD)的特定情况提供了有限提供者体系结构。这意味着开发者可如同在存储平台中那样使用存储平台API并访问AD和Exchange中的数据,但是他们能够访问的数据限于存储平台模式化的类型。由此,在AD中支持地址簿(=存储平台Person类型的集合),且对Exchange支持邮件、日历和联系人。d)与DFS的关系存储平台属性升级器不升级过去的固定点。即使名字空间足够丰富以通过固定点来访问,查询仍不能通过它们。存储平台卷可以作为DFS树中的叶节点出现。e)与GXA/Indigo的关系开发者可使用存储平台API以在数据存储的上方展示“GXA头”。概念上,创建任何其它web服务没有任何区别。存储平台API不使用GXA与存储平台数据存储交谈。如上所述,API使用TDS与本地存储交谈;任何遥控是由本地存储使用同步服务来处理的。12.约束存储平台数据模型允许类型上的值约束。这些约束在存储上自动评估,且该过程对于用户是透明的。注意,在服务器处检查约束。注意到这一点之后,有时候期望给予开发者验证输入数据满足约束的灵活性而不会导致对服务器的往返额外开销。这在其中最终用户输入用于填充对象的数据的交互式应用程序中尤其有用。存储平台API提供该工具。可以回想在XML文件中指定了存储平台模式,它由存储平台用于生成表示该模式的适当的数据库对象。它也由存储平台API的设计时架构用于自动生成类。以下是用于生成Contacts模式的XML文件的部分清单<SchemaName=″Contacts″MajorVersion=″1″MinorVersion=″8″><ReferencedSchemaName=″Base″MajorVersion=″1″/><TypeName=″Person″MajorVersion=″1″MinorVersion=″0″ExtendsType=″Principal″ExtendsVersion=″1″><FieldName=″Birthdate″Type=″thestorageplatformTypes.datetime″Nullable=″true″MultiValued=″false″/><FieldName=″Gender″Type=″thestorageplatformTypes.nvarchar(16)″Nullable=″true″MultiValued=″false″/><FieldName=″PersonalNames″Type=″FullName″TypeMajorVersion=″1″Nullable=″true″MultiValued=″true″/><FieldName=″PersonalEAddresses″Type=″EAddress″TypeMajorVersion=″1″Nullable=″true″MultiValued=″true″/><FieldName=″PersonalPostalAddresses″Type=″PostalAddress″TypeMajorVersion=″1″Nullable=″true″MultiValued=″true″/><Check>expression</Check></Type>……</Schema>以上XML中的Check标签指定了Person类型上的约束。可以有一个以上Check标签。以上约束一般是在存储中检查的。为指定约束也可由应用程序显式地检查,以上XML被修改为<SchemaName=″Contacts″MajorVersion=″1″MinorVersion=″8″><ReferencedSchemaName=″Base″MajorVersion=″1″/><TypeName=″Person″…><FieldName=″Birthdate″Type=″thestorageplatformTypes.datetime″Nullable=″true″MultiValued=″false″/>…<CheckInApplication=″true″>expression</Check></Type>……</Schema>注意,<Check>元素上的新的“InApplication”属性被设为真。这导致存储平台API通过Person类上称为Validate()的实例方法在API中将约束置于表面。应用程序可在对象上调用该方法,以确保数据是有效的,并防止对服务器的可能的无用往返。这返回指示确认的结果的布尔值。注意,值约束仍在服务器处应用,而不论客户机是否调用了<object>.Validate()方法。以下是如何使用Validate的一个示例ItemContextctx=ItemContext.Open();//在用户的MyContacts文件夹中创建联系人。Folderf=UserDataFolder.FindMyPersonalContactsFolder(ctx);Personp=newPerson(f);//设置人的生日p.Birthdate=newDateTime(1959,6,9);//添加被归类为人名的名字FullNamename=newFullName(FullName.Category.PrimaryName);name.GivenName=″Joe″;name.Surname=″Smith″;p.PersonalNames.Add(name);//确认Person对象if(p.Validate()==false){//数据不表示有效的人}//保存改变p.Update();ctx.Close();存在到存储平台存储的多条访问路径—存储平台API、ADO.NET、ODBC、OLEDB和ADO。这引发了权威约束检查的问题—即,如何确保从例如ODBC写出的数据与从存储平台API写出的数据通过相同的数据完整性约束。由于所有的约束是在存储处检查的,因此约束现在是权威的。不论用于到达存储的API路径如何,对存储的所有写都通过存储处的约束检查来过滤。13.共享存储平台中的共享是以下形式\\<DNS名>\<上下文服务>其中<DNS名>是机器的DNS名,<上下文服务>是该机器上的卷中的包含文件夹、虚拟文件夹或项目。例如,假定机器“Johns_Desktop”具有名为Johns_Information的卷,且在该卷中存在名为Contacts_Categories的文件夹;该文件夹包含名为Work的文件夹,后者具有John的工作联系人\\Johns_Desktop\Johns_Information$\Contacts_Categories\Work这可以被共享为“WorkContacts”。采用该共享的定义,\\Johns_Desktop\WorkContacts\JaneSmith是有效的存储平台名,且标识了Person项目JaneSmith。a)表示共享共享项目类型具有以下属性共享名以及共享目标(这可以是非持有链接)。例如,上述共享的名称是WorkContacts,且目标是卷Johns_Information上的Contacts_Categories\Work。以下是用于Share类型的模式片段<Schemaxmlns=″http://schemas.microsoft.com/winfs/2002/11/18/schema″Name=″Share″MajorVersion=″1″MinorVersion=″0″><ReferencedSchemaName=″Base″MajorVersion=″1″/><ReferencedSchemaName=″thestorageplatformTypes″MajorVersion=″1″/><TypeName=″Share″MajorVersion=″1″MinorVersion=″0″ExtendsType=″Base.Item″ExtendsVersion=″1″><FieldName=″Name″Type=″thestorageplatformTypes.nvarchar(512)″TypeMajorVersion=″1″/><FieldName=″Target″Type=″Base.RelationshipData″TypeMajorVersion=″1″/></Type></Schema>b)管理共享由于共享是一个项目,因此共享可如同其它项目那样管理。共享可被创建、删除和修改。共享也以与其它存储平台项目一样的方式来保护。c)访问共享应用程序通过在ItemContext.Open()方法调用中将共享名(例如,\\Johns_Desktop\WorkContacts)传递到存储平台API来访问远程存储平台共享。ItemContext.Open返回ItemContext对象实例。存储平台API然后与本地存储平台服务交谈(可以回想访问远程存储平台是通过本地存储平台完成的)。本地存储平台服务进而与具有给定共享名(例如,WorkContacts)的远程存储平台服务(例如,在机器Johns_Desktop)交谈。远程存储平台服务然后将WorkContacts转换成Contacts_Categories\Work并打开它。在那之后,与其它范围一样执行查询和其它操作。d)可发现性在一个实施例中,应用程序可以用以下方式发现给定的<DNS名>上可用的共享。依照第一种方式,存储平台API接受DNS名(例如,Johns_Desktop),作为ItemContext.Open()方法中的范围参数。存储平台API然后用该DNS名作为连接串的一部分连接到存储平台存储。采用该连接,应用程序唯一能做的事情是调用ItemContext.FindAll(typeof(Share))。存储平台服务然后对所有附加的卷上的所有共享执行并操作,并返回共享集合。依照第二种方式,在本地机器上,管理员可通过FindAll(typeof(Share))发现特定卷上的共享,或通过FindAll(typeof(Share),″Target(ShareDestination).Id=folderId″)来发现特定的文件夹。14.Find的语义Find*方法(无论它们是在ItemContext对象还是在个别的项目上调用)一般应用于给定上下文中的项目(包括嵌入的项目)。嵌套元素没有Find—它们不能独立于其包含项目来搜索。这与存储平台数据模型所期望的语义相一致,其中嵌套元素从包含项目导出其“身份”。为使这一概念更清楚,以下是有效和无效查找操作的示例a)示出系统中具有区号206的所有电话号码?无效,因为该查找是在电话号码(元素)上完成的,而没有引用项目。b)示出所有Person内具有区号206的所有电话号码?无效,即使引用了Person(=项目),搜索准则也不涉及该项目。c)示出Murali(=单个人)的具有区号206的所有电话号码?有效,因为存在项目(名为“Murali”的Person)上的搜索准则。该规则的例外是对于直接或间接从Base.Relationship类型导出的嵌套元素。这些类型可通过关系类个别地查询。这一查询可被支持,因为存储平台实现采用了“主链表”来储存Relationship元素而非将它们嵌入在项目UDT中。15.存储平台ContactsAPI本节给出了存储平台ContactsAPI的综述。ContactsAPI背后的模式在图21A和21B中示出。a)System.Storage.Contact的综述存储平台API包括用于处理联系人模式中的项目和元素的名字空间。该名字空间被称为System.Stroage.Contact。该模式具有例如以下类·项目UserDataFolder、User、Person、ADService、Service、Group、Organization、Principal、Location·元素Profile、PostalAddress、EmailAddress、TelephoneNumber、RealTimeAddress、Eaddress、FullName、BasicPresence、GroupMembership、RoleOccupancyb)域行为以下是联系人模式的域行为的列表。当从足够高的级别来查看时,域行为落入良好组织的类别中·静态助手,例如创建新个人联系人的Person.CreatePersonalContact();·实例助手,例如将用户(User类的实例)登录到被标记为自动登录的所有概况的user.AutoLoginToAllProfiles();·类别GUID,例如Category.Home、Category.Work等;·导出属性,例如emailAddress.Address()—返回组合给定emailAddress(EmailAddress类的实例)的用户名和域字段的串;以及·导出集合,例如person.PersonalEmailAddress—给定Person类的实例,获得其个人电子邮件地址。下表对Contacts中具有域行为的每一类给出了这些方法和它们所属的类别的列表。16.存储平台FileAPI本节依照本发明的一个实施例给出了存储平台FileAPI的综述。a)介绍(1)在存储平台中反映NTFS卷存储平台提供了在现有NTFS卷中的内容上进行索引的方法。这是通过从NTFS中的每一文件流或目录中提取(“升级”)属性,并将这些属性作为项目储存在存储平台中来实现的。存储平台的文件模式定义了两种项目类型—File(文件)和Directory(目录),来储存升级的文件系统实体。Directory类型是Folder类型的子类型;它是包含其它Directory项目或File项目的包含文件夹。Directory项目可包含Directory和File项目;它不能包含任何其它类型的项目。至于所考虑的存储平台,Directory和File项目从任何数据访问API都是只读的。文件系统升级管理器(FSPM)服务异步地将改变的属性升级到存储平台中。File和Directory项目的属性可由Win32API来改变。存储平台API可用于读取这些项目的任何属性,包括与File项目相关联的流。(2)在存储平台名字空间中创建文件和目录当NTFS卷被升级到存储平台卷时,其中的所有文件和目录都在该卷的特定部分中。该区域从存储平台的观点来看是只读的;FSPM可创建新目录和文件,和/或改变现有项目的属性。该卷的名字空间的剩余部分可包含存储平台项目类型的普通全范围—Principal(主体)、Organization(组织)、Document(文档)、Folder(文件夹)等。存储平台也允许在存储平台名字空间的任何部分中创建文件和目录。这些“本机”文件和目录在NTFS文件系统中没有相应物;它们完全储存在存储平台中。此外,对属性的改变是立即可见的。然而,编程模型保持相同;就考虑到存储平台数据访问API而言,它们仍是只读的。“本机”文件和目录必须使用Win32API来更新。这简化了开发者的思维模型,该思维模型为1.任何存储平台项目类型可以在名字空间中的任何地方处创建(当然,除非被许可所阻止);2.任何存储平台项目类型可以使用存储平台API来读取;3.所有存储平台项目类型可使用具有File和Directory的例外的存储平台API来写入4.为写到File和Directory项目而不管它们在名字空间中的何处,使用Win32API;以及5.在“升级的”名字空间中对File/Directory项目的改变可能不直接出现在存储平台中;在“非升级”名字空间中,改变直接在存储平台中反映。b)文件模式图25示出了FileAPI所基于的模式。c)System.Storage.Files的综述存储平台API包括用于处理文件对象的名字空间。该名字空间称为System.Storage.Files。System.Storage.Files中的类的数据成员直接反映了储存在存储平台存储中的信息;该信息从文件系统对象“升级”,或可以使用Win32API本机创建。System.Storage.Files名字空间具有两个类FileItem(文件项目)和DirectoryItem(目录项目)。这些类的成员及其方法可通过查看图25中的模式图来容易地猜想。FileItem和DirectoryItem从存储平台API是只读的。为修改它们,必须使用Win32API或System.IO中的类。d)代码示例在本节中,提供了三个代码示例,示出了System.Storage.Files中的类的使用。(1)打开文件并向其写入本示例示出了如何完成“传统”文件操纵。ItemContextctx=ItemContext.Open();FileItemf=FileItem.FindByPath(ctx,@″\MyDocuments\billg.ppt″);//处理文件属性的示例—确保文件不是只读的if(!f.IsReadOnly){FileStreamfs=f.OpenWrite();//读、写、关闭文件流fs}ctx.Close();第3行使用了FindByPath(按照路径查找)方法来打开文件。第7行示出了对升级的属性IsReadOnly的使用,来检查文件是否可写。如果是,则在第9行使用FileItem对象上的OpenWrite()方法来获得文件流。(2)使用查询由于存储平台存储持有从文件系统升级的属性,因此可能容易地在文件上完成丰富的查询。在本示例中,列出了在最后三天修改的所有文件//列出在最后三天中修改的所有文件FindResultresult=FileItem.FindAll(ctx,″Modified>=′{0}′″,DateTime.Now.AddDays(-3));foreach(result中的FileItemfile){…}以下是使用查询的另一示例—该示例找出某一类型(=extension)的所有可写文件//找出特定目录中所有可写.cs文件//等效于dirc:\win\src\api\*.cs/a-r-dDirectoryItemdir=DirectoryItem.FindByPath(ctx,@″c:\win\src\api″);FindResult=dir.GetFiles(″Extension=′cs′andIsReadOnly=false″);foreach(result中的Filefile){…}e)域行为在一个实施例中,除标准属性和方法之外,文件类也具有域行为(手工编码的属性和方法)。这些行为一般基于对应的System.IO类中的方法。J.总结如上所述,本发明针对一种用于组织、搜索和共享数据的存储平台。本发明的存储平台在现有文件系统和数据库系统之外扩展并拓宽了数据存储的概念,并被设计成储存所有类型的数据,包括结构化的、非结构化的或半结构化的数据,诸如关系型(表式)数据、XML以及称为项目的新形式的数据。通过其公共存储基础和模式化的数据,本发明的存储平台对消费者、知识工作者和企业允许更有效的应用程序开发。它提供了一种丰富且可扩展的应用程序编程接口,该接口不仅使得其数据模型中的固有能力可用,还包含并扩展了现有文件系统和数据库访问方法。可以理解,可以对上述实施例做出改变而不脱离其宽泛的发明性概念。因此,本发明不限于所揭示的具体实施例,而是旨在覆盖落入由所附权利要求书定义的本发明的精神和范围之内的所有修改。如从上文中可以清楚的,本发明的各种系统、方法和方面的全部或部分可以用程序代码(即,指令)的形式来实施。该程序代码可被储存在计算机可读介质上,诸如磁、电、光存储介质,包括但不限于,软盘、CD-ROM、CD-RW、DVD-ROM、DVD-RAM、磁带、闪存、硬盘驱动器、或任何其它机器可读存储介质,其中,当程序代码被加载到诸如计算机或服务器等机器并由其执行时,该机器成为用于实现本发明的装置。本发明也可用通过某一传输介质,诸如通过电线或电缆、通过光纤、通过包括因特网或内联网的网络、或通过任何其它形式的传输来传输的程序代码的形式来实施,其中,当程序代码由诸如计算机等机器接受并加载到其中由其执行时,该机器成为用于实现本发明的装置。当在通用处理器上实现时,程序代码与处理器相结合以提供类似于特定逻辑电路操作的独特装置。附录AnamespaceSystem.Storage{abstractclassItemContextIDisposable,IServiceProvider{ItemContext创建和管理成员//应用程序无法直接创建ItemContext对象,也无法从ItemContext中导出类。internalitemContext();//创建可用于搜索指定路径,或者如果未指定路径,//则创建可用于搜索本地计算机上的默认存储的ItemContext。publicstaticItemContextOpen();publicstaticItemContextOpen(stringpath);publicstaticItemContextOpen(paramsstring[]paths);//返回创建ItemContext时指定的路径。publicstring[]GetOpenPaths();//创建该ItemContext的副本。该副本将具有独立的事务、高速缓存和更新状态。高速缓存//初始为空。期望使用克隆的ItemContext将比使用同一项目域打开新的ItemContext更有效。publicItemContextClone();//关闭ItemContext。在关闭之后使用ItemContext的任何尝试将导致ObjectDisposedException。publicvoidClose();voidIDisposable.Dispose();//如果当打开ItemContext指定的任何域解析到远程计算机,则为真。publicboolIsRemote{get;}//返回可提供所请求的服务类型的对象。如果不能提供所请求的服务,则返回空。//对IServiceProvider模式的使用允许非正常使用且可能导致开发者混淆的API被排除在//ItemContext类之外。ItemContext可提供以下种类的服务ItemSerialization、IStoreObjectCachepublicobjectGerService(TypeserviceType);更新相关成员//保存由所有修改的对象以及传递到MarkForCreate或MarkForDelete的所有对象表示的改变。//如果检测到更新冲突,则可抛出UpdateCollisionException。publicvoidUpdate();//保存由所指定的对象表示的改变。对象必须已被修改或已被传递到MarkForCreate或//MarkForDelete,否则抛出ArgumentException。如果检测到更新冲突,//可抛出UpdateCollisionException。publicvoidUpdate(objectobjectToUpdate);publicvoidUpdate(IEnumerableobjectsToUpdate);//从存储中刷新所指定对象的内容。如果对象已被修改,则覆盖改变,且对象不再被认为是已//改变的。如果指定了除项目、项目扩展或关系对象之外的任何内容,则抛出ArgumentException。publicvoidRefresh(objectobjectToRefresh);publicvoidRefresh(IEnumerableobjectsToRefresh);//当更新检测到检索修改的对象和试图保存它之间在存储中改变了数据时引发。如果没有注册任//何事件处理程序,则更新抛出异常。如果注册了事件处理程序,则它可抛出异常来中止更新,//包装修改的对象以覆盖存储中的数据,或合并在存储中和对象中做出的改变。publiceventChangeCollisionEventHandlerUpdateCollision;//在更新处理的各点处引发,以提供更新进展信息。publiceventUpdateProgressEventhandlerUpdateProgress;//Update的异步版本publicIAsyncResultBeginUpdate(IAsyncCallbackcallback,objectstate);publicIAsyncResultBeginUpdate(objectobjectToUpdate,IAsyncCallbackcallback,objectstate);publicIAsyncResultBeginUpdate(IEnumerableobjectsToUpdate,IAsyncCallbackcallback,objectstate);publicvoidEndUpdate(IAsyncResultresult);//Refresh的异步版本publicIAsyncResultBeginRefresh(objectobjectToRefresh,IAsyncCallbackcallback,objectstate);publicIAsyncResultBeginRefresh(IEnumerableobjectsToRefresh,IAsyncCallbackcallback,objectstate);publicvoidEndRefresh(IAsyncResultresult);事务相关成员//以指定的隔离级别启动事务。默认的隔离级别是ReadCommited。在所有情况下,//启动分布式事务,因为它可能必须包含改变流类型化项目属性。publicTransactionBeginTransaction();publicTransactionBeginTransaction(System.Data.IsolationLevelisolationLevel);搜索相关成员//创建在该项目上下文中搜索指定类型对象的ItemSearcher。如果指定了除项目、关系或//项目扩展之外的类型,则抛出ArgumentException。publicItemSearcherGetSearcher(Typetype);//给定其ID找出项目。publicItemFindItemById(ItemIdItemId);//给定其路径找出项目。路径可以是绝对或相对的。如果是相对的,则如果当打开ItemContext//时指定了多个项目域,则抛出NotSupportedException。如果不存在这样的项目,则返回空。//创建到域的\\machine\share部分的连接以检索项目。该项目将与该域相关联。publicItemFinditemByPath(stringpath);//给定其路径找出项目。路径相对于指定的项目域。创建到指定域的连接以检索项目。该项目将//与该域相关联。如果不存在这样的项目,则返回空。publicItemFindItemByPath(stringdomain,stringpath);//给定其路径找出一组项目。该路径相对于当打开ItemContext时指定的项目域。如果不存在//这样的项目,则返回空结果。publicFindResultFindAllItemsByPath(stringpath);//给定其ID找出关系。publicRelationshipFindRelationshipById(ItemIditemID,RelationshipIdrelationshipId);//给定其ID找出项目扩展。publicItemExtensionFindItemExtensionById(ItemIditemId,ItemExtensionIditemExtensionId);//找出可任意地满足给定过滤器的指定类型的所有项目、关系或项目扩展。如果指定了//这些类型之一以外的类型,则抛出ArgumentException。publicFindResultFindAll(Tyoetype);publicFindResultFindAll(Typetype,stringfilter);//找出满足给定过滤器的指定类型的任何项目、关系或项目扩展。如果指定了这些类型之一//以外的类型,则抛出ArgumentException。如果没有找到这样的对象,则返回空。publicobjectFindOne(Typetype,stringfilter);//找出满足给定过滤器的指定类型的项目、关系或项目扩展。如果指定了这些类型之一以外的//类型,则抛出ArgumentException。如果没有找到这样的对象,则抛出//ObjectNotFoundException。如果找到一个以上对象,则抛出MultipleObjectsFoundException。publicobjectFindOnly(Typetype,stringfilter);//如果存在满足给定过滤器的指定类型的项目、关系或项目扩展,则返回真。如果指定了这些//类型之一以外的类型,则抛出ArgumentException。publicboolExists(Typetype,stringfilter);//指定由涉及对象的搜索返回的对象如何标识由ItemContext维护的映射。publicSearchCollisionModeSearchCollisionMode{get;set;}//当为ResultMapping指定了PreserveModifiedObject时引发。该事件允许应用程序选择性地用//以该搜索检索到俄数据来更新修改的对象。publiceventChangeCollisionEventHandlerSearchCollision;//将来自另一ItemContext的对象结合到该项目上下文中。如果表示同一项目、关系或项目扩展的//对象并未在该ItemContext的身份映射中存在,则创建该对象的克隆并将其添加到该映射。如果//对象的确存在,则用指定对象的状态和内容以与SearchCollisionMode一致的方式更新该对象。publicItemIncorporateItem(Itemitem);publicRelationshipIncorporateRelationship(Relationshiprelationship);publicItemExtensionIncorporateItemExtension(ItemExtensionitemExtension);}//用于ItemContext.UpdateCollision和ItemSearcher.SearchCollision事件的处理程序。publicdelegatevoidChangeCollisionEventHandler(objectsource,ChangeCollisionEventArgsargs);//用于ChangeCollisionEventHandler委托的自变量publicclassChangeCollisionEventArgsEventArgs{//修改的项目、项目扩展或关系对象。publicobjectModifiedObject{get;}//来自存储的属性publicIDictionaryStoredProperties{get;}}//用于ItemContext.UpdateProgress的处理程序publicdelegatevoidUpdateProgressEventHandler(ItemContextitemContext,UpdateProgressEventArgsargs);//用于UpdateProgressEventHandler委托的自变量publicclassChangeCollisionEventArgsEventArgs{//当前更新操作publicUpdateOperationCurrentOperation{get;}//当前更新的对象publicobjectCurrentObject{get;}}//指定由涉及对象的搜索返回的对象如何标识由ItemContext维护的映射。publicenumSearchCollisionMode{//指示应当创建和返回新对象。忽略身份映射中表示同一项目、项目扩展或关系的对象。如果//指定了该选项,则不引发SearchCollision事件。DoNotMapSearchResults,//指示应返回来自身份映射的对象。如果应用程序修改了对象的内容,则保存修改的对象的内容。//如果未修改对象,则用由搜索返回的数据更新其内容。应用程序可提供用于SearchCollision//事件的处理程序,并在需要时选择性地更新对象。PreserveModifiedObjects,//指示应返回来自身份映射的对象。使用由搜索返回的数据更新对象的内容,即使对象已被应用//程序修改。如果指定了该选项,则不引发SearchCollision事件。OverwriteModifiedObjects}//当前更新操作publicenumUpdateOperation{//当首次调用Update时提供。CurrentObject将为空。OverallUpdateStarting,//仅在成功更新后的Update返回之前提供。CurrentObject将为空。OverallUpdateCompletedSuccessfully,//仅在Update抛出异常之前提供。CurrentObject将是异常对象。OverallUpdateCompletedUnsuccessfully,//当启动对象的更新时提供。CurrentObject将引用用于更新的对象。ObjectUpdateStaring,//当需要新连接时提供。CurrentObject将是包含标识传递给ItemContext.Open或从关系的//Location字段检索的项目域的路径的串。OpeningConnection}}附录BnamespaceSystem.Storage{//在项目上下文中执行跨特定类型的搜索。publicclassItemSearcher{构造函数publicItemSearcher();publicItemSearcher(TypetargetType,ItemContextcontext);publicItemSearcher(TypetargetType,ItemContextcontext,paramsSearchExpression[]filters);属性//用于标识匹配对象的过滤器。publicSearchExpressionCollectionFilters{get;}//指定将被搜索的域的ItemContext。publicItemContextItemContext{get;set;}//搜索参数集合。publicParameterCollectionParameters{get;}//搜索器将用于操作的类型。对于简单的搜索,这是将返回的对象的类型。publicTypeTargetType{get;set;}搜索方法//找出满足由Filters指定的条件的TargetType的对象。如果不存在这样的对象,则返回空的//FindResult。publicFindResultFindAll();publicFindResultFindAll(FindOptionsfindOptions);publicFindResultFindAll(paramsSortOption[]sortOptions);//找出满足由Filters指定的条件的TargetType的任何一个对象。如果不存在这样的对象则返回空。publicobjectFindOne();publicobjectFindOne(FindOptionsfindOptions);publicobjectFindOne(paramsSortOption[]sortOptions);//找出满足由Filters指定的条件的TargetType。如果未找到这样的对象则抛出//ObjectNotFoundException。如果找到一个以上对象,则抛出MultipleObjectsFoundException。publicobjectFindOnly();publicobjectFindOnly(FindOptionsfindOptions);//确定满足由Filters指定的条件的TargetType的对象是否存在。publicboolExists();//创建可用于更有效地重复执行同一搜索的对象。publicPreparedFindPrepareFind();publicPreparedFindPrepareFind(FindOptionsfindOptions);publicPreparedFindPrepareFind(paramsSortOption[]sortOptions);//检索将由FindAll()返回的记录的数目。publicintGetCount();//各种方法的异步版本publicIAsyncResultBeginFindAll(AsyncCallbackcallback,objectstate);publicIAsyncResultBeginFindAll(FindOptionsfindOptions,AsyncCallbackcallback,objectstate);publicIAsyncResultBeginFindAll(SortOption[]sortOptions,AsyncCallbackcallback,objectstate);publicFindResultEndFindAll(IAsyncResultar);publicIAsyncResultBeginFindOne(AsyncCallbackcallback,objectstate);publicIAsyncResultBeginFindOne(FindOptionsfindOptions,AsyncCallbackcallback,objectstate);publicIAsyncResultBeginFindOne(SortOption[]sortOptions,AsyncCallbackcallback,objectstate);publicobjectEndFindOne(IAsyncResultasyncResult);publicIAsyncResultBeginFindOnly(AsyncCallbackcallback,objectstate);publicIAsyncResultBeginFindOnly(FindOptionsfindOptions,AsyncCallbackcallback,objectstate);publicIAsyncResultBeginFindOnly(SortOption[]sortOptions,AsyncCallbackcallback,objectstate);publicobjectEndFindOnly(IAsyncResultasyncResult);publicIAsyncResultBeginGetCount(AsyncCallbackcallback,objectstate);publicintEndGetCount(IAsyncResultasyncResult);publicIAsyncResultBeginExists(AsyncCallbackcallback,objectstate);publicboolEndExists(IAsyncResultasyncResult);}//当执行搜索时使用的选项publicclassFindOptions{publicFindOptions();publicFindOptions(paramsSortOption[]sortOptions);//指定是否应当延迟加载可延迟加载的字段。publicboolDelayLoad{get;set;}//返回的匹配的数目。publicintMaxResults{get;set;}//排序选项的集合。publicSortOptionCollextionSortOptions{get;}}//表示参数名和值publicclassParameter{//使用名称和值初始化Parameter对象publicParameter(stringname,objectvalue);//参数名publicstringName{get;}//参数值publicobjectValue{get;set;}}//参数名/值对的集合publicclassParameterCollectionICollection{publicParameterCollection();publicintCount{get;}publicobjectthis[stringname]{get;set;}publicobjectSyncRoot{get;}publicvoidAdd(Parameterparameter);publicParameterAdd(stringname,objectvalue);publicboolContains(Parameterparameter);publicboolContains(stringname);publicvoidCopyTo(Parameter[]array,intindex);voidICollection.CopyTo(Arrayarray,intindex);IEnumeratorIEnumerable.GetEnumerator();publicvoidRemove(Parameterparameter);publicvoidRemove(stringname);}//表示已为重复执行进行优化的搜索。publicclassPreparedFind{publicItemContextItemContext{get;}publicParameterCollectionParameters{get}publicFindResultFindAll();publicobjectFindOne();publicobjectFindOnly();publicboolExists();}//指定搜索中使用的排序选项。publicClassSortOption{//使用默认值初始化对象。publicSortOption();//使用SearchExpression、order初始化SortOptions对象。publicsortOption(SearchExpressionsearchExpression,SortOrderorder);//标识将排序的属性的搜索SearchExpression。publicSearchExpressionExpression{get;set;}//指定升序或降序的排序顺序publicSortOrderOrder{get;set;}}//排序选项对象的集合publicclassSortOptionCollectionIList{publicSortOptionCollection();publicSortOptionthis[intindex]{get;set;}publicintAdd(SortOptionvalue);publicintAdd(SearchExpressionexpression,SortOrderorder);intIList.Add(objectvalue);publicvoidClear();publicboolContains(SortOptionvalue);boolIList.Contains(objectvalue);publicvoidCopyTo(SortOption[]array,intindex);voidICollection.CopyTo(Arrayarray,intindex);publicintCount{get;}IEnumeratorIEnumerable.GetEnumerator();publicvoidInsert(intindex,SortOptionvalue);voidIList.Insert(intindex,objectvalue);publicintindexOf(SortOptionvalue);intIList.IndexOf(objectvalue);publicvoidRemove(SortOptionvalue);voidIList.Remove(objectvalue);publicvoidRemoveAt(intindex);publicobjectSyncRoot{get;}}//使用SortOption对象指定排序顺序publicenumSortOrder{Ascending,Descending}}附录CnamespaceSystem.Storage{publicabstractclassFindResultIAsyncObjectReader{publicFindResult();//将FindResult移至结果中的下一位置。publicboolRead();publicIAsyncResultBeginRead(AsyncCallbackcallback,objectstate);publicboolEndRead(IAsyncResultasyncResult);//当前对象。publicobjectCurrent{get;}//返回FindResult是否包含任何对象。publicboolHasResults{get;}//返回FindResult是否被关闭。publicboolIsClosed{get;}//返回该FindResult中的项目的类型。publicTypeObjectType{get;}//关闭FindResultpublicvoidClose();voidIDisposable.Dispose();//返回FindResult上的枚举器,从当前位置开始。在FindResult上前进任何枚举器将前进所有的//枚举器以及FindResult本身。IEnumeratorIEnumerable.GetEnumerator();publicFindResultEnumeratorGetEnumerator();}publicabstractclassFindResultEnumeratorIEnumerator,IDisposable{publicabstractobjectCurrent{get;}publicabstractboolMoveNext();publicabstractvoidReset();publicabstractvoidClose();voidIDisposable.Dispose();}}namespaceSystem{//用于在对象上迭代的公共接口publicinterfaceiObjectReaderIEnumerable,IDisposable{objectCurrent{get;}boolIsClosed{get;}boolHasResults{get;}TypeobjectType{get;}boolRead();voidClose();}//向IObjectReader添加异步方法publicinterfaceIAsyncObjectReaderIObjectReader{IAsyncResultBeginRead(AsyncCallbackcallback,objectstate);boolEndRead(IAsyncResultresult);}}权利要求1.一种包括项目、元素和关系的每一个的至少一个的数据存储,其特征在于所述项目是可储存在数据存储中的数据单元,且包括所述元素和所述关系;所述元素是包括一个或多个字段的类型的实例;以及所述关系是至少两个项目之间的链接。2.如权利要求1所述的数据存储,其特征在于,还包括多个项目,所述多个项目包括项目文件夹以及作为所述项目文件夹的成员的至少一个其它项目。3.如权利要求1所述的数据存储,其特征在于,还包括多个项目,所述多个项目包括类别以及作为所述类别的成员的至少一个其它项目。4.如权利要求1所述的数据存储,其特征在于,两个项目之间的关系是由硬件/软件接口系统自动建立的。5.如权利要求1所述的数据存储,其特征在于,所述元素是可由硬件/软件接口系统理解的。6.如权利要求1所述的数据存储,其特征在于,还包括第二元素,且其中,所述关系包括所述第二元素。7.如权利要求1所述的数据存储,其特征在于,还包括定义一组核心项目的核心模式,硬件/软件接口系统理解所述核心项目并以预定且可预测的方式直接处理所述的一组核心项目。8.如权利要求7所述的数据存储,其特征在于,所述一组核心项目中的每一项目是从公共单个基础项目中(直接或间接)导出的。9.如权利要求7所述的数据存储,其特征在于,所述公共单个基础项目是基础模式中的基本项目。10.一种具有用于包括至少两个项目的数据存储的计算机可读指令的计算机可读介质,所述项目的每一个包括至少一个元素,且所述项目的每一个与至少一个其它项目共享关系。11.如权利要求10所述的计算机可读介质,其特征在于,还包括用于所述数据存储储存项目、元素和关系的每一个中的至少一个的指令;用于所述项目用所述数据存储进一步包括所述元素和所述关系的指令;用于所述元素包括一个或多个字段的类型的指令;以及用于形成两个项目之间的关系的指令。12.一种计算机系统,所述计算机系统包括多个元素,其中来自所述多个元素中的每一元素构成包括一个或多个字段的类型的实例;多个项目,其中来自所述多个项目中的每一项目构成可由硬件/软件接口系统操纵的离散的可储存信息单元,且其中,每一所述项目包括至少一个元素;多个关系,其中来自所述多个关系中的每一关系是至少两个项目之间的链接;数据存储,所述数据存储包括所述多个项目、所述多个元素以及所述多个关系;存储平台,用于管理所述数据存储以及用于操纵所述多个项目。13.如权利要求12所述的计算机系统,其特征在于,来自所述多个项目中的每一项目属于来自多个项目文件夹中的至少一个项目文件夹,且其中,每一所述项目可属于来自所述多个项目文件夹中的一个以上项目文件夹。14.如权利要求13所述的计算机系统,其特征在于,所述项目文件夹的删除不自动导致所述项目的删除。15.如权利要求13所述的计算机系统,其特征在于,项目是在它不再属于任何项目文件夹时被删除的。16.如权利要求13所述的计算机系统,其特征在于,所述项目在它仅是一个项目文件夹的成员且所述项目文件夹被删除时自动被删除。17.如权利要求13所述的计算机系统,其特征在于,项目自动是默认项目文件夹的成员。18.如权利要求13所述的计算机系统,其特征在于,当所述项目仅是一个项目文件夹的成员且所述项目文件夹被删除时,所述项目自动成为默认项目文件夹的成员。19.一种用于组织数据存储中的项目的方法,所述项目包括(a)可由操作系统操纵的离散的信息单元,(b)至少一个元素,以及(c)与至少一个其它项目的关系;所述方法包括用于使项目是至少两个项目文件夹的成员但不被所述项目文件夹的任一个拥有,使得任一所述项目文件夹的删除不自动导致所述项目的删除的手段。20.如权利要求19所述的方法,其特征在于,所述项目是项目文件夹的成员,但不被所述项目文件夹拥有,使得所述项目文件夹的删除不自动导致所述项目的删除。21.如权利要求20所述的方法,其特征在于,所述项目是在它不再属于任何项目文件夹时被自动删除的。22.如权利要求20所述的方法,其特征在于,当所述项目不再属于任何项目文件夹时,所述项目自动成为默认项目文件夹的成员。23.如权利要求20所述的方法,其特征在于,所述项目在它仅是一个项目文件夹的成员且所述项目文件夹被删除时被自动删除。24.如权利要求20所述的方法,其特征在于,当所述项目仅是一个项目文件夹的成员且所述项目文件夹被删除时,所述项目自动成为默认项目文件夹的成员。25.一种计算机系统,包括包括至少一个项目的多个项目,其中所述多个项目的每一个构成了可由硬件/软件接口系统操纵的离散的可储存信息单元;包括至少一个项目文件夹的多个项目文件夹,其中所述多个项目文件夹构成用于所述项目的组织结构;以及用于操纵所述多个项目的硬件/软件接口系统,其中所述多个项目的每一个属于所述多个项目文件夹的至少一个,且其中,所述多个项目的每一个可属于所述多个项目文件夹中一个以上项目文件夹。26.如权利要求25所述的计算机系统,其特征在于,项目是项目文件夹的成员,但不被所述项目文件夹拥有,使得所述项目文件夹的删除不自动导致所述项目的删除。27.如权利要求25所述的计算机系统,其特征在于,项目是在它不再属于任何项目文件夹时被自动删除的。28.如权利要求25所述的计算机系统,其特征在于,所述项目在它仅是一个项目文件夹的成员且所述项目文件夹被删除时被自动删除。29.如权利要求25所述的计算机系统,其特征在于,每一项目是至少一个项目文件夹的成员,但不被所述项目文件夹拥有,使得所述项目文件夹的删除不自动导致项目的删除。30.如权利要求25所述的计算机系统,其特征在于,还包括包含至少一个类别的多个类别,其中,所述多个类别构成用于所述项目的组织结构。31.如权利要求30所述的计算机系统,其特征在于,类别是由项目属性定义的。32.如权利要求31所述的计算机系统,其特征在于,所述多个类别之一是由项目属性定义的,且仅包括用于来自所述多个类别中的特定类别的项目属性的项目可以是所述特定类别的成员。33.如权利要求30所述的计算机系统,其特征在于,所述多个类别的每一个是由项目属性定义的。34.如权利要求33所述的计算机系统,其特征在于,所述多个类别的每一个是由项目属性定义的,且仅包括用于来自所述多个类别的特定类别的项目属性的项目可以是所述特定类别的成员。35.一种能够操纵项目的硬件/软件接口系统,所述项目包括离散的信息单元,所述信息单元包括一组跨由操纵系统外壳展现的对象共同支持的基本属性。36.如权利要求35所述的硬件/软件接口系统,其特征在于,所述项目是由操作系统操纵的基本信息单元。37.如权利要求36所述的硬件/软件接口系统,其特征在于,所述项目是项目文件夹的成员。38.如权利要求37所述的硬件/软件接口系统,其特征在于,所述项目不被所述项目文件夹拥有,使得所述项目文件夹的删除不自动导致所述项目的删除。39.如权利要求38所述的硬件/软件接口系统,其特征在于,所述项目是在它不再属于任何项目文件夹时被自动删除的。40.如权利要求38所述的硬件/软件接口系统,其特征在于,所述项目在它仅是一个项目文件夹的成员且所述项目文件夹删除被时被自动删除。41.一种包括用于项目的计算机可读指令的计算机可读介质,所述项目包括可由硬件/软件接口系统操纵的离散信息单元。42.一种包括用于硬件/软件接口系统的计算机可读指令的计算机可读介质,所述操作系统包括用于操纵包括至少一个项目的多个项目的装置,其中所述多个项目中的每一个构成了可由硬件/软件接口系统操纵的离散信息单元;用于操纵包括至少一个项目文件夹的多个项目文件夹的装置,其中所述多个项目文件夹构成用于所述项目的组织结构;以及其中,所述多个项目中的每一个属于所述多个项目文件夹的至少一个,且其中,所述多个项目中的每一个可属于所述多个项目文件夹中一个以上项目文件夹。43.一种具有用于计算机的硬件/软件接口系统的计算机可读指令的计算机可读介质,其中所述硬件/软件接口系统操纵多个离散信息单元(“项目”),所述项目是通过由所述硬件/软件接口系统所管理的多个关系互连的。44.如权利要求43所述的计算机可读介质,其特征在于,第一项目具有从其自身到第二项目的关系。45.如权利要求44所述的计算机可读介质,其特征在于,所述第一项目是项目文件夹。46.如权利要求45所述的计算机可读介质,其特征在于,所述第二项目是项目文件夹。47.如权利要求45所述的计算机可读介质,其特征在于,所述第二项目是类别。48.如权利要求45所述的计算机可读介质,其特征在于,所述第二项目是既不是项目文件夹也不是类别的项目。49.如权利要求45所述的计算机可读介质,其特征在于,来自所述多个项目中的每一项目具有与至少一个其它项目的关系。50.如权利要求45所述的计算机可读介质,其特征在于,项目的子集包括项目文件夹。51.如权利要求45所述的计算机可读介质,其特征在于,项目的子集包括类别。52.如权利要求45所述的计算机可读介质,其特征在于,项目的子集包括既不是项目文件夹又不是类别的项目。53.一种具有用于计算机系统的硬件/软件接口系统的计算机可读指令的计算机可读介质,其特征在于,所述硬件/软件接口系统操纵具有可由所述硬件/软件接口系统理解的属性的多个离散信息单元(“项目”)。54.如权利要求53所述的计算机可读介质,其特征在于,所述硬件/软件接口系统包括定义至少一个项目和至少一个属性的基础模式。55.如权利要求54所述的计算机可读介质,其特征在于,所述基础模式中的至少一个项目是基本项目,它构成了基本项目类型,从所述基本项目类型中可导出在所述硬件/软件接口系统中操纵的所有其它项目。56.如权利要求55所述的计算机可读介质,其特征在于,所述基本项目类型包括用于引用所述项目是其成员的至少零个类别的属性。57.如权利要求55所述的计算机可读介质,其特征在于,所述基本项目类型包括用于硬件/软件接口系统中所述项目的唯一标识的属性。58.如权利要求54所述的计算机可读介质,其特征在于,所述基础模式中的至少一个属性是基本属性,它构成了基本属性类型,从所述基本属性类型中,可导出在所述硬件/软件接口系统中使用的所有其它属性。59.如权利要求54所述的计算机可读介质,其特征在于所述基础模式中的至少一个项目是基本项目,它构成了基本项目类型,从所述基本项目类型中,可导出在所述硬件/软件接口系统中操纵的所有其它项目;以及所述基础模式中的至少一个属性是基本属性,它构成了基本属性类型,从所述基本属性类型中,可导出在所述硬件/软件接口系统中使用的所有其它属性。60.如权利要求59所述的计算机可读介质,其特征在于,所述基础模式还包括从基本项目类型(第一项目)中导出的第二项目,所述第二项目构成了用于项目文件夹的基本类型,且所述第二项目表达了与所述第一项目的关系。61.如权利要求59所述的计算机可读介质,其特征在于,所述基础模式还包括从所述基本属性类型(第一属性)中导出的第二属性,所述第二属性构成了用于id单元键属性的基本类型。62.如权利要求61所述的计算机可读介质,其特征在于,所述基础模式还包括从所述第二属性导出的第三属性,所述第三属性构成了用于类别引用的基本类型。63.如权利要求59所述的计算机可读介质,其特征在于,所述基础模式还包括从所述基本属性类型(第一属性)导出的第二属性,所述第二属性构成了用于类别的基本类型。64.一种具有用于计算机系统的硬件/软件接口系统的计算机可读指令的计算机可读介质,其中,所述硬件/软件接口系统操纵具有可由所述硬件/软件接口系统理解的属性的离散信息单元(“项目”)。65.如权利要求64所述的计算机可读介质,其特征在于,所述硬件/软件接口系统包括定义一组核心项目的核心模式,所述硬件/软件接口系统理解且可以用预定且可预测的方式直接处理所述核心项目。66.如权利要求65所述的计算机可读介质,其特征在于,来自所述一组核心项目的每一项目是从公共单个基础项目(直接或间接)导出的。67.如权利要求66所述的计算机可读介质,其特征在于,所述公共单个基础项目是基础模式中的基本项目。68.如权利要求67所述的计算机可读介质,其特征在于,所述核心模式还定义了一组核心属性,所述硬件/软件接口系统理解且可用预定且可预测的方式直接处理所述核心属性。69.如权利要求68所述的计算机可读介质,其特征在于,来自所述一组核心项目的每一属性是从至少一个基础属性(直接或间接)导出的。70.如权利要求69所述的计算机可读介质,其特征在于,所述核心模式包括用于设备的项目。71.如权利要求69所述的计算机可读介质,其特征在于,所述核心模式包括用于事件的项目。72.如权利要求69所述的计算机可读介质,其特征在于,所述核心模式包括用于物品的项目。73.如权利要求69所述的计算机可读介质,其特征在于,所述核心模式包括用于消息的项目。74.如权利要求69所述的计算机可读介质,其特征在于,所述核心模式包括用于主体的项目。75.如权利要求69所述的计算机可读介质,其特征在于,所述核心模式包括用于位置的项目。76.如权利要求69所述的计算机可读介质,其特征在于,所述核心模式包括用于文档的项目。77.如权利要求69所述的计算机可读介质,其特征在于,所述核心模式包括用于语句的项目。78.如权利要求69所述的计算机可读介质,其特征在于,所述核心模式包括用于联系人的项目。79.如权利要求69所述的计算机可读介质,其特征在于,所述核心模式包括用于证书的属性。80.如权利要求69所述的计算机可读介质,其特征在于,所述核心模式包括用于主体id单元键的属性。81.如权利要求69所述的计算机可读介质,其特征在于,所述核心模式包括用于邮政地址的属性。82.如权利要求69所述的计算机可读介质,其特征在于,所述核心模式包括用于多信息文本元素的属性。83.如权利要求69所述的计算机可读介质,其特征在于,所述核心模式包括用于电子地址的属性。84.如权利要求69所述的计算机可读介质,其特征在于,所述核心模式包括用于id单元安全包的属性。85.如权利要求69所述的计算机可读介质,其特征在于,所述核心模式包括用于占据两个联系人之间的角色的关系。86.如权利要求69所述的计算机可读介质,其特征在于,所述核心模式包括用于基本存在的属性。87.一种用于在计算机系统的硬件/软件接口系统中操纵多个离散信息单元(“项目”)的方法,所述方法包括将所述项目与多个关系互连,以及在硬件/软件接口系统级上管理所述关系。88.如权利要求87所述的接口系统,其特征在于,来自所述多个关系中的每一关系在硬件/软件接口系统级上,构成了所述关系互连的一对项目之间的映射。89.如权利要求88所述的接口系统,其特征在于,每一关系具有属性。90.如权利要求89所述的接口系统,其特征在于,每一关系包括用于所述关系的目标项目的标识的属性(Target)。91.如权利要求90所述的接口系统,其特征在于,每一关系还包括用于所述关系的目标项目的所有权的属性(IsOwned)。全文摘要本发明的各实施例针对包括项目、元素和关系的数据存储(302)。项目是数据存储(302)中的数据存储单元,且还包括所述元素和所述关系。元素是包括一个或多个字段的类型的实例。关系是至少两个项目之间的链接。数据存储(302)还包括定义一组核心项目的核心模式(340),硬件/软件接口系统理解该组核心项目且可以使用预定的和可预测的方式直接处理该组核心项目。核心项目是从公共单个基础项目导出的,该基础项目是基础模式中的基本项目。文档编号G06F17/30GK1820245SQ03826943公开日2006年8月16日申请日期2003年8月21日优先权日2003年8月21日发明者A·K·诺瑞,S·阿加瓦尔,J·P·汤普森,P·赛尔斯,D·G·坎普贝尔,S·F·特瑞克,K·卡梅伦,W·R·史密斯,D·A·沙吉布,N·H·巴卢,S·P·阿查里雅,B·S·拉曼,P·M·司皮洛申请人:微软公司
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1