CN1828594A - 对象关系型数据的数据模型 - Google Patents
对象关系型数据的数据模型 Download PDFInfo
- Publication number
- CN1828594A CN1828594A CN 200610004632 CN200610004632A CN1828594A CN 1828594 A CN1828594 A CN 1828594A CN 200610004632 CN200610004632 CN 200610004632 CN 200610004632 A CN200610004632 A CN 200610004632A CN 1828594 A CN1828594 A CN 1828594A
- Authority
- CN
- China
- Prior art keywords
- type
- entity
- name
- attribute
- data
- Prior art date
- Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
- Pending
Links
Images
Landscapes
- Information Retrieval, Db Structures And Fs Structures Therefor (AREA)
Abstract
一种公用数据模型(CDM),它是多个应用程序专属数据模型公用的数据模型。CDM既支持PIM(个人信息管理器)终端用户应用程序数据,又支持业务(LOB)数据。类似地,SDM类型(系统定义模型)应用程序可在CDM之上指定其模型。CDM通过使用实体组件和关系组件来实现应用程序之间提高的可相互操作性,其中实体类型提供具有多个完全不同的应用程序上的统一标识的数据实体,而关系组件定义两个或多个数据实体之间的关系。CDM提供任何代数可在其上操作的类型系统。
Description
相关申请的参照
本申请要求于2005年2月28日提交的题为“DATA MODEL FOROBJECT-RELATIONAL DATA”(对象关系型数据的数据模型)的美国临时专利申请第60/657,295号的优先权,并涉及于2005年6月30日提交的题为“PLATFORMFOR DATA SERVICES ACROSS DISPARATE APPLICATION FRAMEWORKS”(跨越完全不同的应用程序框架的数据服务的平台)的待审美国专利申请第11/171,905号。上述申请的全部内容通过引用包含于此。
背景技术
数据持久化在任何应用程序中都是关键性要求,无论是消费者应用程序还是业务(LOB)应用程序。例如,外壳和媒体应用程序保存文档、音乐和照片,电子邮件应用程序保存消息和日历对象,而商务应用程序套件保存顾客和订单对象。几乎所有这些应用程序都定义数据的对象模型,并编写它们自身的持久化机制。
用于描述、查询和操纵数据的标准机制是基于SQL(结构化查询语言)的关系型数据库管理系统(RDBMS)。SQL数据模型是用来声明性地描述表、约束等形式的数据的结构。但是,诸如LOB应用程序等数据密集型应用程序发现SQL在某些方面不足以满足它们的需求。首先它们的数据的结构比能用SQL来描述的结构更为复杂。第二,它们使用面向对象的语言来创建其应用程序,而面向对象语言在它们能够表示的数据结构方面也要比SQL更为丰富。
这些应用程序的开发者通过使用在诸如C#等编程语言中实现的面向对象的设计描述其数据来解决这些缺点。然后他们或者手动地或者使用某种形式的面向对象的技术在SQL数据和对象之间进行转换。不幸的是,不是每一种面向对象的设计都可被容易地映射到给定的SQL实现,或者在某些情形中,可被容易地映射到任何SQL实现,从而产生要让开发者处理差异的大量手动编程工作。
另一个问题是,开发者从SQL得悉和认识的能力在其数据是对象的形式时对他们而言是不可用的。例如,表达查询必须以底层数据库的语言来完成,而不是他们对其它任务所使用的对象。
一个解决方案是提供受到框架支持的较丰富的数据模型以及数据库服务器或支持运行库。对于开发者而言,它看起来就好像是具有较丰富的用于描述和操纵数据的能力的数据库。一个通用且简单、但又丰富的数据模型将实现适用于这些应用程序的公用编程模型,并允许应用程序平台在公用数据访问基础上进行革新。因此,对于提供适用于多个完全不同的应用程序的公用编程模型的能力的富数据模型有未被满足的需求。
发明内容
以下给出简化的概述以提供对所揭示的发明的一些方面的基本理解。此概述并不是详尽的综览,它也并不试图标识本发明的关键/必要元素或界定本发明的范围。它唯一的目的是以简化形式给出一些概念,以作为对稍后给出的更加详细的描述的序言。
所揭示的发明是一种称为公用数据模型(CDM)的富数据模型。该模型由实现它的一种称为公用数据平台(CDP)的平台支持。CDM是对于多个应用程序专属的数据模型公用的数据模型。例如,它既可支持PIM(个人信息管理器)终端用户应用程序数据,又可支持业务(line-of-business:LOB)数据。类似地,诸如MicrosoftWindowsTM SDM(系统定义模型)等带有自己的数据模型的应用程序可在CDM之上指定其自己的模型。CDM实现应用程序之间提高的可相互操作性。
在应用程序中有相当数量的通常使用的数据建模和持久化概念可被分解为公用数据模型,由此提供了可被大量应用程序操作的富持久化框架。CDM能力包括将关系型概念归类,定义数据的富对象抽象、将富语义(例如,关系)建模,将应用程序和CDM之间的不匹配最小化,与CLR(公用语言运行库)类型系统对齐,支持实现中层和客户应用程序的开发的行为,以及提供逻辑概念。建模概念捕捉独立于数据存储的语义。
CDM改进SQL的一个示例是定义关系的情形。在SQL中,顾客和订单之间的关系不能被显式地表达。表达可从其推断关系的外来关键字约束是可能的,但是外来关键字只是实现关系的许多方法中的一种。在CDM中,关系可被显式表达,并且和表定义具有属性的方式相同,关系也具有属性。关系是一等公民。第二个示例是CDM具有适用于对象的类型系统,该类型系统使其能与CLR更自然地集成。
在本发明的另一个方面,提供了CDM的一种替换实现,其中使用<Association>(关联)或<Composition>(合成)元素在顶层定义关系。由此,就无需为定义Ref(引用)关联(或合成)而在源(或父)上定义一属性。
为实现前述及相关目的,本文中结合以下描述和附图描述了所揭示的发明的某些示例性方面。但是,这些方面仅仅指示了可采用本文中所揭示的原理的各种方法中的数种,并且旨在包括所有这些方面及其等效技术方案。当结合附图考虑以下详细描述,其它优点和新颖特征将会明确。
附图说明
图1示出根据本发明的一种公用数据模型(CDM)体系结构。
图2示出根据一个发明方面的一种提供CDM的方法。
图3示出关系组件及其形式。
图4示出实体组件、其成员、以及成员类型。
图5示出用于描述本发明的核心数据模型特征的LOB应用程序窗口。
图6示出一LOB应用程序窗口以及如何在图5的LOB应用程序窗口上反映实体之间的结构关系。
图7示出强加在图5的LOB应用程序窗口上的实体的合成。
图8使用了采用实体关系、聚合关系及其定址的CDM概念示出根据本发明的一种示例性LOB模型和约束。
图9根据CDM示出实体关键字和标识符的用途。
图10示出一些内联类型的UML表示。
图11示出一些实体类型的UML表示。
图12示出合成下的一些类型的UML表示。
图13示出TS.TableD中的D的一个实例的可视化表示。
图14示出对应于图13的实体表的SQL表。
图15示出一种可利用所揭示的发明的CDM的数据平台。
图16示出阐明与类型相关的模型的语义的CDM元模型片段。
图17示出阐明与属性相关的模型的语义的CDM元模型片段。
图18示出阐明与关联相关的模型的语义的CDM元模型片段。
图19示出CDM的替换实现的4个主要概念。
图20示出CDM支持类型继承的概念。
图21示出适用于此实现的CDM类型的分类法。
图22示出CDM的这一实现中类型和实例的概念。
图23示出如何使用SDL来声明实体和内联类型。
图24示出CDM所支持的许多类型的关系。
图25示出适用于CDM中被持久化的实体的结构组织。
图26示出CDM的这一实现中实体扩展的用途。
图27示出替换实现中阐明与类型相关的模型的语义的CDM元模型片段。
图28示出替换实现中阐明与属性相关的模型的语义的CDM元模型片段。
图29示出替换实现中阐明与关联相关的模型的语义的CDM元模型片段。
图30示出图29的UML合成图,该图示出其中所示关系的数个方面。
图31示出替换实现的高级关系。
图32示出可用于执行该CDM体系结构的计算机的框图。
图33示出可在其中采用该CDM的示例性计算环境的示意框图。
具体实施方式
现在参考附图描述本发明,其中贯穿全文使用相同的标号指向相同的元素。在以下描述中,出于解释的目的,阐述了许多特定细节以提供对本发明的详尽理解。但是,很明显无需这些特定细节也可实施本发明。在其它实例中,以框图形式示出公知的结构和设备以便于对这些实例进行描述。
如此申请中所使用,术语“组件”和“系统”意指计算机相关的实体,无论是硬件、硬件和软件的组合、软件、还使执行中的软件。例如,组件可以是,但不限于,在处理器上运行的进程、处理器、硬盘驱动器、(光学和/或磁存储介质的)多个存储驱动器、对象、可执行码、执行线程、程序、和/或计算机。作为示例,在服务器上运行的应用程序和该服务器都可以是组件。一个或多个组件可驻留在进程和/或执行线程内,而组件可被局部化在一台计算机上和/或被分布在两台或多台计算机之间。
尽管参考了如截屏图等某些附图示出并描述了向用户显示信息的某些方式,但是相关领域的技术人员将会认识到可以采用各种其它替换方式。术语“屏幕”、“万维网页”和“页面”在本文中一般可被互换使用。页面或屏幕作为显示描述、作为图形用户界面、或通过描述屏幕上的信息的其它方法(例如,无论是个人计算机、PDA、移动电话,还是其它适用的设备)被存储和/或发送,而要在页面上显示的布局以及信息或内容被存储在存储器、数据库、或其它存储装置中。
首先参考附图,图1示出根据本发明的一种公用数据模型(CDM)体系结构100。CDM 100包括一实体组件102,它提供跨越多个完全不同的应用程序的统一标识(identity)的数据实体。关系组件104定义两个或多个数据实体之间的关系。
CDM 100是多个应用程序专属的数据模型公用的数据模型。例如,它既可支持PIM(个人信息管理器)终端用户应用程序数据,又可支持业务(LOB)数据。类似地,SDM类型(WindowsTM系统定义模型)的应用程序可在CDM 100之上指定其模型。CDM 100实现应用程序之间提高的可相互操作性。
有相当数量的数据建模和持久化概念可被分解为CDM,由此使用诸如对象关系型持久化框架等用于描述数据并实现可有益于所有应用程序的公用服务集的公用词汇表。CDM的一个间接目的是使应用程序不再受定义其自身的持久化基础结构的约束,并实现跨越不同数据存储的较高等级的应用程序可相互操作性。其它目的包括将关系型概念归类,定义数据的富对象抽象,将富语义(例如,关系)建模,将应用程序和CDM之间的不匹配最小化,与CLR(公用语言运行库)类型系统对齐,支持实现中层和客户应用程序的开发的行为,以及逻辑概念。建模概念捕捉独立于数据存储的语义。
本发明的CDM至少提供以下新颖的方面。
●由实体类型、内联类型、实体表、表集(table set)和关系构成的类型系统
●实体和内联类型之间的区别
●实体类型包括标识和关键字的概念(而不是向在SQL中的情况那样用表来定义它们)
○包含实体属性的合成的关键字的显式声明
●实体之间的关系(关联)的不同形式
○实体关联与其它关联类型的可合成性
○公用值关联
○条件关联(提供更加复杂的联合类型关系)
●在实体上指定的属性(属性描述)相对于在关系上指定的属性(如何使用那些属性来将实体相关)的分解
●嵌套表(合成)
●扩展
○类型专属的
○基于实例或类的
○从其它扩展推导的能力
○指定存储表的能力
●可扩展枚举
●关系的导航属性的声明
●对仅应用于特定表的关联的范围界定
●将实体表和关系分组到表集中
●指定要在实体定义、关联或表集中使用的表的能力
●每个类型定义的属性集
●将投影表示为匿名类型
●类型约束的规范
以下是对任何代数将在其上操作的CDM类型系统的文本描述。缩进形式指示缩进的类型是一种“凸排”(outdented)类型;例如,数组类型是内联类型。
类型-所类型化的抽象基
实体类型-具有内联命名类型的属性的可引用类型(具有唯一的标识)
内联类型-没有标识
集合类型
数组类型-一组内联类型实例
实体表类型-一实体集
标量类型
实体ref类型-对实体的引用
表ref类型-这是更新代数所需的;它不应作为属性的类型使用简单类型-诸如int(整数)、string(串)、Xml、FileStream(文件流)等
枚举类型
数组类型-一组内联类型实例;它是一个RowSet(行集)<I>
复合类型
结构化类型-具有用户定义的属性的类型;内联类型的属性
匿名类型-非命名的;每次使用时被重新定义的;具有内联类型的属性
行集类型-一组内联或实体类型实例
实体表类型-实体类型实例集;它是一个场地(存储实例的地方)
关系型表类型-一组匿名类型实例;它是一个场地
图2示出根据一个发明方面的一种提供CDM的方法。尽管出于解释简单的目的,本文中以例如流程图表或流程图形式示出的一种或多种方法是作为一系列动作来示出和描述的,但是应当理解并认识到,本发明不受动作顺序的限制,因为根据本发明,一些动作可以按不同顺序发生和/或与来自本文中示出和描述的方法的其它动作同时发生。例如,本领域技术人员将会理解和认识到,方法可被替换地表示为诸如状态图中等一系列相互关联的状态或事件。此外,不是所有示出的动作都是实现根据本发明的方法所需的。
在200,提供了一种定义用于界定模式定义的范围的名字控件的方案。在202,定义了用于将属性和方法分组的实体类型。在204,定义了其属性为表的表集实体。在206,使用关系(例如,关联、合成、......)表达了实体之间的语义连接。
实体将现实世界的对象建模。在CDM中,实体是可使用其标识(关键字)唯一标识的数据对象。实体是可使用其标识来共享(引用)的最小单元。实体具有结构(例如,属性)和行为(例如,方法)。不同类型的实例的一些例子有订单、顾客、合同、文档、等等。实体和SQL99中的类型化行或ODBMS中的对象类似。实体被定义为实体类型的实例。仅为举例目的,以下是实体定义的语法:
<EntityType Name=″Order″Key=″OrderId″>
<Property Name=″OrderId″Type=″Guid″Nullalbe=″false″/>
<Property Name=″Date″Type=″DateTime″Nullalbe=″false″/>
...
</EntityType>
每个实体都具有由实体关键字值构成的唯一标识。此标识是构成对该实体的引用的基础。实体关键字是该实体的一个或多个属性的集合。每个实体都具有由实体关键字值构成的唯一标识。此标识是构成对该实体的引用的基础。每个非抽象实体类型定义必须指定关键字属性或从基实体类继承关键字规范。关键字属性的值可以是用户定义的或者系统生成的。
实体的标识符是从该实体的关键字加上该实体的包含实体或父实体的标识符构成的。父实体是包含其中存储了该(子)实体的表的实体。实体的关键字只需在其表中是唯一的——其它表可包含具有同一实体关键字值的实体。由此,通过将实体的关键字值与其父的标识符相结合来使该实体标识符唯一。在一些实例中,可通过诸如使用全局唯一标识符(GUID)等来使关键字在存储范围内唯一。CDM仅要求标识符在元素(例如,实体集)内是唯一的。
标识完全标识了实体,并可被反引用以回到该实体实例。引用使用标识。给定一实体,即可获得其引用值。当且仅当两个实体的标识相同时,它们是相同的。CDM中引用类型的语法是“Ref(<entity_type>)”,而属性可以是“ref”类型,这一属性被称为ref属性。ref值可被持久化;它们是对实体的持久引用。复制ref值并不将实体复制到它们所引用的对象。ref值还通过Ref(引用)和Deref(反引用)操作符来提供查询语言内部的导航。
引用实现了实体的共享。例如,订单实体可具有顾客ref属性。同一顾客的所有订单的顾客ref属性将具有相同的值。ref的结构是由实现定义的。ref和关键字可在API中作为类型给出。ref的实现包括其所引用的实体的标识符信息,该信息包括关键字值,可能还包括在其中找到该实体的表。它可将ref作为个体的关键字值存储(实现了高效的联合)或作为单个的不透明值存储。函数可给出ref的结构,以获取关键字值或包含该实体的表。
CDM由以下核心概念构成:实体和关系。实体是具有单个标识的密切相关的数据的集合。关系是将两个或多个实体相关的机制。图3示出关系组件102及其形式。关系描述两个或多个实体如何相关。关系300表现为以下各种形式中的一种。
关联302是两个或多个实体之间最一般形式的关系300。称为端点的实体经由显式的源-目标(类似于外来关键字-主关键字)关系或经由查询相关。关系中的每个端点保持独立于其它端点。使一个端点在另一端点被删除时也被删除,或只要在另一端点存在的情况下就防止一个端点被删除是可能的。
合成304是以子实体在概念上是父实体的组成部分的方式与一个或多个子实体相关的父实体。子实体仅在一个父实体中存活,因此当父实体被删除时总是必须被删除。此外,其标识仅需在该合成中的其它子实体中间是唯一的。
在称为端点的两个或多个实体被一称为关联实体的本身可具有属性的单独实体上的关系链接在一起的情形中定义了关联实体306。这些端点中的每一个保持概念上独立于其它端点。
图4示出实体组件100及其成员和成员类型。实体组件100利用由实体成员组成的实体400。以下类型的成员受到支持。属性402为特定类型的实例分配存储。导航属性404简化由关联相关的实体上的查询。经计算属性表示与已存储的值对立的经计算的值。方法408表示可被执行的操作。
实体成员具有成员类型和/或取类型化的参数。当描述实体的成员时,以下各种类型是可用的:内联类型412和表类型414。内联类型是其数据被内联地存储在实体上的类型。类似于实体类型,内联类型也是由成员组成的。和实体类型不同的是,内联类型在超出由它们驻留在其内的实体强加的范围以外不具有任何标识。在数据模型中,内联类型可被直接声明,并包含数种其它的类型。内联类型包括以下类型。
简单内联类型416是不具有在公用数据模型中可见的任何内部结构的内联类型。CLR值类型是公用数据模型中的简单类型。枚举类型418是命名值集。枚举类型418是可由多个开发者独立和同时扩展而无惧于冲突的简单类型。实体引用类型420是对单个实体的持久引用,可能包括对该实体驻留在其中的表的引用。实体引用与关联相结合被用来将两个实体相关。表引用类型422是对表的持久引用。数组类型424是除数组以外的内联类型的实例的有序集合。
表类型414是指定实体类型的实例的无序集合。表与合成相结合被用来将两个实体相关。以上所列出的所类型化都是被包含的类型,即这些类型的值可被实体包含。
实体的类型描述该实体的成员。实体类型可从基实体类型推导,在这种情形中,派生的实体类型包含基类型的所有成员以及针对派生类型所描述的成员。实体类型可由多个开发者独立和同时扩展而无惧于冲突。此类实体扩展类型不依赖于类型继承。实体和实体扩展类型不是被包含的类型。
表集是具有表值属性的实体类型的实例。声明一表集就创建了该类型的单个命名实例,并由此创建了其所包含的每个表。以类似于创建数据库就创建了用于存储数据的位置的方式,表集也创建用于存储数据的位置。
现在参考图5,图中示出了用于描述本发明的核心数据模型特征的LOB应用程序窗口。销售订单条目示出诸如订单号、顾客号、顾客名等数据,以及诸如项目编号、描述、数量和其它相关信息等订单线信息。
图6示出如何在图5的LOB应用程序窗口上反映实体之间的结构关系。如上文中所示,CDM的两个核心概念是实体和关系。实体是具有属性以及唯一标识它的标识的对象。关系是将实体相关的方法。在图6中,订单和顾客是由关联相关的两个实体。这里,订单实体仅与一个顾客实体(“1”)相关联。直观上,一个顾客可与0个或多个订单(“*”)相关。实体具有属性,并可相互继承。关联被以不同的方式实现:作为引用(例如,Order.Customer(订单.顾客)),作为属性之间的联合,作为实体,等等。
关联能以许多不同方式来实现。一个方法是使用引用(类似于指针)。在前面图6的示例中,有一个引用,它是从订单到顾客的指针。这就方便地实现了约束,因为可有一个顾客与该订单相关。在一个实现中,引用属性中只能有一个引用。
另一个方法是使用条件关联,它是以属性形式描述的关系。有以某种方式相关的两个属性,或者以某种方式相互关联的一属性集。公用值关系是如果两个实体具有相同的值则它们是相关的这样一种关系。例如一文档(实体)具有作者名(属性),另一称为联系人的实体具有联系人名属性。可在该文档实体的作者名属性和联系人实体的联系人名属性之间建立关系。如果那些属性值是相同的,则那两个实体之间具有关系。这可被一般化为创建某个表述“如果此表达式为真,则这些实体是相关的”的任意表达式。例如,如果第一实体具有第一矩形属性,第二实体具有第二矩形属性,则可将关系定义为如果第二实体矩形完全包含第一实体矩形则第一和第二实体相关。
第三个方法是关联实体,其中实体被用来进行连接。这可被用来在关联上具有属性。
图7根据本发明示出强加在图5的LOB应用程序窗口上的实体的合成。合成是其中一事物包含另一事物的包含,因此不仅仅是一种关系。例如,订单具有或包含订单线实体集。父标识加上子标识一起组成了子实体的完整标识。合成由父实体上的实体表属性表示。CDM内重复使用表概念来表示合成的这一重复使用性是有利的。合成(如黑色菱形所示)将两个实体相关联为父和子。每个订单都具有许多个(“*”)订单线实体(或其派生实体)的表。父实体控制子实体的生命期,因为子实体在父实体内存活,删除父实体必定删除子实体。子实体仅需在同一合成中的其它子实体之间是唯一的。
图8使用了采用实体关系、聚合表及其定址的CDM概念示出根据本发明的一种示例性LOB模型和约束。带箭头的线表示关联(例如,引用属性),黑色菱形指示合成(表属性),而表集类似于数据库。表集是应用程序数据树的根。表集是表集类型的实例。表集类型只具有表值属性。即,表集类型只参与合成。表集类型是一种实体类型。应用程序通过定义称为“表集”的表集类型的实例来创建数据(例如,定义“NorthwindData”类型的“Northwind”)。表集还描述被安装在服务中并且最终被安装在数据库中的数据集。它是自包含和可合成的数据单元。
当一实体(例如,SalesData(销售数据))被定义,可令其与许多不同实体相关。例如,公司内将会有订单集和顾客集。这示出一对不同的合成。订单内会有订单线,从而树开始成形。在树的顶部是称为表集实体的特殊实体。表集是某个实体类型的单个实例。(此构造类似于SQL概念的数据库。)表集提供一种数据声明的方式。在图中,它被以白色绘出(而不是阴影框),因为它与其它实体不同。该LOB示例示出具有一个或多个公司、地址、顾客和订单的销售数据表集(或“数据库”)。顾客实体在例如公司表示住宅业务或者公司表示商业业务时,顾客实体可以是单个公司的一个部分。为说明图8的LOB模型中实体关系的概念,父实体公司具有订单和顾客两个子实体。CDM在公司实体中逻辑地构建相互脱离的子表。从订单实体到地址实体的线是到子实体的关联。
CDM中合成的一个方面是,如果一公司设立数个订单,则该订单集和另一公司的订单集是脱离的。例如,来自零售的订单与来自工程的订单永远不会有交集或重叠。合成意味着这些集合是分离的,不重叠的,并且它们不共享。如上文中所示,关联由带箭头的线表示。因此,一订单可引用一顾客,并可生成另一订单(未示出)使其引用同一顾客。这里,订单无需引用其紧邻的同级(顾客),而是可以直接引用被包含的地址实体。一个以上订单可引用被标记为开账单地址的地址。概念上,订单将被开给在该地址的人。但是,订单的每个订单线可被运往沿每条线引用的各别的运货地址。这些地址中的每一个都来自订单线的父实体——订单所引用的同一顾客。由此,引用扩展至属于该顾客的地址。
CDM的另一个方面允许引入约束。考虑以下三条关联线:从订单到顾客;从订单到地址;以及从订单线到地址。没有什么要求订单或其线所引用的顾客地址必须属于该订单的顾客。令地址引用另一个顾客的地址是可能的。但是,CDM中有可被应用以确保地址是正确的顾客的地址的约束。这被称为关联的“范围界定”。就订单实体和顾客实体之间的关联而言,一个约束是订单只可引用同一公司中的顾客。即,它们具有“公用祖先”。
就订单实体和地址实体之间的关联而言,一个约束是订单只可引用聚合表/销售数据/公司/顾客/地址中的地址。聚合表是约束和经由属性路径的查询中的地址。这里,销售数据表集类型具有名为“公司”的表属性800。每个顾客实体都有其自身的地址实体表。那些表的聚合(实际上是它们的并集)由地址实体处的表名:销售数据/公司/顾客/地址来定址。
图9根据CDM示出实体关键字和标识符的用途。关键字是实体上的在特定表中唯一标识该实体的一个或多个属性,其中同样,表是通过合成关系构成的。例如,可将社会保障属性定义为顾客的关键字。关键期确保例如表内没有两个顾客具有相同的社会保障号。实体的标识的第二部分是其中存在该实体的表。如果想要有两个具有相同名字的顾客,则或可将关键字定义为除了名字以外的某个属性(如本文中所述),或可将每个顾客放到不同的表中以避免名字冲突。实体表是通过提供包含表属性的实体的实体的标识符加上表的属性名来标识的。因此,它是递归定义。
在图9中,有两个A表(B上的A表和C上的A表)。给定一个A,其标识符由AID(<<key>>AID)组成,它也指示了它位于哪个表中。一种可能性是它在A表属性中的特定B实体中。另一种可能性是它在A表属性中的特定C实体中。一个实际的例子是通常为序列号的订单线关键字。属性名是被标记为关键字的序列号。可以有许多具有相同序列号的不同订单。因此,序列号仅需在该订单内、而不是在所有订单中是唯一的。
如上文中所示,CDM所提供的另一个方面是表的聚合。例如,对应于一个订单的订单线表和对应于另一个订单的订单线表是脱离的。但是,不考虑订单本身,知道某个项目被订购了多少可能是人们所关心的。因此,需要在不考虑订单本身的情况下审核所有订单线,以明确所订购的器具的个数。聚合表是实现此目的的方法。即,查看许多不同订单或其它实体类型上的所有订单线是可能的。
以下是对所揭示的发明的CDM更为详细的描述。在CDM中,关键字是在类型上定义的;相反,在SQL99中,关键字是在表上而不是行类型定义上定义的。尽管将关键字定义与实体类型定义去耦看起来可能是灵活的(或可扩展的),但是它实际上限制了类型的可重复使用性和可移植性。如果关键字是在表上定义的,那么类型专属的行为可能不能在不同的表上都有效。即,不能保证写在实体类型上的某个商务逻辑(例如创建顾客、订单并将它们相关)将会在这些实体类型的不同存储上都有效,由此减弱了类型的可重复使用性。在SQL99中,这并不是问题,因为它不指定类型被如何映射到客户/中层应用程序编程环境中。SQL99中缺少实体类型上的标识迫使人们将类型表映射为编程语言对象(类)而不是映射实体类型。此外,将标识与表相关联不适应支持暂态实体。标识被与实体类型相关联以支持可重复使用的类型和层不可知的类型行为。
实体持久化。实体可通过调用实体类型的构造函数(新建)方法来创建;通过将它们添加到表中,实体被持久化。在CDM中,实体表是类型化的实体集合。实体表类似于SQL99类型化表,但前者是逻辑的。即,实体表可被映射到一个或多个物理的SQL表。一实体类型的表被称为该类型的实体表。
实体的生命期取决于该实体为其成员的表的生命期。当表被删除时,该表中的实体也被删除。实体还可被显式地删除。
实体表是通过定义合成或指定实体类型中的属性来定义的。逻辑上,当实体类型的实例被创建时表的实例被创建,而当该实体实例被删除时表的实例被删除(但是,一般在定义类型的模式被安装时物理的SQL表被创建,并且它一直存在,直至该模式被反安装)。
<EntityType Name=″Order″...>
<Property Name=″Lines″Type=″Table(OrderLine)″.../>
...
</EntityType>
<EntityType Name=″OrderLine″...>
...
</EntityType>
此类属性定义了父和子实体类型(在此例中分别为Order(订单)和OrderLine(订单线))之间的台成关系。
可创建任意个数的表来存储给定实体类型的实例。每个表都是完全独立的(关键字仅在单个表等的范围中是唯一的)。给定类型的所有实例没有可被查询的任何全局“扩展”。
可通过在<EntityType>(实体类型)元素上包括表属性来将实体类型约束到单个表。这在实体将包含取决于其它实体类型的表的存在的行为时是有用的。例如,Order(订单)类型很可能取决于Customer(顾客)表的存在(反之亦然),这在下例中通过包括Table(表)属性来反映。
<EntityType Name=″Order″Table=″SalesData.Orders″...>
...
</EntityType>
<EntityType Name=″Customer″Table=″Sales Data.Customers″...>
...
</EntityType>
<EntityType Name=″Sales Data″...>
<Property Name=″Orders″Type=″Table(Order)″.../>
<Property Name=″Customer″Type=″Table(Customer)″.../>
</EntityType>
对实体设置表约束排除了出现一个以上该类型的表的情况。限制性较低的一种方法是对关联设置约束,如在关系一章中的关联一节中所描述。
表集。表集类型是实体类型的受限形式。表集类型可能仅有应用和表值属性、经计算属性、和/或方法。例如,
<TableSetType Name=″SalesData″>
<Property Name=″Orders″Type=″Table(Order)″.../>
<Property Name=″Customer″Type=″Table(Customer)″.../>
</TableSetType>
表集是表集类型的实例。每个表集实例都具有在给定存储内唯一的名字。表集实例可在模式中声明,或可使用存储提供的操作来动态创建。以下示出从一模式出发的示例性表集实例声明:
<TableSet Name=″Sales″Type=″SalesData″/>
表集名以及表属性名可在查询的FROM从句中使用。例如:
SELECT OrderID,Date FROM Sales.Orders
表集类型可声明默认的表集实例。例如:
<TableSetType Name=″WinFSData″DefaultTableSet=″WinFS″>
...
</TableSetType>
<TableSet Name=″Sales″Type=″SalesData″/>
将先前所定义的表集聚合为一新的表集也是可能的。这在将来自两个单独的应用程序的数据合成到单个应用程序中时是有用的。注意,上例中的SalesData(销售数据)实体类型是抽象的。这是因为非抽象实体类型必须指定关键字属性,在用于表集的实体类型中,简单类型的属性是不被允许的。将先前所定义的表集聚合为一新的表集的可能的。这在将来自两个单独的应用程序的数据合成到单个应用程序中时是有用的。
实体类型对内联类型。内联类型是非实体类型。内联类型类似于结构类型;它们仅仅是值。它们不具有任何标识;每个内联类型都是不同的,即使它们具有完全相同的值。在CDM中,内联类型只可作为实体属性的类型使用。内联类型值随该内联类型是其一个部分的实体内联地存储。因为内联类型实例不具有其自己的标识,所以它是不可引用的。它可经由持有该内联类型实例的实体属性来引用。以下是内联类型定义的示例:
<InlineType Name=″Address″>
<Property Name=″Street″Type=″String″Nullable=″false″/>
<Property Name=″City″Type=″String″Nullable=″false″/>
...
</InlineType>
尽管实体类型和内联类型都是强类型化的并具有相似的结构,但是它们具有截然不同的持久化、共享和操作语义。内联类型实例不是由它们自身持久化的;它们在结构上是实体类型的一个部分。内联类型实例不能别共享;每个实例的使用是排它的。内联类型实例不是如复制、移动、删除、备份、恢复等大多数操作的目标。
由于以上语义差异,提供不同的内联和实体类型概念以使应用程序能够正确地编程是很重要的。在SQL99中,内联和实体类型概念没有被显式建模。在SQL99中,只有“用户定义类型”。如果一种类型被作为列类型来使用,则它表现出类似于内联类型的行为;如果它被用来定义表,则它表现为实体类型(行类型)。因为关键字是在表上定义的,所以只有类型化表的的行被标识。因方类型不具有关键字,所以在SQL中,当推论类型实例时,必须以带关键字的类型实例和不带关键字的实例的语言来表达。
在CDM中,实体类型和内联类型是以单独的句法规范显式地建模为单独的概念。
数据并发。数据并发可被乐观或悲观地管理。无论在哪种情形中,并发管理的单元都是实体,在乐观并发中用于冲突检测,在悲观并发中用于锁定。本数据模型允许采用不同的冲突检测方案,并且将其视为数据模型实现和开发者(如果本数据模型实现给予他们该机动性)的策略决策(例如,该实现可在正被更新的属性中没有任何一个已改变的情况下忽略冲突)。
在悲观并发中,对完整的实体除其中所嵌套的表以外的部分加锁。因此,在以锁来读一实体的情况中,如果另一个用户将该实体锁定,则读将失败。但是,如果仅仅子实体被锁定,则对父实体的读将会成功。本数据模型允许采用不同的锁定方案,并且将其视为数据模型实现和开发者(如果本数据模型实现给予他们该机动性)的策略决策。
关系。关系将两个或多个实体相关。例如,联系人创作文档,或者订单包含订单线。关系可以是关联或合成。关联描述实体之间的“对等”关系,而合成描述两个实体之间的父/子关系。
关系本身并不作为类型的实例存储在存储中,而是由相关实体上的数据具体化。关联的一种特定用途指定实体类型关联实体为具体化该关系的实体,并且任选地可将附加数据作为关系的一个部分存储。每个关联都有一个名字;该名字表示实体之间的语义关系。例如,DocAuthor(文档作者)是文档和联系人之间的关系的名字;DocAuthor关联将联系人相关为文档的作者;类似地,OrderCustomer(订单顾客)是将顾客与订单相关联的关联;给定一个订单,即可导航关联来确定其顾客。
注意,关联与合成的概念和UML关联与合成的概念是一致的。实体关系图形表示和UML术语(例如,角色、多重性、......)被尽可能地保留。
关系的概念在关系型模型中不被显式支持。外来关键字和主关键字以及引用完整性提供了以受限方式实现关系的工具。SQL99已添加了如Ref(引用)和Table(表)类型等对象关系型扩展来支持单实体值和多实体值的属性,但关系未被正式建模。
CDM将SQL99的ref和table属性与UML的关联和合成概念相结合。此方法给SQL带来富关系和导航,而给使用UML建模的应用程序带来可查询性。
关联。关联表示实体之间的对等关系。可将关联基于引用类型的属性或非引用类型的属性的使用。它们还可涉及扮演特定角色的关联实体。以下依次进行描述。使用引用类型的属性的关联。考虑以下示例性模式。
<EntityType Name=″Customer″...>
...
</EntityType>
<EntityType Name=″Order″...>
<Property Name=″CustRef″Type=″Ref(Customer)″Nullable=″false″
Association=″OrderCustomer″/>
...
</EntityType>
<TableSetType Name=″SalesData″>
<Property Name=″Orders″Type=″Table(Order)″.../>
<Property Name=″Customers″Type=″Table(Customer)″.../>
<Property Name=″BadCustomers″Type=″Table(Customer)″.../>
</TableSetType>
<Association Name=″OrderCustomer″>
<End Role=″OrderRole″Type=″Order″Multiplicity=″*″
Table=″SalesData.Customers″/>
<End Role=″CustomerRole″Type=″Customer″OnDelete=″Cascade″
Multiplicity=″1″/>
<Reference FromRole=″OrderRole″ToRole=″CustomerRole″
Property=″CustRef″/>
</Association>
关联有两个端点,其中每一个都表示一个相关的实体。每个端点都提供以下信息:
●Role(角色):角色命名描述实体类型的实例在该端所扮演的角色或功能的端点。它是为关联的另一端上的实体所使用的名字。在CDM中,角色名必须被显式地指定,尽管通常它将是该端的实体类型的名称。
●Type(类型):类型指定该端的实体类型的名称。例如,在OrderCustomer(订单顾客)关联中,角色为CustomerRole(顾客角色)的一端的类型是Customer(顾客)类型。OrderRole(订单角色)的类型是Order(订单)实体类型。该类型必须是实体类型(它不能是内联类型)。
●Multiplicity(多重性):多重性为关联端点指定合法基数值的范围。关系端点的基数是该关系中在该端点所涉及的实体实例的实际个数。在
OrderCustomer关联的例子中,一个Order来自唯一的Customer(顾客),且每个Order必须由一个Customer下单。因此,多重性是‘1’。此约束被捕捉为CustomerRole端上的多重性=“1”。另一方面,一个Customer可有与其相关联的无线个数的订单。OrderRole端上的多重性=“*”捕捉了这一基数约束。
典型多重性值是“0..1”(0个或1个),“1”(有且仅有1个),“*”(0或多个),以及“1..*”(1个或多个)。更一般地,多重性值可指定一个值“n”(有且仅有n个),或值的范围“n..m”(n和m之间,含n和m,其中n小于等于m)。通常一个关联的两端的多重性被一同提及,诸如1:1(1对1),1:*(1对多),*:1(多对1),以及*:*(多对多)。在以上OrderCustomer的例子中,同一顾客(具有相同的CustRef属性值)可有0个或多个订单。注意,引用完整性约束的限制语义可通过正确地设置端点上的多重性来建模。在多重性的下界是1的情形中,强制了常规的限制语义。即,对于每个订单,必须存在一个顾客。因此,除非有顾客,否则订单不能被创建;类似地,如果顾客下了订单,则该顾客不能被删除。
●Table(表):约束其中可找到类型的实例的表。这是基于引用的关联的目标所必需的,除非在目标实体类型的定义中直接指定了表。在上例中示出Order上的顾客只能在SalesData.Customers表中、而不是SalesData.BadCustomers表中找到,。指定Table=””表示该引用可引用正确类型的任何表中的实体。
●OnDelete:OnDelete属性指定当该端处的实体被删除时应该做声明。在此例中,所允许的值是:Cascade(级联)、SetNull(设空)或Restrict(限制)。在此例中,
●因为指定了Cascade,所以当Customer实体被删除时,Order实体也被删除。
●如果指定了SetNull,则当Customer实体被删除时,另一端上的Order实体的CustRef属性将被设为Null。该属性必须是可为空的。
●如果指定了Restrict,则在有Order实体与Customer实体相关联的情况下,该Customer不能被删除。
<Reference>(引用)元素指示这是基于引用的关联。此元素指定以下信息:FromRole是包含实现该关联的引用属性的角色;ToRole是作为该引用的目标的角色;而Property是引用属性的名称。
在OrderCustomer关联中,OrderRole端上的CustRef属性与CustomerRole实体的标识符相关;CustRef属性表现出外来关键字的行为。
使用非引用类型的属性的关联。以上OrderCustomer关联在顾客的标识上将订单与顾客实体类型相关。一般而言,在端点的任何属性上将两个实体类型相关是可能的。例如,考虑以下DocumentAuthor(文档作者)关联,其中Document.Author(文档.作者)属性与Contact.Name(联系人.名字)相关。因为Contact.Name不是唯一的,所以此关联可返回对应于一文档的多个联系人。
<EntityType Name=″Contact″Key=″ContactId″>
<Property Name=″ContactId″Type=″String″Nullable=″false″>
<Property Name=″Name″Type=″String″Nullable=″false″/>
</EntityType>
<EntityType Name=″Document″Key=″DocId″>
<Property Name=″DocId″Type=″String″Nullable=″false″/>
<Property Name=″Title″Type=″String″Nullable=″false″>
<Property Name=″Author″Type=″String″Nullable=″true″>
</EntityType>
<Association Name=″DocumentAuthor″>
<End Role=″DocRole″Type=″Document″Multiplicity=″*″/>
<End Role=″ContactRole″Type=″Contact″Multiplicity=″1″/>
<Condition>
DocRole.Author=ContactRole.Name
</Condition>
</Association>
此例和Customer/Order(顾客/订单)例子之间的一个差别是,不是指定<Reference>(引用)元素,而是在<Condition>(条件)元素内提供一布尔表达式。因为<Condition>可包含任意复杂程度的表达式,所以这是非常灵活的关联形式。它实际上通过将联合作为查询和编程模型的一等部分,来使在应用程序中重复使用联合变得很容易。
在仅需两个属性之间的简单等价的情形中,支持简化的句法。在此类情形中,可使用<CommonValue>(公用值)元素以取代<Condition>(条件)元素。下例和前例具有相同的意义(除了以下所述的OnUpdate行为以外)。
<Association Name=″DocumentAuthor″>
<End Role=″DocRole″Type=″Document″Multiplicity=″*″/>
<End Role=″ContactRole″Type=″Contact″Multiplicity=″1″
OnUpdate=″Cascade″/>
<CommonValue Propertyl=″DocRole.Author″
Property2=″ContactRole.Name″/>
</Association>
因为这些属性被显式地列出,并总是具有相同的值,所以有一个附加特征可用:OnUpdate属性。此属性的可能的值是:Cascade(级联)、SetNull(设空)或Restrict(限制)。在此例中,属性值“Cascade”标识如果ContactRole端上的属性被更新,则该值被传播到另一端上的该属性;如果OnUpdate=”Restrict”,则在有一实体与另一端相关联的情况下,此属性不能被改变;如果OnUpdate=”SetNull”,则在此端上的属性被更新的情况下,另一端上的该属性被设为null。
关联实体。将属性与关系相关联是很普遍的。例如,通常组织和个人之间的雇佣关系携带如EmploymentPeriod(雇佣期)等属性。Organization(组织)或Person(个人)类型的属性部分可被设立,但若没有关系,该属性没有任何意义。例如,除非被雇佣的人也存在,否则Organization上的EmploymentPeriod属性是无意义的;类似地,Person实体上的该属性也是无意义的。
在CDM中,仅实体(实体类型实例)被持久化。只有实体(实际上是实体表)是可查询的。关联和合成作为元数据被存储。因此关联上的属性必须被存储在实体中。这一实体是关联实体。这与UML中的关联类扮演相同的角色。关联实体类型类似于关系型系统中带有对其链接的实体的引用(外来关键字)的中间(链接或联合)表。关联实体的关键字一般包括对相关实体的引用。例如,考虑以下:
<EntityType Name=″Product″...>
...
</EntityType>
<EntityType Name=″Supplier″...>
...
</EntityType>
<EntityType Name=″PSLink″Key=″ProductRef,SupplierRef″...>
<Property Name=″ProductRef″Type=″Ref(Product)″
Nullable=″false″.../>
<Property Name=″SupplierRef″Type=″Ref(Supplier)″
Nullable=″false″.../>
<Property Name=″Price″Type=″Decimal″Nullable=″false″>
<Decimal Precision=″6″Scale=″2″/>
</Property>
<Property Name=″Quantity″Type=″int″Nullable=″false″/>
</EntityType>
PSLink是链接产品和供应商的实体类型。PSLink通过分别向Product(产品)和Supplier(供应商)类型指定两个引用属性ProductRef(产品引用)和SupplierRef(供应商引用)来将Product与Supplier相关。除了将产品与供应商相关,它还具有对该关系而言有意义的属性Price(价格)和Quantity(数量)。
Product、Supplier和PSLink之间可能的关联是在以下两两之间:PSLink和Product,PSLink和Supplier,以及Product和Supplier。这些关联可被显式定义如下:
<Association Name=″PSLinkProduct″>
<End Role=″PSLink″Type=″PSLink″/>
<End Role=″Product″Type=″Product″/>
<Reference FromRole=″PSLink″ToRole=″Product″
Property=″ProductRef″/>
</Association>
<Association Name=″PSLinkSupplier″>
<End Role=″PSLink″Type=″PSLink″EndProperty=″SupplierRef″/>
<End Role=″Supplier″Type=″Supplier″/>
<Reference FromRole=″PSLink″ToRole=″Supplier″
Property=″SupplierRef″/>
</Association>
<Association Name=″ProductSupplier″>
<End Role=″Product″Type=″Product″/>
<End Role=″Supplier″Type=″Supplier″/>
<Uses Role=″PSLink″Type=″PSLink″/>
<Condition>
PSLink.ProductRef=Product AND PSLink.SupplierRef=Supplier
</Condition>
</Association>
在上例中,PSLink是关联实体这一事实不是显式的,因此不能在关联的定义中使用。模式设计者必须单调乏味地定义所有必需的关联定义。但是,通过引入显式关联实体的概念作为关联定义的一个部分,这就可被避免。上例被重写为指定PSLink为以下关联实体:
<EntityType Name=″Product″...>
...
</EntityType>
<EntityType Name=″Supplier″...>
...
</EntityType>
<EntityType Name=″PSLink″Key=″ProductRef,SupplierRef″
Association=″ProductSupplier″>
<Property Name=″ProductRef″Type=″Ref(Product)″Nullable=″false″
Role=″Product″/>
<Property Name=″SuplierRef″Type=″Ref(Supplier)″Nullable=″false″
Role=″Supplier″/>
<Property Name=″Price″Type=″Decimal″Nullable=″false″>
<Decimal Precision=″6″Scale=″2″/>
</Property>
<Property Name=″Quantity″Type=″int″Nullable=″false″/>
</EntityType>
<Association Name=″ProductSupplier″>
<AssociationEntity Type=″PSLink″>
<End Role=″Link″Type=″PSLink″/>
<Reference FromRole=″Link″ToRole=″Product″
Property=″ProductRef″/>
<Reference FromRole=″Link″ToRole=″Supplier″
Property=″SupplierRef″/>
</AssociationEntity>
<End Role=″Product″Type=″Product″
OnDelete=″CascadeToAssociationEntity″/>
<End Role=″Suppier″Type=″Supplier″
OnDelete=″CascadeToAssociationEntity″/>
</Association>
注意关于此例的以下方面:
●它不只是另一个声明的缩写形式,因为它提供了关于在关联实体没有被显式调出时不能被推断的类型的信息。
●PSLink的<EntityType>(实体类型)定义上的Association(关联)属性标识此类型为关联实体,并标识使用该类型的关联。
●ProductRef和SupplierRef属性元素上的Role属性在使用这些属性的关联内部标识这些角色。
●嵌套在AssociationEntity(关联实体)内的End(端点)元素为关联实体本身所扮演的角色提供名字。在许多方面,关联实体只是多路关联的一个端点,但在其它方面它在关联中行使特殊功能。
●<Reference>(引用)元素描述关联实体如何与产品和供应商实体相关联。它们是被嵌套的,因为它们隶属于总关联。
●End元素上的OnDelete属性指示,如果任一端点被删除,则关联实体也被删除,因而关系也被删除。但是,删除一端并不引起另一端也被删除(即,删除供应商并不引起所供应的产品被删除)。此属性其它可能的值有:Cascade(级联),它将引起所有端点(包括关联实体)被删除;SetNull(设空),它将引起关联实体上的引用属性被设为null;或Restrict(限制),它将在PSLink实例存在的情况下使删除失败。
关联实体还可在使用非引用类型的属性的关联中使用。详见此文档中稍后对关联的完整描述。
界定关联范围。界定关联范围指定该关联的两端处的实体都是同一实体实例的子实体。通过在Scope(范围)属性中放置包含两端的实体类型的名称,关联即被界定范围。从而两端上的Table属性必需以该类型开始。考虑以下例子,其中Car(汽车)具有Engine(引擎)、Wheels(车轮)和DriveTrain。
<EntityType Name=″Car″Key=″Model″>
<Property Name=″Model″Type=″String″>
<Property Name=″Wheels″Type=″Array(Ref(Wheel))″/>
<Occurs Miniumum=″4″Maximum=″4″/>
</Property>
<Property Name=″Engine″Type=″Ref(Motor)″/>
<Property Name=″DriveTrain″Type=″Ref(DriveTrain)″/>
</EntityType>
<EntityType Name=″Motor″...>...</EntityType>
<EntityType Name=″Wheel″...>...</EntityType>
Engine和Wheel由DriveTrain连接。
<EntityType Name=″DriveTrain″Association=″DriveTrain″>
<Property Name=″Engine″Type=″Ref(Motor)″Role=″Engine″/>
<Property Name=″Wheels″Type=″Array(Ref(Wheel))″
Role=″Wheels″>
<Check>Count(*)=2 OR Count(*)=4</Check>
</Property>
</EntityType>
<Association Name=″DriveTrain″Scope=″Car″>
<End Role=″Engine″Type=″Motor″Table=″Car.Engine″/>
<End Role=″Wheels″Type=″Wheel″Table=″Car.Wheels″/>
<AssociationEntity Type=″DriveTrain″/>
<End Role=″DriveTrain″
Type=″DriveTrain″Table=″Car.DriveTrain″/>
<Reference FromRole=″DriveTrain″ToRole=″Engine″
Property=″Engine″/>
<Reference FromRole=″DriveTrain″ToRole=″Wheels″
Property=″Wheels″/>
</AssociationEntity>
</Association>
上例示出DriveTrain连接来自同一Car的Engine和Wheels。来自一个Car的Engine被附加到来自另一个Car的Wheels是不合法的。<End>元素上的任何Table属性必须以范围界定实体开始。<End>元素可通过添加Scoped=”false”来指示范围界定不适用于该元素。
合成。合成是定义两个实体之间的合成关系的建模概念。再次考虑Order(订单)的例子;Lines(线)属性和OrderLines(订货线)关系定义了Order和Line实体类型之间的合成。Order和Line类型之间有一种结构关系;线是订单的一个部分(或被合成在其中)。线实体属于单个订单实体;线实体是唯一的订单的一个部分;订单及其线构成操作单元。
相反,在上例中,Order和Customer是独立的实体。Orders和Customers表是相互独立的。OrderCustomer关联将订单与顾客相关。除非在关联上指定了OnDelete=Cascade,否则订单和顾客的生命期是相互独立的。OnDelete=Cascade添加了要求与顾客相关联的订单在该顾客被删除时也被删除的行为约束。但是,订单和顾客实体例行之间没有结构管理。例如,取出顾客实体并不访问任何订单,反之亦然。此外,Order可参与另一个但类似的与Supplier的关联是可能的;比如Order上有SupplierRef(供应商引用)属性,以及OrderSupplier(订单供应商)关联。此关联还可指定OnDelete=”Cascade”,这意味着Order的生命期或受下该订单的顾客控制,或由供应该订单的供应商控制。但是,Order与Customer或者Order与Supplier不构成如复制、移动、备份、恢复等操作的操作单元。
<EntityType Name=″Order″...>
<Property Name=″Lines″Type=″Table(OrderLine)″
Compos ition=″OrderLines″/>
...
</EntityType>
<EntityType Name=″OrderLine″...>
...
</EntityType>
<Composition Name=″OrderLines″>
<ParentEnd Role=″ParentOrder″Type=″Order″EndProperty=″Lines″/>
<ChildEnd Role=″LineItems″Type=″OrderLine″Multiplicity=″*″/>
</Composition>
尽管合成的确是关联概念进一步的特殊化,但是它是基础概念,特别是从结构和操作的角度来看。Order和Lines之间的关系与Order和Customer之间的关系非常不同。因此,在CDM中,合成是独特的、顶层的概念。
合成和关联实体。关联实体的一种特定用途将该关联实体本身合成到相关联的实体里的一个中。考虑下例:
<EntityType Name=″Item″...>
<Property Name=″Links″Type=″Table(Link)″
Association=″ItemLinkRelation″/>
...
</EntityType>
<EntityType Name=″Link″Association=″ItemLinkRelation″...>
<Property Name=″Target″Type=″Ref(Item)″Role=″Target″/>
...
</EntityType>
<Association Name=″ItemLinkRelation″>
<AssociationEntity Type=″Link″/>
<End Role=″Link″Type=″PSLink″/>
<Composition ParentRole=″Source″ChildRole=″Link″
Property=″Links″/>
<Reference FromRole=″Link″ToRole=″Target″Property=″Target″/>
</AssociationEntity>
<End Role=″Source″Type=″Item″/>
<End Role=″Target″Type=″Item″/>
</Association>
这里我们有一实体类型Item(项目),它包含Link(链接)实体类型的嵌套表。Link类型本身是关联实体,因为它处于两个相关实体(在本例中是两个项目)之间,并包含关系专属的属性。合成是将Item和Link相关这一事实并不改变正被建模的真实关系是在两个Item之间这一事实。
导航。将关系显式地建模的好处之一是使用关系定义从一个实体导航到相关实体的能力。可仅有对CDM的查询或通过使用从实体类型和关系定义生成的API类来支持此类导航。在OrderCustomer例子中,给定一个订单实体,就可使用CustRef属性和关联定义导航到其顾客。关联定义还可被用来从顾客导航到其订单。关联元数据可被用来生成基于联合的查询,以从顾客遍历到订单。类似地,在DocumentAuthor关联中,可被用来生成从文档到联系人的导航,反之亦然。
在CDM中,使用关系定义来预定义基于关联的导航属性是可能的。此类导航属性的一个示例如下所示:
<EntityType Name=″Customer″...>
<NavigationProperty Name=″Orders″Association=″OrderCustomer″
FromRole=″Customer″ToRole=″Order″/>
...
</EntityType>
<EntityType Name=″Order″...>
<Property Name=″CustRef″Type=″Ref(Customer)″Nullable=″false″
Association=″OrderCustomer″/>
...
</EntityType>
<Association Name=″OrderCustomer″>
<End Role=″OrderRole″Type=″Order″Multiplicity=″*″/>
<End Role=″CustomerRole″Type=″Customer″OnDelete=″Cascade″
Multiplicity=″1″/>
<Reference FromRole=″OrderRole″ToRole=″CustomerRole″
Property=″CustRef″/>
</Association>
Customer(顾客)实体中的NavigationProperty(导航属性)元素指定从一个(或多个)顾客到与该一个(或多个)顾客相关联的订单的导航路径。此属性可在查询和编程模型中被表示为虚拟的(非物质化的)和可查询的对Order(订单)实体的引用的只读集合。
以下是对CDM模式语言的描述。所有实体、关系和表集定义都在模式的上下文中出现。模式定义了界定在该模式内所定义的事物的名字的范围的名字空间。<Schema>(模式)元素是模式文档的根元素。<Schema>元素可具有以下属性:
●Namespace(名字空间)-必需。该模式的唯一名字空间。该名字空间复合CLR中名字空间名的规则。此外,为CLR名字空间定义的名字空间命名方针也应被遵守。通过遵守这些协定,在选择名字空间名时对唯一性就有了合理的保证。
例如:
<Schema Namespace=″MyCompany.MySchema″>
</Schema>
模式可使用完全限定的类型名(名字空间名.类型名)来引用在不同模式中定义的类型。例如:
<Schema Namespace=″MyCompany.MySchema″>
<InlineType Name=″MyType″
BaseType=″YourCompany.YourSchema.YourType″...>
...
</InlineType>
</Schema>
模式可包括<Using>(使用)元素以将在外部模式中定义的类型名带入到范围中。<Using>元素可具有以下属性:
●Namespace(名字空间)-必需。其内容被带入到范围中的模式的名字空间。
●Alias(别名)-可选。可被用作该名字空间的替代的名字。
例如:
<Schema Namespace=″MyCompany.MySchema″>
<Using Namespace=″YourCompany.YourSchema″/>
<Using Namespace=″AnotherCompany.AnotherSchema″Alias=″Another″/>
<InlineType Name=″Typel″BaseType=″YourType″>
...
</InlineType>
<InlineType Name=″Type2″BaseType=″Another.AnotherType″>
...
</InlineType>
</Schema>
命名规则。所类型化、关系、以及表集名都必需复合CLR中类型名的规则。这些名字还应.Net框架类型命名方针。类型和关系名应是唯一的。即,类型和关系不能具有相同的完全限定名称,且任何两种类型或两个关系都不能具有相同的完全限定名称。所有表集名都应是唯一的(没有任何两个表集可具有相同的完全限定名称),但表集可与类型或关系具有相同的名称。
简单类型。简单类型表示不带在数据模型中可见的任何内部结构的单个值。在CDM中,CLR值类型被作为简单类型使用。CLR的系统中所定义的许多值类型,System.Storage(系统.存储)、以及System.Data.SqlTypes(系统.数据.Sql类型)名字空间被本机地支持以供在数据模型中使用。这些类型是:
System.Data.SqlTypes.SqlString System.String System.Storage.ByteCollection
System.Data.SqlTypes.SqlBinary System.Boolean System.Storage.StorageStreamReference
System.Data.SqlTypes.SqlBoolean System.Byte System.Storage.StorageXmlReference
System.Data.SqlTypes.SqlByte System.Int16
System.Data.SqlTypes.SqlInt16 System.Int32
System.Data.SqlTypes.SqlInt32 System.Int64
System.Data.SqlTypes.SqlInt64 System.Single
System.Data.SqlTypes.SqlSingle System.Double
System.Data.SqlTypes.SqlDouble System.Decimal
System.Data.SqlTypes.SqlDecimal System.DateTime
System.Data.SqlTypes.SqlDateTime System.Guid
System.Data.SqlTypes.SqlGuid System.Uri
等等 System.TimeSpan
满足一组要求的任何值类型在本数据模型中也应能作为简单类型使用。这一类型需要满足的条件将或允许其在查询中被直接存储和使用(诸如UDT),或将经由CLR属性提供为提供存储和查询映射所需的元数据。
简单类型约束。使用以下所定义的约束元素之一来约束简单类型的值是可能的。这些元素可被嵌套在引用简单类型的各个元素内(例如,<EntityType>(实体类型)或<InlineType>(内联类型)元素中的<Property>(属性)元素)。
长度。可将<Length>(长度)约束元素应用于System.String(系统.串)、System.Storage.ByCollection和System.Data.SqlTypes.String类型来约束值的长度。此元素可包含以下属性:
●Minimum(最小)-该值的最小长度。默认值为0。
●Maximum(最大)-该值的最大长度。值“unbounded”(无限的)表示没有指定的最大长度。默认值是“unbounded”。
为与基类型中指定的约束一致,对Minimum所指定的值必需等于或大于先前的值,而对Maximum所指定的值必需等于或小于先前的值。
小数。<Decimal>(小数)约束元素可被应用于System.Decimal(系统.小数)和System.SqlDecimal(系统.Sql小数)类型以约束可接收的值的精度和范围。此元素可包含Precision(精度)和Scale(范围)属性。
默认。<Default>(默认)约束元素可被应用于任何简单类型以指定对一属性使用的默认值。此元素可具有以下属性:Value(值)-必需。该属性的默认值。此属性的值必须是可转换为正确类型的值的。注意,<Default>元素并不实际指定约束。任何值都是与基类型中所指定的值一致的。
校验。<Check>(校验)约束元素可包含布尔查询表达式。要使属性值有效,则此表达式的值必须为真。该表达式不应有任何副作用。当在基类型和派生类型两者中都指定了校验约束时,两个约束都生效。
枚举类型。枚举类型定义表示唯一值的名字集。底层值的类型,而不是被存储的值本身,在CDM中是可见的。当使用自定义存储映射时,底层类型由此映射定义。对于排斥性的存储,底层类型将被自动选择,或可经由存储专属的提示来提供。枚举类型是使用<EnumerationType>(枚举类型)元素来声明的。此元素可具有以下属性:
●Name(名字)-必需。该枚举类型的名字。
●Extensible(可扩展)-可选。值“真“表示该枚举类型可使用
<EnumerationExtension>(枚举扩展)元素(见下)来扩展。值“假”表示不允许任何扩展。默认值是“假”。
<EnumerationType>元素可包含0个或多个<EnumerationMember>(枚举成员)元素。这些元素可具有以下属性:
●Name(名字)-必需。用来表示特定枚举值的名字。此名字在声明<EnumerationType>元素内必须是唯一的。当引用枚举成员时,此名字总是由枚举类型名限定。
●AliasesMember(别名成员)-可选。包含另一个枚举成员的名字。表示此枚举成员是指定成员的别名(例如,两个名字都表示相同的值)。以下定义了一示例性枚举:
<Schema Name=″MyCompany.MySchema″>
<EnumerationType Name=″A″>
<EnumerationMember Name=″P″/>
<EnumerationMember Name=″Q″/>
<EnumerationMember Name=″R″AliasesMember=″Q″/>
</EnumerationType>
</Schema>
注意,“置位标志”样式枚举不能使用枚举类型来描述。必须改为使用枚举类型的数组。
可扩展枚举。当<EnumerationType>元素指定Extensible=”true”时,就能以附加值来扩展该枚举。枚举类型的属性可包含<EnumerationType>中或该类型的任何扩展中所指定的任何值。
每个扩展中所定义的值与在基枚举类型及所有其它扩展中所定义的值是截然不同的。这允许枚举类型被多个开发者独立扩展而没有冲突的可能。
枚举扩展是使用<EnumerationExtensionType>(枚举扩展类型)元素来定义的。此元素可具有以下属性:
●Name(名字)-必需。该枚举扩展类型的名字。
●ExtendsType(扩展类型)-必需。正被扩展的枚举类型的名字。
<EnumerationExtensionType>元素可包含0个或多个<EnumerationMember>(枚举成员)元素。这些元素可具有以下属性。
●Name(名字)-必需。用来表示特定枚举值的名字。此名字在声明<EnumerationExtensionType>元素内必须是唯一的。
但是该名字可复制已扩展枚举类型中的名字。在此类情形中,扩展中所定义的值仍然和已扩展枚举中所定义的值截然不同。
当引用枚举成员时,此名字总是由枚举扩展的类型名限定。
●AliasesMember(别名成员)-可选。包含此扩展中、对同一枚举类型的另一扩展中、或已扩展枚举类型本身中的另一个枚举成员的全名(枚举类型名.枚举成员名)。表示此枚举成员是指定成员的别名(例如,两个名字表示相同的值)。
以下定义一示例性枚举:
<Schema Name=″MyCompany.MySchema″>
<!--
枚举类型C与扩展类型D和E的合成定义以下可被存储在类型C的属性中的不同值:C.P,C.Q,D.Q,D.S,E.T和E.U。枚举成员C.R,D.T和E.U都是C.Q的别名,因此不表示唯一值。
-->
<EnumerationType Name=″C″Extensible=″true″>
<EnumerationMember Name=″P″/>
<EnumerationMember Name=″Q″/>
<EnumerationMember Name=″R″AliasesMember=″Q″/>
</EnumerationType>
<EnumerationExtensionType Name=″D″ExtendsType=″C″>
<EnumerationMember Name=″Q″/>
<EnumerationMember Name=″S″/>
<EnumerationMember Name=″T″AliasesMember=″C.R″/>
</EumerationExtension>
<EnumerationExtension Name=″E″ExtendsType=″C″>
<EnumerationMember Name=″T″/>
<EnumerationMember Name=″U″AliasesMember=″D.T″/>
</EnumerationExtension>
</Schema>
数组类型。数组类型的实例可存储指定的简单类型、内联类型、枚举类型、实体引用类型、或表引用类型的多个实例(不允许数组的数组)。这些实例是该数组的元素。这些元素的顺序被保持,并由应用程序显式地维护。应用程序可将元素插入数组中,以及将元素从数组中删除。数组类型使用以下句法来指定:
Array(element-type)
其中element-type(元素类型)是该元素的类型的名称。
数组类型约束。使用以下定义的约束元素之一来约束数组类型的值是可能的。这些元素可被嵌套在引用数组类型(例如,<EntityType>或<InlineType>元素中的<Property>元素)的各种元素内。
元素约束。<ElementConstraint>(元素约束)约束元素可被用来对数组中的元素设置约束。可在<ElementConstraint>元素中指定对元素类型有效的任何约束元素。
出现。<Occurs>(出现)约束元素可被用来约束数组中的元素的个数。此元素可具有以下属性:
●Minimum(最小)-可选。指定该数组中条目的最小个数。默认值为0。
●Maximum(最大)-可选。指定该数组中条目的最大个数。值“unbounded”(无限)意味着没有任何约束。默认值为“unbounded”。
为与基类型中指定的约束一致,为Minimum指定的值必须等于或大于先前的值,而为Maximum指定的值必须等于或小于先前的值。
唯一。<Unique>(唯一)约束元素可被用来指定必须在数组中包含唯一值的元素类型的一个或多个属性。此元素可具有以下属性:Properties(属性)-必需。逗号分隔的元素属性名列表。
校验。<Check>(校验)约束元素包含布尔查询表达式。要使属性值有效,则此表达式的值必须为真。该表达式不应有任何副作用。当在基类型和派生类型两者中都指定了校验约束时,两个约束都生效。注意,对数组属性的校验约束适用于整个属性。例如,它可被用来校验元素属性的和是否小于某个限制。或者,放在<ElementConstraint>(元素约束)元素内的校验约束可个别地应用于每个值。
表类型。表类型的实例可存储指定实体类型的实例的无序集合。所指定的实体类型,或在其基类型分层结构中的类型必需指定关键字属性。注意,这并不意味着该实体类型不可以是抽象类型。存储在嵌套表中的实体类型的关键字属性在任何表实例中必须是唯一的。表可持有指定类型、或从该类型派生的类型的任何实体。应用程序可将实体插入到表,以及将实体从表中移除。表类型使用以下句法来指定:
Table(entity-type)
实体类型(且仅实体类型)可定义表类型的属性。这些属性表示嵌套表。嵌套表定义依存于包含实体的实例存储位置。存储在嵌套表中的实体被视为是该包含实体所定义的数据的内聚单元的一部分(例如,当包含实体被删除时,它们也被删除)。但是,除非使用事务经由应用程序显式地管理,否则在对包含实体和被包含实体的改变上没有任何一致性保证。定义递归表是错误的。即,实体不可定义其类型、其超类型或其子类型的表,实体也不能定义具有其类型的表的某种其它实体类型的表。表类型的属性定义两个实体(具有该属性的父实体和被包含在该表中的子实体)之间的合成关系。
实体引用类型。引用类型的实例存储对指定类型的实体的引用。引用封装对包含该实体及该实体的关键字属性值的表的引用。引用可被解析到作为该引用的目标的实体。引用类型使用以下句法来指定:
Ref(entity-type)实体和内联类型可定义引用类型的属性。引用类型的属性定义两个实体(具有该属性的源实体和被该属性引用的目标实体)之间的关联关系。
表引用类型。表引用类型的实例存储对表的引用。目标表可以是表集或嵌套表中的“顶层”表。引用可被解析到作为该引用的目标的表。表引用类型使用以下句法来指定:
TableRef(entity-type)
实体和内联类型可定义引用类型的属性。
属性。在实体和内联类型中使用属性来分配存储。属性是使用<Property>(属性)元素来定义的。除了以上所定义的公用成员元素以外,此元素还可具有以下属性:
●Name(名字)-必需。该成员的名字。该名字在定义类型的范围中必须是唯一的。该名字必须遵守CLR中类成员名规则,并应遵守.Net框架命名方针。
●DuplicateName(重复名字)-可选。成员名还必须在基类型分层结构上是唯一的,除非提供了DuplicateName属性且其有值为“true”(真)。默认值“false”(假)值表示预期该成员名是唯一的。
此属性的职责是a)记录一成员名复制基类型中的一个属性这一事实,以及b)强制模式设计者有目的地选择复制名字(即,它起到和C#中的new关键字相同的作用)。
●Type(类型)-必需。该属性的类型。这可以是任何简单、内联、数组、实体引用、或表引用类型。对于实体中所定义的属性,也允许表类型。
●Nullable(可为空)-为除数组和嵌套表以外的所类型化的属性所必需,对于具有数组和嵌套表类型的属性是不允许的。“true”值意味着该属性可存储null值。“false”值意味着该属性不能存储null值。
●Association(关联)-在属性类型是ref或ref类型的数组的情况下是必需的。指定此属性参与其中的关联的名字。详见关联。
●Composition(合成)-在属性类型是表类型的情况下是必需的。指定此属性参与其中的关联或合成的名字。详见合成。
●Role(角色)-指定此属性参与其中的关联的角色。对此属性何时为必需的描述见关联一节。
以下示出一些示例性属性定义:
<Schema Namespace=″MyCompany.MySchema″>
<Using Namespace=″System″/>
<InlineType Name=″A″>
<Property Name=″One″Type=″Int32″/>
</InlineType>
<InlineType Name=″B″BaseType=″A″>
<Property Name=″One″Type=″String″DuplicateName=″true″/>
<Property Name=″Two″Type=″Int32″/>
</InlineType>
</Schema>
属性约束。可被存储在属性中的值可在<Property>元素内使用约束元素来约束。所允许的约束元素的集合依存于该属性的类型,并可被定义为所讨论的每一种类型。此外,在派生类型中,还可通过在<PropertyConstraint>元素内放置约束元素来进一步约束属性。此元素可具有以下属性:
●Property(属性)-必需。被约束的属性的名字。在存在复制属性名的情形中,此名字可使用类型名来限定。如果该名字被复制且没有被限定,则在大多数派生类中假定该属性。
●Type(类型)-可选。将该属性约束到的类型。仅当属性的原始类型是Array(T)、Table(T)、Ref(T)、或TableRef(T)时可指定类型。在此类情形中,新类型分别必须是Array(S)、Table(S)、Ref(S)、或TableRef(S),且S必须是T的子类型。
当使用<PropertyConstraint>元素时,所指定的约束必须遇基类型上所定义的任何约束一致。对每个约束元素的描述包括对伴随什么一致性的定义。以下示出一些简单的例子:
<Schema Namespace=″MyCompany.MySchema″>
<Using Namespace=″System″/>
<InlineType Name=″A″>
<Property Name=″X″Type=″Int32″>
<Range Miniumum=″10″Maximum=″1000″/>
</Property>
<Property Name=″Y″Type=″String″>
<Length Maximum=″100″/>
</Property>
</InlineType>
<InlineType Name=″B″BaseType=″A″>
<PropertyConstraint Property=″Y″>
<Length Maximum=″50″/>
</PropertyConstraint>
</InlineType>
</Schema>
约束目标类型。当从具有引用属性的类型派生一类型时,进一步约束可被指定的实体的类型是可能的。这是在<PropertyConstraint>元素内使用该元素、并如本文中所述地为Type属性指定值来实现的。例如:
<Schema Namespace=″MyCompany.MySchema>
<EntityType Name=″A″Key=″ID″>
<Property Name=″ID″Type=″Int32″/>
</EntityType>
<EntityType Name=″B″BaseType=″A″>
</EntityType>
<InlineType Name=″C″>
<Property Name=″ARef″Type=″Ref(A)″/>
</InlineType>
<InlineType Name=″D″BaseType=″C″>
<PropertyConstraint Property=″ARef″Type=″Ref(B)″/>
</InlineType>
</Schema>
经计算的属性。在实体和内联类型中使用经计算的属性来表示经计算的而没有被存储的值。用来计算该属性的值的算法不被视为本数据模型的一个部分。可描述返回查询的属性作为本数据模型的一个部分。经计算的属性是使用<ComputedProperty>(经计算的属性)元素来声明的。除了以上所定义的公用成员属性以外,此元素还可具有以下属性:
●ReadOnly(只读)-可选。指示该属性是否为只读。默认值是“true”,意味着该属性是只读的,并且不能在更新中使用。
●Static(静态)-可选。指示该属性是静态属性还是实例属性。默认值是“false”,表示这是实例属性。
以下示例声明一类型为“Int32”的名为“X”的经计算的属性:
<Schema Namespace=″MyCompany.MySchema″>
<InlineType Name=″A″>
<ComputedProperty Name=″X″Type=″Int32″/>
</InlineType>
</Schema>
经计算的属性约束。可被存储在属性中的值可在<ComputedProperty>(经计算的属性)元素内使用约束元素来约束。所允许的约束元素集依存于该属性的类型,并被定义为所讨论的每一种类型。在一个实现中,<PropertyConstraint>元素还可用于经计算的属性。
方法。在内联和实体类型上使用方法来表示可被执行的操作。用来实现方法的算法不被视为本数据模型的一个部分。在一个实现中,可描述一种取一查询作为输入、并返回一查询作为输出的方法作为本数据模型的一个部分。关联在本质上定义此类方法。方法是使用<Method>(方法)元素来声明的。此元素可具有以下属性:
●Name(名字)-可选。该成员的名字。该名字在定义类型的范围中必须是唯一的。该名字必须遵守CLR中类成员名的规则,并应遵守.Net框架命名方针。
●DuplicateName(复制名字)-可选。成员名字在基类型分层结构上也必须是唯一的,除非提供了DuplicateName属性且有值为“true”。默认值“false”值指示预期该成员名是唯一的。
此属性的职责是a)记录一成员名复制基类型中的一个属性这一事实,以及b)强制模式设计者有目的地选择复制名字(即,它起到和C#中的new关键字相同的作用)。
●RetumType(返回类型)-必需。该方法所返回的值的类型。这可以是简单、内联、数组、实体引用、表引用、或表类型,或者它可以是指示不返回任何值的空串。
●Static(静态)-可选。指示该方法是静态还是示例方法。默认值是“false”,指示这是一示例方法。
●Association(关联)在返回类型是ref或ref类型的数组的情况下为必需。指定此方法参与其间的关联的名字。详见关联一节。
●Composition(合成)-在返回值是表类型的情况下为必需。指定此方法参与其间的关联或合成的名字。详见合成一节。
●Role(角色)-指定此方法参与其间的关联的角色。对此属性何时为必需的
描述见关联一节。
<ReturnTypeConstraints>(返回类型约束)元素可被嵌套在<Method>(方法)元素内。应用于该方法的返回类型的约束元素可被嵌套在<ReturnTypeConstraints>元素内。<Method>元素可具有0个或多个嵌套的<Parameter>(参数)元素以指定该方法所接受的参数。<Parameter>元素可具有以下属性:
●Name(名字)-必需。该参数的名字。
●Type(类型)-必需。该参数的类型。
●Out(输出)-可选。如果这是输出参数则值为“true”,如果这是输入参数则值为默认值“false”。
应用于参数类型的约束元素可被嵌套在<Parameter>元素内。下例声明了类型为“Int32”的名为“X”的经计算的属性,以及带类型化为“Int32”的名为“a”的参数并返回类型为“Int32”的值的名为“Y”的方法。
<Schema Namespace=″MyCompany.MySchema″>
<InlineType Name=″Foo″>
<Method Name=″Y″Type=″Int32″>
<Parameter Name=″a″Type=″String″>
<Length Maximum=″100″/>
</Parameter>
</Method>
</InlineType>
</Schema>
内联类型。内联类型的示例只可被持久化为唯一的实体实例的组件内联类型的实例没有任何显式的标识(标识在其如何被定位在其包含实体内方面是隐式的)内联类型的实例被视为是由包含实体所定义的数据的内聚单元的一个部分(例如,当包含实体被删除时它们也被删除)。还保证所有是一实体的一个部分的内联数据上的一致性将被维持而无需任何显式的应用程序动作。注意,这并不排除如WinFS变化单元和同步等特征向模式设计者提供对一致性粒度更细的控制。
模式设计者可定义具有由属性集组成的结构的新的内联类型。这一内联类型可以从单个基内联类型派生。这些类型是在<Schema>(模式)元素内使用<InlineType>(内联类型)元素来定义的(不允许嵌套的内联类型)。<InlineType>元素可具有以下属性:
●Name(名字)-必需。指定该类型的名字。
●BaseType(基类型)-可选。定义此类型是其子类型的内联类型。如果没有任何基类型被指定,则不定义任何属性的匿名抽象基类型被假定。
●Abstract(抽象)-可选。如果该类型是抽象的则为“true”,如果它是具体的则为“false”只有非抽象类型的实例才可被创建。默认值是“false”。
●Sealed(密封的)-可选。如果该类型是密封的则为“true”,如果不是则为“false”,或者如果仅在定义模式外部的使用中是密封的则为“external”。默认值是“false”。
●FriendSchemas(友元模式)-可选。逗号分隔的被视为是该定义类型的“友元”的模式名字空间列表。这些模式不受到Sealed=”external”属性值所强加的限制(但是它们受到Sealed=”true”的限制)。
一些示例性内联类型定义有:
<Schema Namespace=″MyCompany.MySchema″>
<InlineType Name=″A″Abstract=″true″>
<Property Name=″One″Type=″Int32″/>
</InlineType>
<InlineType Name=″B″BaseType=″A″>
<Property Name=″Two″Type=″Int32″/>
</InlineType>
<InlineType Name=″C″BaseType=″B″>
<Property Name=″Three″Type=″Int32″/>
</InlineType>
</Schema>
图10示出上述内联类型中的一部分的UML表示1100。
内联类型约束。内联类型的实例可使用以下约束元素来约束。这些元素可被嵌套在引用内联类型的各种元素内(例如,<EntityType>或<InlineType>元素中的<Property>元素)。
校验。<Check>(校验)约束元素可包含布尔查询表达式。要使该属性值有效,则此表达式的值为真。该表达式不应有任何副作用。当在基类型和派生类型两者中都指定了校验约束,则两个约束都生效。
实体类型。实体类型定义数据的内聚单元。实体类型的实例可被持久化在唯一的表中。实体类型的实例具有显式的标识。使用引用类型来存储对实体类型实例的持久引用是可能的。
模式设计者可定义具有由属性集组成的结构的新的实体类型。实体类型可以从单个基实体类型派生。这些类型是在<Schema>元素内使用<EntityType>元素来声明的(不允许嵌套的实体类型)。<EntityType>元素可具有以下属性:
●Name(名字)-必需。指定该类型的名字。该名字在封闭模式中定义的所类型化名(内联和实体类型名两者)中间必须是唯一的。
●BaseType(基类型)-可选。定义此类型是其子类型的内联类型。如果没有任何基类型被指定,则不定义任何属性的匿名抽象基类型被假定。
●Abstract(抽象)-可选。如果该类型是抽象的则为“true”,如果它是具体的则为“false”只有非抽象类型的实例才可被创建。默认值是“false”。
●Sealed(密封的)-可选。如果该类型是密封的则为“true”,如果不是则为“false”,或者如果仅在定义模式外部的使用中是密封的则为“external”。默认值是“false”。
●FriendSchemas(友元模式)-可选。逗号分隔的被视为是该定义类型的“友元”的模式名字空间列表。这些模式不受到Sealed=”true”或Sealed=”external”属性值所强加的限制(但是它们受到Sealed=”true”的限制)。
●Table(表)-可选。使用句法实体类型名.表属性名来指定将包含此实体类型的实例的唯一的顶层或嵌套表。默认是可定义任意个数的表来包含该实例类型的实例。
●Extensible(可扩展的)-可选。默认值“true”值指示该实体可使用如下所描述的<EntityExtensionType>(实体扩展类型)元素来扩展。“false”值指示该实体不能被扩展。
●Association(关联)-如果该实体在一关联定义中具有关联实体的角色,则此属性是必需的,并且必须指定该关联的名字。否则此属性不能呈示。
●Key(关键字)-逗号分隔的该实体类型或基类型中所定义的一个或多个属性的名字的列表。实体类型分层结构中只有一种类型能够指定Key属性。该类型的基类型分层结构中的所类型化都必须是抽象类型。所指定的属性必须取自该类型或其基类型。所指定的属性建立该属性的标识的一部分。标识的其余部分是隐式地取自该实体的父实体(例如,定义子实体驻留在其中的表属性的实体实例)。只有内联非可为空类型的属性,除了数组以外,可以被指定为关键字属性。如果该属性属于用户定义的内联类型,则此类型的所有属性都被视为关键字属性,且所有都必须是单值和非可为空的。嵌套属性(复合类型的属性的属性)也可被指定为关键字属性。
一些示例性实体类型定义有:
<Schema Namespace=″MyCompany.MySchema″>
<EntityType Name=″A″Abstract=″true″>
<Property Name=″One″Type=″Int32″/>
</EntityType>
<EntityType Name=″B″BaseType=″A″Key=″Two″>
<Property Name=″Two″Type=″Int32″/>
</EntityType>
<EntityType Name=″C″BaseType=″B″>
<Property Name=″Three″Type=″Int32″/>
</EntityType>
<InlineType Name=″D″>
<Property Name=″X″Type=″Int32″/>
<Property Name=″Y″Type=″Int32″/>
</InlineType>
<EntityType Name=″E″Key=″D″>
<Property Name=″D″Type=″D″/>
</EntityType>
<EntityType Name=″F″Key=″D.X″>
<Property Name=″D″Type=″D″/>
</EntityType>
</Schema>
图11示出上述实体类型1100中的一部分的UML表示。
实体类型约束。实体类型的实例可使用以下约束元素来约束。这些元素可被嵌套在引用实体类型的各种元素内(例如,<EntityType>元素中的<Property>元素)。
校验。<Check>(校验)约束元素可包含布尔查询表达式。要使该属性值为真,则此表达式的值为真。该表达式不应有任何副作用。当在基类型和派生类型两者中都指定校验约束时,两个约束都生效。
实体扩展类型。为解决WinFS和MBF的情形,必须要能够在实际上不修改在其中定义了给定类型集的模式的前提下扩展那些类型。尽管可通过采用许多模式(诸如提供具有扩展实体类型的表的基类等)中的一种来实现此目的,但是令这一概念称为本数据模型的一等部分是合乎需要的。这允许为扩展生成特殊的API模式,并且对类型设计者而言更易理解和使用。
指定Extensible=”true”的实体类型可被扩展。实体扩展是在<Schema>(模式)元素中使用<EntityExtensionType>(实体扩展类型)元素来声明的。<EntityExtensionType>元素可具有以下属性:
●Name(名字)-必需。该扩展类型的名字。
●ExtensType(扩展类型)-必需。正被扩展的实体类型的名字。
●InstanceManagement(实例管理)-必需。值“Implicit”(隐式的)指示该扩展的实例是被隐式地添加到被扩展的实体,和从被扩展的实体隐式地移除的。值“Explicit”(显式的)指示该扩展的实例必须由应用程序显式地添加和移除。
●Table(表)-可选。指定将扩展存储在其中的表。
从一种扩展类型派生另一种扩展类型也许是不可能的。<EntityExtensionType>元素可包含可被方在<EntityType>元素内的任何元素。通常这包括<Property>元素。属性名在所有扩展上或甚至在被扩展的类型的属性上不必是唯一的。如果InstanceManagement=”Implicit”,则扩展中所定义的所有属性必须或是可为空的,或是指定默认值,或是具有最小出现约束为0的数组、集合或表类型。注意,单元素内联类型的属性不能指定默认值,因此必须是可为空的。这允许对扩展执行查询,就好像它总是存在的。
如果InstanceManagement=”Explicit”,则应用程序使用在CDM的查询语言中定义的操作来将扩展显式地添加到实体实例中,或从中显式地移除扩展。还提供了一种测试扩展的存在的手段。实体扩展实例被视为是由包含实体所定义的数据的内聚单元的一个部分(即,当包含实体被删除时它们也被删除)。但是,除非使用事务经由应用程序显式地管理,否则在对实体和扩展的改变上没有任何一致性保证。
所有EntityExtension(实体扩展)都具类型化为Ref(T)的名为“Entity”(实体)的默认属性,其中T是ExtendsType(扩展类型)的值,它指向该扩展与之相关联的实体实例。以下示出一示例性实体类型和扩展。
<Schema Namespace=″MyCompany.MySchema″>
<EntityType Name=″A″Key=″ID″>
<Property Name=″ID″Type=″Int32″/>
<Property Name=″X″Type=″Int32″/>
</EntityType>
<EntityExtension Name=″B″ExtendsType=″A″
InstanceManagement=″Implicit″>
<Property Name=″X″Type=″String″/>
<Property Name=″Y″Type=″Int32″/>
</EntityExtension>
</Schema>
关联。关联允许两个或多个实体——端点实体被相关。每个端点保持与其它端点概念上的独立。关联是使用<Association>(关联)元素来表示的。此元素可具有以下属性:
●Name(名字)-必需。该关联的名字。
●Scope(范围)-可选。指定实体类型名。该关联的范围被界定到指定类型的实体的实例,且可相对于实例检查其有效性。
<Association>元素具有两个或多个嵌套的<End>(端点)元素,其中每一个描述该关联的端点中的一个。注意,仅在也指定了<AssociationEntity>(关联实体)元素的情况下才可指定两个以上<End>元素。<End>元素可具有以下属性:
●Role(角色)-必需。此端点在该关联中所扮演的角色的名字。
●PluralRole(复数角色)-可选。提供角色名的复数形式。此名字在查询模型和正则对象映射中使用。如果未被指定,则使用roleEntities(角色实体)形式的名字来代替。
●Type(类型)-必需。该端点所表示的实体的类型。
●Multiplicity(多重性)-可选。关联的此端点的多重性,它对基数设置了下下界和上界。它被指定为<下界>..<上界>形式的整数范围,或在下界与上界相同的情况下被指定为单个整数。上界可以是“*”,它指示无限。单个“*”与“0..*”同义。默认值以及关于那些默认值是否能被覆盖的规则是取决于关联的样式。
■引用:引用方为“*”,被引用方为“0..1”
■合成:父方为“1”(固定),子方为“*”
■条件和公用值:两方都为“*”(固定)
■关联实体:两方都为“*”
大于1的多重性是合法的,但出于实施目的可被当作*。
●Table(表)-对于基于参考的关联为必须,否则为可选。指定由Type或Type的祖先类型之一所指定的实体类型的表属性。该端点被约束为使相关联的实体出现在指定的表中。该句法指定以实体类型开始并以正确类型的表属性结束的路径。该路径的每个片段以两种方式中的一种解析到实体类型。
a.它指定该实体类型上的引用或表属性(任一者都解析到底层的实体类型)。此句法为以下形式:<实体类型>/<属性名>。如果使用了引用
属性,则对应的关联端点必须已指定了表名。
b.它指定关联或合成上的角色(任一者都解析到该端点的类型)。此句
法为以下形式:<实体类型>/<关系名>.<角色名>。如果使用了关联,
则由该角色名指定的端点必须已指定了表名。在基于引用的关联上可以是“”,这指示该引用可在正确类型的任何表中。如果指定了Scope(范围)属性,则该路径必须以所指示的实体类型开始。如果在Type的定义上指定了Table(表)属性,则此路径必须与其一致。
●Scoped(范围已界定)-可选。指示此端点的范围是否已被界定到<Association>元素上的Scope(范围)属性中所指示的实体的实例。默认值为真。
●OnDelete-可选。指定在该角色中的实体被删除时要采取的行动。仅可在此端点在<Reference>(引用)或<CommonValue>(公用值)元素中被列出时被指定。可能的值有:
●Restrict(限制)-防止该实体被删除。这是默认值。
●Cascade(级联)-使另一端点角色中的实体被删除。
●CascadeToAssociationEntity(级联到关联实体)-仅使关联实体被删除。
●SetNull(设空)-使关联的另一端上的属性被设为null。在该属性是引
用集合的情形中,引用被从该集合中移除。关联的另一端上的多重性的下界必须为0。仅当此端点在<CommonValue>元素的属性中的一个或<Reference>元素的ToRole中被列出是是可指定的。
●OnUpdate-可选。指定在该端点角色中的实体的公用值属性被更新时要采取的行动。仅可在此端点在<CommonValue>元素中被列出时被指定。如果OnUpdate没有被指定,则在一端上更新该属性对另一端上的该属性没有作用。可能的值有:
●Restrict(限制)-防止该实体被更新。
●Cascade(级联)-使另一端点角色中的实体的公用值属性被更新为同一值。
●SetNull(设空)-使关联的另一端点角色中的实体的公用值属性被设为null。该关联的另一端上的多重性的下界必须为0。
关联样式。关联的样式指定端点被如何连接。每个关联是4种样式中的一种,这由在<Association>元素下嵌套以下元素中的一个来指示。
●<Reference>(引用)-使用两个端点中的一个上的引用属性连接这两个端点。
●<Condition>(条件)-通过两个端点上的任一联合来连接这两个端点。
●<CommonValue>(公用值)-通过来自每个端点的同一个属性上的等同联合连接这两个端点。
●<AssociationEntity>(关联实体)一使用另一个实体连接两个或多个端点。仅当使用此元素时可指定两个以上<End>元素。
<Reference>元素描述引用样式关联。该元素可具有以下属性:
●FromRole-必需。包含引用类型的属性的角色的名字。对于关联实体,这必须是关联实体角色的名字。
●ToRole-必需。该引用属性将其作为目标的角色的名字。被标识的角色不应指定OnUpdate属性。
●Property(属性)-必需。FromRole实体中的引用属性的名字。定义此属性的<Property>元素必需具有指定封闭关联的Role属性。如果多重性的上界是1,则该属性的类型肯定是引用,并且如果下界为0,则该引用必须可为空。如果大于1,则该属性类型肯定是引用数组。
以下示出将实体A和B相关的引用关联“AtoB”的示例。
<EntityType Name=″A″Key=″ID″>
<Property Name=″ID″Type=″Int32″>
<Property Name=″BRef″Type=″Ref(B)″Association=″AtoB″/>
</EntityType>
<EntityType Name=″B″Key=″ID″>
<Property Name=″ID″Type=″Int32″>
</EntityType>
<Association Name=″AtoB″>
<End Role=″ARole″Type=″A″/>
<End Role=″BRole″Type=″B″/>
<Reference FromRole=″ARole″ToRole=″BRole″Property=″BRef″/>
</Association>
<CommonValue>(公用值)元素描述公用值样式关联。该元素可具有以下属性:
●Property1(属性1)-必需。使用格式为角色名.属性名的串来标识其中一个端点上的属性。
●Property2(属性2)-必需。使用格式为角色名属性名的串来标识其中一个端点上的属性。
对于关联实体,Property1和Property2中的一个指定关联实体角色,而另一个指定端点角色。所指定的端点可包含OnUpdate和/或OnDelete属性。以下示出将实体A和B相关的公用值关联“AtoB”的示例。
<EntityType Name=″A″Key=″ID″>
<Property Name=″ID″Type=″Int32″>
<Property Name=″X″Type=″String″/>
</EntityType>
<EntityType Name=″B″Key=″ID″>
<Property Name=″ID″Type=″Int32″>
<Property Name=″Y″Type=″String″/>
</EntityType>
<Association Name=″AtoB″>
<End Role=″ARole″Type=″A″/>
<End Role=″BRole″Type=″B″/>
<CommonValue Property1=″ARole.X″Property2=″BRole.Y″/>
</Association>
<Condition>(条件)元素描述基于两个端点之间的任意联合的关联。该元素必需包含对于相关实体其值为真的表达式。<End>和<Using>元素中指定的角色名可在此表达式中使用。如果<Association>元素包含<Condition>元素,则它还可包含0个或多个<Using>元素。这些元素描述被用来定义端点之间的关系的其它实体。<Using>元素可具有以下属性:
●Role(角色)-必需。该关系中所使用的端点的角色的名字。
●Type(类型)-必需。该关系中所使用的实体的类型。
●Table(表)-见对于关联<End>元素的属性描述。
使用<End>、<Using>和<Condition>元素,完整的查询被构造。此查询具有以下形式:
SELECT end-角色-1,end-角色-2
FROM end-表-1 AS end-角色-1,end-表-2 AS end-角色-2,using-表-n ASusing-角色-n,...
WHERE条件
以下例子示出使用包括第三实体C的表达式相关的两个实体A和B。
<EntityType Name=″A″Key=″ID″>
<Property Name=″ID″Type=″Int32″>
<Property Name=″X″Type=″String″/>
</EntityType>
<EntityType Name=″B″Key=″ID″>
<Property Name=″ID″Type=″Int32″>
<Property Name=″Y″Type=″String″/>
</EntityType>
<EntityType Name=″C″Key=″ID″>
<Property Name=″ID″Type=″Int32″>
<Property Name=″Z1″Type=″String″/>
<Property Name=″Z2″Type=″String″/>
</EntityType>
<Association Name=″AtoB″>
<End Role=″ARole″Type=″A″/>
<End Role=″BRole″Type=″B″/>
<Using Role=″CRole″Type=″C″Table=″CTable″/>
<Condition>
ARole.X=CRole.Z1 AND BRole.Y=CRole.Z2
</Condition>
</Association>
<AssociationEntity>(关联实体)元素指示该关联的端点由关联实体连接。<AssociationEntity>元素可具有以下属性:
●Role(角色)-必需。命名此关联实体在关联中所扮演的角色。
●PluralRole(复数角色)-可选。提供角色名的复数形式。此名字在查询模型和正则对象映射中使用。如果未被指定,则使用roleEntities(角色实体)形式的名字来代替。
●Type(类型)-必需。该关联实体的类型。定义此类型的<EntityType>元素必须指定标识封闭<Association>元素的Association属性。
●Table(表)-见对关联<End>元素的属性描述。
<AssociationEntity>具有一个嵌套的<End>元素。关联实体定义此<End>元素和<Association>下所嵌套的每一个<End>元素之间的关联。这些关联的样式以<Reference>、<Condition>或<CommonValue>元素来描述。可改为用<Composition>元素描述这些关联中的一个。
●<Composition>(合成)-该关联实体是合成的端点之一的子实体。
<Assosiation>的<End>上的Role(角色)必须由这些样式元素中的一个上的两个角色之一引用;另一个角色引用<AssociationEntity>的<End>。
<Composition>(合成)元素描述将关联实体合成到端点角色中的一个中。它必须被嵌套在<AssociationEntity>之内。<Composition>元素具有以下属性:
●ParentRole(父角色)-必需。包含关联实体类型的嵌套表的端点角色的名字。这不应是关联实体角色。被此角色引用的<End>元素上的OnDelete属性必需指定Cascade(级联)或CascadeToAssociationEntity(级联到关联实体)。OnUpdate属性不能被指定。
●ChildRole(子角色)-必需。被父实体包含的角色的名字。这必须是关联实体的<End>角色。
●Property(属性)-必需。父实体中的表属性的名字。定义此属性的<Property>元素必须具有指定封闭关联的Association属性。
<Condition>元素被嵌套在<AssociationEntity>下时必须具有以下属性:
●JoinedRoles(联合的角色)-必需。逗号分隔的两个或多个角色名的列表。此列表包括<AssociationEntity>的<End>的角色名字、以及端点角色名字中的一个。所列出的角色不应指定OnDelete或OnUpdate属性。
以下例子示出使用关联实体C将A和B相关的实体关联“AtoB”,其中C被合成在A中,并具有对B的引用。
<EntityType Name=″A″Key=″ID″>
<Property Name=″ID″Type=″Int32″>
<Property Name=″CTable″Type=″Table(C)″/>
</EntityType>
<EntityType Name=″B″Key=″ID″>
<Property Name=″ID″Type=″Int32″>
</EntityType>
<EntityType Name=″C″Key=″ARef,BRef″Association=″AtoB″>
<Property Name=″BRef″Type=″Ref(B)″Role=″BRole″/>
</EntityType>
<Association Name=″AtoB″>
<AssociationEntity Type=″C″>
<End Role=″CRole″Type=″C″/>
<Composition ParentRole=″ARole″ChildRole=″CRole″
Property=″CTable″/>
<Reference FromRole=″CRole″ToRole=″BRole″Property=″BRef″/>
</AssociationEntity>
<End Role=″ARole″Type=″A″/>
<End Role=″BRole″Type=″B″/>
</Association>
合成。每个嵌套表定义两种类型的实体(包含表类型的属性的实体类型,以及被表所包含的实体类型)之间的合成。合成是使用<Composition>(合成……元素来描述的。此元素可具有以下属性:
●Name(名字)-必需。该合成的名字。
<Composition>元素包含<ParentEnd>(父端点)元素。此元素可具有以下属性:
●Role(角色)-必需。指定父实体的类型。
●Property(属性)-必需。指定父实体上定义该合成的属性。
●PluralRole(复数属性)-可选。提供角色名的复数形式。此名字在查询模型和正则对象映射中使用。如果没有被指定,则使用roleEntities(角色实体)形式的名字来代替。
<Composition>元素还必须包含<ChildEnd>(子端点)元素。此元素可具有以下属性:
●Role(角色)-必需。子实体的角色的名字。
●Type(类型)-必需。指定子实体的类型。
●Multiplicity(多重性)-可选。合成中子实体的多重性。见关联的<End>元素上的多重性。
●PluralRole(复数角色)-可选。提供提供角色名的复数形式。此名字在查询模型和正则对象映射中使用。如果没有被指定,则使用roleEntities(角色实体)形式的名字来代替。
以下模式定义了可包含A的实例的两个独立的嵌套表:B.ATable和C.ATable。其中还有可包含B的实例的嵌套表:D.BTable,以及可包含C的实例的嵌套表:D.CTable。D的实例被包含在名为DTable的顶层表中。
<Schema Namespace=″MyCompany.MySchema″>
<EntityType Name=″A″Key=″AID″>
<Property Name=″AID″Type=″String″>
<Length Maximum=″2″/>
</Property>
</EntityType>
<EntityType Name=″B″Key=″BID″>
<Property Name=″BID″Type=″String″>
<Length Maximum=″2″/>
</Property>
<Property Name=″TableA″Type=″Table(A)″Composition=″BA″/>
</EntityType>
<Composition Name=″BA″>
<ParentEnd Role=″RoleB″Type=″B″Property=″TableA″/>
<ChildEnd Role=″RoleA″Type=″A″/>
</Composition>
<EntityType Name=C″Key=CID″>
<Property Name=″CID″Type=″String″>
<Length Maximum=″2″/>
</Property>
<Property Name=″TableA″Type=″Table(A)″Composition=″CA″/>
</EntityType>
<Composition Name=″CA″>
<ParentEnd Role=″RoleC″Type=″C″Property=″TableA″/>
<ChildEnd Role=″RoleA″Type=″A″/>
</Composition>
<EntityType Name=″D″Key=″DID″>
<Property Name=″DID″Type=″String″>
<Length Maximum=″2″/>
</Property>
<Property Name=″TableB″Type=″Table(B)″Composition=″DB″/>
<Property Name=″TableC″Type=″Table(C)″Composition=″DC″/>
</EntityType>
<Composition Name=″DB″>
<ParentEnd Role=″RoleD″Type=″D″Property=″TableB″/>
<ChildEnd Role=″RoleB″Type=″B″/>
</Composition>
<Composition Name=″DC″>
<ParentEnd Role=″RoleD″Type=″D″Property=″TableC″/>
<ChildEnd Role=″RoleC″Type=″C″/>
</Composition>
<TableSet Name=″TS″>
<Table Name=″TableD″Type=″D″/>
</TableSet>
</Schema>
图12示出合成下的相同类型中的一部分的UML表示1200。
图13示出TS.TableD中的D的实例的可视化表示。
图14示出对应于图13的实体表的SQL表1400。
嵌套表类型约束。使用以下所定义的约束元素中的一个来约束数组类型的集合的值是可能的。这些元素可被嵌套在引用表类型的各种元素内(例如,<EntityType>或<InlineType>元素中的<Property>元素)。
EntityConstraint(实体约束)。<EntityConstraint>约束元素可被用来对表中的实体设置约束。对一实体类型有效的任何约束元素都可在<EntityConstraint>元素内被指定。
出现。<Occurs>(出现)约束元素可被用来约束表中的实体的个数。此元素可具有以下属性:
●Minimum(最小)-可选。指定该表中条目的最小个数。默认值为0。
●Maximum(最大)-可选。指定该表中条目的最大个数。值“unbounded”
(无限)意味着没有任何约束。默认值为“unbounded”。
为与基类型中指定的约束一致,为Minimum指定的值必需等于或大于先前的值,而为Maximum指定的值必需等于或小于先前的值。
唯一的。<Unique>(唯一的)约束元素可包含布尔查询表达式。要使表有效,则此表达式的值为真。该表达式不应有任何副作用。当在基类型和派生类型两者中都指定了校验约束时,两个约束都生效。注意,对表的校验约束适用于整体的属性。例如,它可被用来校验属性值的和是否小于某个限制。或者,放在<EntityConstraint>(实体约束)元素内的校验约束可个别地应用于每个值。
导航属性。导航属性可被任选地放在由关系的任一端点所指定的实体上。此属性提供一种从关系的一端导航到另一端的手段。导航属性是在<Entity>定义内适用<NavigationProperty>(导航属性)元素来表示的。此元素可具有以下属性:
●Name(名字)-必需。该成员的名字。该名字在定义类型的范围中必须是唯一的。该名字必须遵守CLR中类成员名的规则,并应遵守.Net框架命名方针。
●DuplicateName(复制名字)-可选。成员名在基类型分层结构上也必须是唯一的,除非提供了DuplicateName属性且其有值为“true”。默认值“false”值指示预期该成员名是唯一的。
此属性的职责是a)记录一成员名复制基类型中的一个属性这一事实,以及b)强制模式设计者有目的地选择复制名字(即,它起到和C#中的new关键字相同的作用)。
●Association(关联)-必须或者给出Association属性,或者给出Composition属性。指定由此属性所表示的关联的名字。
●Composition(合成)-必须或者给出Association属性,或者给出Composition属性。指定由此属性所表示的合成的名字。
●FromRole-必需。由具有导航属性的实体所表示的端点的角色。
●ToRole-必需。由属性所表示的端点的角色。
类型别名。类型别名给予简单、集合、数组、表或引用类型以及约束集唯一的名字。类型别名是适用允许以下属性的<TypeAlias>(类型别名)元素来定义的。
●Name(名字)-必需。该别名的名字。
●AliasedType-必需。别名类型的名字。这必需是简单、集合、数组、表或引用类型。
<TypeAlias>(类型别名)元素可包含别名类型所允许的任何约束元素。所定义的别名名字可在能使用该别名类型的名字的任何地方使用。以下示出一些示例性别名:
<Schema Namespace=″MyCompany.MySchema″>
<TypeAlias Name=″Name″AliasedType=″String″>
<Length Maximum=″1000″/>
</TypeAlias>
<TypeAlias Name=″PersonRef″BaseType=″Ref(PersonItem)″>
</TypeAlias>
<TypeAlias Name=″Keywords″AliasedType=″Collection(String)″>
<Length Maximum=″100″/>
<Occurs Minumum=″0″Maximum=″unbounded″/>
</TypeAlias>
</Schema>
表集和表集类型。表集类型是实体类型的受限形式。表集类型是使用<TableSetType>(表集类型)元素来定义的。此元素可包含以下属性:
●Name(名字)-必需。该表集类型的名字。此名字在定义模式中的所类型化和关系中间必需是唯一的。
●DefaultTableSet(默认表集)-可选。指定该表集类型的默认表集。如果没有被指定,则没有默认表集。
<TableSetType>元素可包含指定引用和表类型的<Property>元素。引用属性仅可指定表集类型。<TableSetType>元素还可包含<ComputedProperty>(经计算的属性)和<Method>(方法)元素。
表集实例。表集是表集类型的实例。表集构成本数据模型的“顶层”。所有存储都是通过创建表集来直接或间接分配的。表集是使用<TableSet>(表集)元素来描述的。此元素可具有以下属性:
●Name(名字)-必需。该表集类型的名字。此名字在定义模式中的所有表集中间必需是唯一的。
●Type(类型)-必需。表集类型的名字。
聚合表集。<TableSet>元素为所指定的实体类型中每一个引用类型的属性包含一个<AggregatedTableSet>(聚合表集)元素。这允许先前所定义的表集被聚合为一新的表集。这在将来自两个单独的应用程序的数据合成到单个应用程序中时是有用的。<AggregatedTableSet>元素可包含以下属性:
●Property(属性)-必需。引用类型的属性的名字。
●TableSet(表集)-必需。将被该属性引用的表集的名字。
下例示出此元素:
从销售模式
<TableSetType Name=″SalesData″>
...
</TableSetType>
<TableSet Name=″Sales″Type=″SalesData″/>
从WinFS模式
<TableSetType Name=″WinFSData″DefaultTableSet=″WinFS″>
...
</TableSetType>
<TableSet Name=″WinFS″Type=″WinFSData″/>
从第三模式
<TableSetType Name=″ThirdAppData″>
<Property Name=″Sales″Type=″Ref(SalesData)″.../>
<Property Name=″WinFS″Type=″Ref(WinFSData)″.../>
...
</TableSetType>
<TableSet Name=″ThirdApp″Type=″ThirdAppData″>
<AggregatedTableSet Property=″WinFS″TableSet=″WinFS″/>
<AggregatedTableSet Property=″Sales″TableSet=″Sales″/>
</TableSet>
查询语言。CDM的查询语言可被指定。该查询语言可基于如实体和关系等SQL目标的CDM概念。
在查询中使用合成。以下模式通过确定输入表所基于的表集来起作用。合成可使以下函数在查询中可用。
●Table(parent-type)composition.Getparent-role-p(Table(child-type))-返回所输入的多个子的多个父。
●parent-type composition.Getparent-role-s(child-type)-所输入的一个子的一个父。
●Table(parent-type)composition.Filterparent-role-p(Table(parent-type),Table(child-type))-返回由所输入的多个子的集合中出现一个子过滤的多个父的集合。
●Table(child-type)composition.Getchild-role-p(Table(parent-type))-返回所输入的多个父的多个子。
●Table(child-type)composition.Getchild-role(parent-type)-返回所输入的一个父的多个子。
●Table(child-type)composition.Filterchild-role-p(Table(child-type),Table(parent-type))-返回由所输入的多个父的集合中出现一个子过滤的多个子的集合。
其中:composition表示合成名;parent-role-s表示父角色名的单数形式;parent-role-p表示父角色名的复数形式;child-role-s表示子角色名的单数形式;child-role-p表示子角色名的复数形式;parent-type表示父实体类型;child-type表示子实体类型;而Table(type)表示特定类型的表上的查询。
在查询中使用关联。这些模式可通过确定输入表所基于的表集来起作用。关联使以下函数在查询中可用:
●Table(end-1-type)association.Getend-1-role-p(Table(end-2-type))-返回与所指定的多个end-2实体相关联的多个end-1实体。
●Table(end-1-type)association.Getend-1-role-p(end-2-type)-返回与所指定的一个end-2实体相关联的多个end-1实体。
●Table(end-1-type)association.Filterend-1-role-p(Table(end-1-type),Table(end-2-type))-返回由多个end-2实体的输入集中出现一相关联的end-2实体过滤的多个end-1实体的集合。
●为所有端点的合成、包括关联实体(若有)重复以上方法。
其中:association表示关联名;end-1-role-s表示一端点的角色名的单数形式;end-1-role-p表示一端点的角色名的复数形式;end-2-role-s表示一端点的角色名的单数形式;end-2-role-p表示一端点的角色名的复数形式;end-1-type表示源实体类型;end-2-type表示目标实体类型;而Table(type)表示特定类型的表上的查询。
接口。接口为实体和内联类型提供类似于CLR的接口。它们可被用来解决接口在对象类型系统中解决的大多数相同的问题。接口是使用<Interface>(接口)元素来声明的。<Interface>元素可具有以下属性:
●Name(名字)-必需。该接口的名字。在模式中所定义的所类型化图合格顶层表中间必须是唯一的。
●BaseInterfaces(基接口)-可选。逗号分隔从其派生出此接口的接口的列表。
<EntityType>或<InlineType>元素可使用ImplementedInterfaces(已实现的接口)属性来指定的逗号分隔的其所实现的接口的列表。在所列出的接口中所定义的每个属性都必须在该类型中被定义。如同C#中的接口的情况,接口中所定义的属性仅仅是通过声明具有相同名字和类型的属性而被隐式地实现在该类型中的。对属性的约束在该属性被声明时可被缩小。属性还可被显式地实现。这是通过将接口类型名包括在属性名中(正如C#的情况)来实现的。这允许不同的约束被应用于具有相同的签名但却是从不同的接口继承来的属性。例如:
<Schema Namespace=″MyCompany.MySchema″>
<Interface Name=″IA″>
<Property Name=″X″Type=″Int32″/>
<Property Name=″Y″Type=″Int32″/>
</Interface>
<Interface Name=″IB″>
<Property Name=″X″Type=″Int32″/>
<Property Name=″Y″Type=″Int32″/>
</Interface>
<EntityType Name=″C″ImplementedInterfaces=″IA,IB″Key=″ID″>
<Property Name=″ID″Type=″Int32″/>
<Property Name=″X″Type=″Int32″/>
<Proeprty Name=″IA.Y″Type=″Int32″>
<RangeConstraint Maximum=″100″/>
</Proeprty>
<Property Name=″IB.Y″Type=″Int32″>
<RangeConstraint Maximum=″10″/>
</Property>
</EntityType>
</Schema>
以下是一完整的模式示例。下例定义了Customer(顾客)、Order(订单)、Orderline(订单线)、Product(产品)和Supplier(供应商)实体类型,以及描述这些实体如何相关的关联。
<Schema Namespace=″MyLOB″>
<InlineType Name=″Address″>
<Property Name=″Linel″Type=″String″Nullable=″false″>
<Length Maxiumum=″100″/>
</Property>
<Property Name=″Line2″Type=″String″Nullable=″true″>
<Length Maxiumum=″100″/>
</Property>
<Property Name=″City″Type=″String″Nullable=″false″>
<Length Maxiumum=″50″/>
</Property>
<Property Name=″State″Type=″String″Nullable=″false″>
<Length Minimum=″2″Maximum=″2″/>
</Property>
<Property Name=″ZipCode″Type=″String″Nullable=″false″>
<Length Minimum=″5″Maximum=″5″/>
</Property>
</InlineType>
<EntityType Name=″Customer″Key=″CustomerId″>
<Property Name=″CustomerId″Type=″String″Nullable=″false″>
<Length Minimum=″10″Maximum=″10″/>
</Property>
<Property Name=″Name″Type=″String″Nullable=″false″>
<Length Maximum=″200″/>
</Property>
<Property Name=″Addresses″Type=″Array(Address)″>
<Occurs Minumum=″1″Maximum=″3″/>
</Property>
<NayigationProperty Name=″Orders″Association=″OrderCustomer″
FromRole=″Customer″ToRole=″Orders″/>
</EntityType>
<EntityType Name=″Order″Key=″OrderId″>
<Property Name=″OrderId″Type=″String″Nullable=″false″>
<Length Minimum=″10″Maximum=″10″/>
</Property>
<Property Name=″Date″Type=″DateTime″Nullable=″false″/>
<Property Name=″Customer″Type=″Ref(Customer)″
Association=″OrderCustomer″/>
<Property Name=″Lines″Type=″Table(OrderLine)″
Composition=″OrderOrderLine″/>
<Property Name=″ShippingAddress″Type=″Address″Nullable=″false″/>
</EntityType>
<Composition Name=″OrderOrderLine″>
<ParentEnd Role=″Order″Type=″Order″PluralRole=″Orders″Property=″Lines″/>
<ChildEnd Role=″OrderLine″Type=″OrderLine″PluralRole=″OrderLines″
Multiplicity=″100″/>
</Composition>
<Association Name=″OrderCustomer″>
<End Role=″Order″Type=″Order″PluralRole=″Orders″/>
<End Role=″Customer″Type=″Customer″PluralRole=″Customers″
OnDelete=″Cascade″Table=″/>
</Association>
<EntityType Name=″OrderLine″Key=″LineId″>
<Property Name=″LineId″Type=″Byte″Nullable=″false″/>
<Property Name=″Product″Type=″Ref(Product)″Nullable=″false″
Association=″OrderLineProduct″/>
<Property Name=″Quantity″Type=″Int16″Nullable=″false″>
<Range Minumum=″1″Maximum=″100″/>
</Property>
<Property Name=″Price″Type=″Decimal″Nullable=″false″>
<Decimal Precision=″6″Scale=″2″/>
</Property>
<NavigationProperty Name=″Order″Composition=″OrderOrderLine″
FromRole=″Line″ToRole=″Order″/>
</EntityType>
<Association Name=″OrderLineProduct″>
<End Role=″OrderLine″PluralRole=″OrderLines″/>
<End Role=″Product″Type=″Product″PluralRole=″Products″Table=″″/>
<Reference FromRole=″OrderLine″ToRole=″Product″Property=″Product″/>
</Association>
<EntityType Name=″Product″Key=″ProductId″>
<Property Name=″ProductId″Type=″Guid″Nullable=″false″/>
<Property Name=″Title″Type=″String″Nullable=″false″>
<Length Maximum=″100″/>
</Property>
<Property name=″Description″Type=″String″Nullable=″false″>
<Length Maxumum=″1000″/>
</Property>
</EntityType>
<Association Name=″CustomerProduct″>
<End Role==″Customer″PluralRole==″Customers″Type==″Customer″/>
<End Role=″Product″PluralRole=″Products″Type=″Product″/>
<Uses Role=″Order″Type=″Order″/>
<Uses Role=″Line″Type=″Lines″/>
<Condition>
Order.Customer=Customer AND OrderLine.Product=Product
</Condition>
</Association>
<EntityType Name=″Supplier″Key=″SupplierId″>
<Property Name=″SupplierId″Type=″String″Nullable=″false″>
<Length Minimum=″10″Maximum=″10″/>
</Property>
<Property Name=″Name″Type=″String″Nullable=″false″>
<Length Maximum=″200″/>
</Property>
<Property Name=″Addresses″Type=″Array(Address)″>
<Occurs Minumum=″1″Maximum=″3″/>
</Property>
<NavigationProperty Name=″Products″Association=″ProductSupplier″
FromRole=″Supplier″ToRole=″Product″/>
</EntityType>
<EntityType Name=″ProductSupplierLink″Key=″Product,Supplier″
Association=″ProductSupplier″>
<Property Name=″Product″Type=″Ref(Product)″Nullable=″false″
Role=″Product″/>
<Property Name=″Supplier″Type=″Ref(Supplier)″Nullable=″false″
Role=″Supplier″/>
<Property Name=″Price″Type=″Decimal″Nullable=″false″>
<Decimal Precision=″6″Scale=″2″/>
</Property>
</EntityType>
<Association Name=″ProductSupplier″>
<AssociationEntity Type=″ProductSupplierLink″>
<End Role=″Link″Type=″ProductSupplierLink″/>
<Reference FromRole=″Link″ToRole=″Product″Property=″Product″/>
<Reference FromRole=″Link″ToRole=″Supplier″Property=″Supplier″/>
</AssociationEntity>
<End Role=″Product″Type=″Product″PluralRole=″Products″
Table=″″/>
<End Role=″Supplier″Type=″Supplier″PluralRole=″Suppliers″
Table=″″/>
</Association>
<TableSetType Name=″LOBData″>
<Property Name=″Orders″Type=″Table(Order)″/>
<Property Name=″Customers″Type=″Table(Customer)″/>
<Property Name=″Products″Type=″Table(Product)″/>
<Property Name=″Suppliers″Type=″Table(Supplier)″/>
<Property Name=″PSLinks″Type=″Table(ProductSupplierLink)″/>
</TableSetType>
<TableSet Name=″LOB″Type=″TableSetType″/>
</Schema>
SQL99和CDM。SQL99定义了对核心关系型数据模型的数种对象扩展(例如,SQL92)。SQL99的一些关键方面有:既包括独特类型也包括结构化类型的用户定义的类型;方法(行为);类型化的表;以及Ref。
SQL99定义SQL数据模型内子包含的完整的类型系统的一部分或全部。尽管编程语言中的对象可被映射到SQL对象,但是定义与编程语言(例如,Java、C#)的紧绑定不是SQL99的目标。例如,SQL99中的方法是以过程化语言、而不是标准编程语言定义的。CDM的一个目标是指定与SQL和CLR两者的紧对齐。
用户定义的类型。CDM中简单和复合类型这些类型几乎与SQL99中的用户定义的类型一对一映射。简单类型和简单类型别名映射到SQL99标量类型和独特类型;复合类型映射到SQL99结构化数据类型。SQL结构化类型和复合类型之间一个主要的差异是内联类型和实体类型之间的区别。在CDM中,标识/关键字的概念是在类型定义时被定义的。在SQL99中,标识是在当该类型被用来定义类型化的表时被定义的。因此,在SQL99中,无需区别带有和不带标识的类型,由此得以支持将一个类型重复使用于表(可引用对象)和列定义(非可引用的、内联的对象)。此类重复使用仅对存储起作用,因为标识可在表定义的时候被定义。但是同一类型不能既被映射到内联的类又被映射到可引用的类。因为CDM的一个目标是提供应用程序对象框架和持久化框架,所以内联的类型和实体类型之间的区别是很重要的。
方法/行为。在CDM中,行为是使用CLR框架定义的。SQL99定义其自身的方法/行为框架。尽管它接近于大多数现代的OO语言,但是它仍然是不同的,而且没有为应用程序提供良好的编程环境。通常应用程序(或应用程序服务器)填补了编程环境和数据库环境之间的差异。
类型化的表对实体表。CDM中的实体表类似于SQL99中的类型化的表。但是,范围是逻辑的——它是对象的逻辑集合。没有任何与范围相关联的物理存储。类型表是在表上所有存储属性都被允许的SQL表。范围可被映射到一个或多个物理表。
Ref。CDM中和SQL99中的Ref是非常相似的。在CDM中,ref的范围是通过指定该ref的范围来界定的;在SQL99中,ref的范围是通过指定类型表作为该ref的目标来界定的。在两种情形中,ref都被解析到对象。
图15示出可使用本体系结构的CDM的数据平台1500的示意图。应当认识到,将任何组件和/或框放置于此图示中并不意味着(或必定防止)任何跨越过程/机器界线的特定部署。数据平台1500可利用乐观并发模型,从而如果改变要被保存,而已对底层数据进行了其它改变,则冲突检测以应用程序专属的方式解决此问题。为了称为有效的平台,数据平台1500包括诸如编程语言继承、富数据建模、持久化框架、服务等等特征。API 1502便于语言集成、以及应用程序1504经由数据平台运行库1506对存储1508的数据访问。数据平台1500提供以下特征。
CDM。在数据平台1500运行库1506的中心是CDM 1510。CDM 1510的目的是分解出从主要处理用户数据(PIM、文档等)的应用程序到主要处理LOB和企业数据的应用程序的多个应用程序域上公用的建模概念。除了提供富对象和关系抽象以外,CDM 1510还提供对结构、非结构化以及半结构化数据的支持。
行/实体数据。CDM 1510支持捕捉结构化数据(例如,商务数据)的结构和行为的富实体-关系模型。CDM 1510是核心关系型模型的超集,它还具有富对象抽象和关系建模(例如,文档和联系人之间的作者关系;采购订单和订单线之间的线关系)的扩展。
文件数据。CDM 1510支持“文件流”数据类型以存储和操纵非结构化的(文件)数据。文件流数据类型可将数据作为文件存储,并且支持文件访问API。文件流数据类型在SQL服务器中受到本机支持,被映射到NTFS文件流,并支持所有基于文件处理/流式传输的操作。在CDM 1510中除了将非结构化的内容建模为文件流以外,使用实体类型,有用的内容还可被升级为结构化属性。基于数据库的文件存储系统定义了文件支持项的概念,它是将结构化属性与非结构化内容的文件流建模的实体。文件支持项提供了相关联的文件流上的富查询以及基于流的操作。
XML数据。XML文档在CDM 1510中可朝两个主要方向建模:(1)将其作为XML数据类型存储;(2)将XML文档映射到一个或多个实体(例如,类似于数据合同)。CDM 1510以SQL服务器中支持XML数据类型的方式支持XML数据类型。XML数据类型可以是任何实体属性的类型;XML数据类型允许无类型的或类型化的XML文档被存储。强类型化是通过将一个或多个XML模式与XML文档属性相关联来提供的。
API 1502中包括查询的编程语言集成。数据平台1500中的会话和事务1512、查询1514、持久化1516、游标1515、服务1520、对象高速缓存1522和商务逻辑主宿1524这些特征组件被封装在数据平台API 1502中可用的数个“运行时”类中。
持久化实体1516包括一持久化引擎,它提供描述如何从来自各关系型存储的组件片汇编出对象的确切情况的声明性映射定义。该引擎包括一查询生成组件(未示出),它取由查询处理器以对象查询表达式的语言定义的表达式,然后将其与声明性映射相结合。这就变成访问数据库中各底层表的等效查询表达式。更新生成组件(未示出)查看改变跟踪服务,并且在映射元数据的帮助下描述如何将对象世界中的那些变化转化为表世界中的变化。
持久化引擎可包括对象关系型映射。换言之,数据平台1500所提供的建模、访问和查询抽象是基于对象的。数据平台1500所使用的主存储基数是基于关系的。持久化引擎使用对象关系型映射(也称为“O-R映射”),其中持久化引擎可将语言类映射到底层的表的表示。
查询/搜索文件和XML数据。CDM 402使用文件流和XML数据类型来存储非结构化和半结构化的数据。CQL能够查询这些数据类型。对于被升级为结构化实体的文件内容(例如,WinFS文件支持项)而言,CQL的关系运算符可查询这些实体。作为文件流存储的非结构化数据可使用全文本搜索来查询。XML内容可使用XPath或XQuery来查询。
对象关系型映射。因为数据平台1500提供关系型(表的)存储之上的基于对象的抽象,所以它提供一O-R映射组件。数据平台1500既支持规定的映射,也支持非规定的映射(类型设计者在指定映射时有一些机动性)。注意,目前基于数据库的文件存储系统实现使用规定的映射,而更多一般的O-R持久化框架需要非规定的映射。
高速缓存。数据平台运行库1506维护查询结果(例如,游标)和未经提交的更新的高速缓存。这被称为会话高速缓存。数据平台1500还提供显式的高速缓存,它使应用程序能在断开模式中工作。数据平台1500为显式高速缓存中的数据提供各种一致性保证。该高速缓存通过将数据的盘上标识与存储器中的对象相互关联来执行标识管理。数据平台运行库1506维护查询结果(例如,在下文详细讨论的游标)和未经提交的更新的高速缓存1522;其中此类高速缓存可被称为会话高速缓存,因为它被绑定到会话,即事务1512。此外,它在会话被创建时出现,而在会话被中止时消失。
数据平台1500还可给出称为显式高速缓存的另一种高速缓存。显式高速缓存提供来自一个或多个查询的数据的高速缓存。一旦数据被具体化到显式高速缓存中,即可提供以下数据一致性保证:1)只读,非权威性的;2)连续写入,权威性的;以及3)经由外源的通知自动刷新。对显式高速缓存的编程和查询模型可以在实质上类似于存储数据上的编程和查询模型。
查询处理器。数据库查询要经由查询处理器。查询处理器允许多个前端处理要被表达、然后被映射到内部正则格式的多种查询语言。这是以域模型以及它正在处理的应用程序的对象的形式来实现的。然后这些查询被传递给该处理器,然后被转换成后端专属的查询,其中该处理器是一管道。
游标。数据平台1500既可提供仅前向的游标,也可提供可滚动的游标。游标支持通知、带展开/折叠状态的多级分组、动态分类和过滤。游标,即规则1515是允许从CQL返回的一组数据实体一次被处理一个的机制。应用程序可仅仅通过将整个结果集复制到存储器中、并在存储器结构中在此之上覆盖滚动模式来创建结果集上的游标。但是,此需求的普遍存在和实现游标中(特别是在考虑了更新、页面调度等的时候)时有涉及的复杂性意味着任何数据平台逗引提供游标定位模型。除了浏览和滚动的基本功能以外,数据平台游标还能提供以下特征:1)外源的通知和维护;2)带展开/折叠状态的多级分组;以及3)动态分类和过滤(例如,“后处理”)。应当认识到并理解,游标可能不是指定结果集的不同机制;结果集是由查询指定的,而游标是在这些查询之上。
商务逻辑主宿1524。数据平台1500提供运行时环境以在类型/示例上和操作上主宿以数据为中心的逻辑。此类以数据为中心的商务逻辑与应用程序/商务过程逻辑截然不同,后者可被主宿在应用程序服务器中。对象不只是数据库中的行。当对象在存储器中被具体化时,它们实际上是具有可由应用程序调用的行为的对象。这些是系统中的扩展点,它们主要都是用于在运行时扩展数据平台1500的事件和回调。这些对象不仅仅是对象,而且还是CLR对象、NET对象、等等。数据平台1500允许截取这些对象中的属性或方法调用的能力。应用程序可自定义这些对象的行为。
数据平台1500提供数种用于创作商务逻辑的机制。这些机制可被分成以下5个类别:约束、事件处理程序、静态/实例方法、可绑定的行为、以及静态服务方法,以下将详细讨论其中每一类。约束/安全实体1526可以是声明性的和过程性的。可对存储执行这些约束,这很接近与数据。因此,约束1526被视为在信任界限内。此外,约束可由类型设计者创作。
商务逻辑主宿1524可采用事件处理程序。数据平台API 1502在数据改变操作上引发数个事件。商务逻辑作者可经由处理程序代码挂钩到这些事件中。例如,考虑一订单管理应用程序。当新的订单到来,该应用程序需要确保该订单的价值低于对该顾客授权的信用限额。此逻辑可以是事件处理程序代码的一个部分,而该事件处理程序代码在该订单被插入到存储中以前已被运行。
服务。数据平台1500提供对所有数据平台客户可用的服务的核心集。这些服务包括规则、改变跟踪、冲突检测、事件机制以及通知。事件机制将数据平台运行库1506将数据平台运行库1506从框架级服务扩展,或用于使应用程序添加其它行为,并且还被用于用户接口处的数据绑定。
约束。数据平台1500提供一约束/安全组件1526以至少允许类型设计者声明性地创作约束。这些约束是在存储中执行的。通常,数据平台约束的范围包括诸如长度、精度、范围、默认值、校验等概念。这些约束是由数据平台约束引擎1526在运行时强制实施的。
安全。数据平台1500提供基于角色的安全模型——用户的凭证确定其“角色”(诸如管理员、权威用户、被批准者等等)。每个角色都被附于一组访问许可。数据平台安全引擎1526强制实施这些安全策略。此外,数据平台1500提供用于控制对数据平台1500中的实体的访问的安全模型。该安全模型可支持操作系统用户的认证、实体的授权等级(例如,具有单独的读和更新的许可)、等等。
注意,图中将约束/安全组件1526示为与数据平台运行库组件1506脱离,因为它能够作为与之脱离的实体进行操作。或者,也许是更为高效的,约束/安全组件1526被与存储组件1508相结合,其中后者可以是数据库系统。
在以下图16-18中,图中每个类都是模型或模式元素。由“S”指示的元素是SDL中的元素。其它元素或是结构化元素、或是被隐式构造的元素(诸如引用类型)、或是内建元素(诸如简单类型,它是通过导入CLR类型、而不是通过直接声明来扩展的)。
图16示出阐明与类型相关的模型的一些语义的CDM元模型片段。这些模型描述模式的作用,而不是对其确切语义进行建模。例如,在这些模型中,使用关联端点角色名的属性被表示为对关联端点的引用。注释及其它约束:
声明实体类型就隐式地定义了EntityCollectionType(实体集合类型)和ReferenceType(引用类型)。声明复合类型就隐式地定义了InlineCollection(内联集合)。在实施中,这些类型能以类属来实现,诸如Ref<T>、EntityCollection<T>、InlineCollection<T>。
●属性仅可在内联和实体类型声明上被声明。
●typeof(InlineCollectionType.ElementType)!=InlineCollectionType
图17示出阐明与属性相关的模型的一些语义的CDM元模型片段。注释及其它约束:
Property.Kind(属性.种类)使关联约束更易阅读,因为Property元类具类型化,且其所表示的属性具类型化。Kind可能带来的任何混淆。
●AssociationEnd.Property(关联端点.属性)是引用关联同一端点处的实体的属性。换言之,它是关联对方上的实体上的属性。
●引用或实体集的属性是具有底层实体类型的关联属性。
●导航属性返回查询。
图18示出阐明与关联相关的模型的一些语义的CDM元模型片段。这里的大多数约束仅仅陈述关联端点上的属性必须是正确的类型,而正确的类型是相当显然的。例如,引用样式的关联必须具有引用类型的属性。注释及其它约束:
AssociationEnd.Property(关联端点.属性)是关联的另一端点上的实体类型上的属性。它指示引用关联的此端点上的实体的属性。更为正式地,在关联上以下成立:
Ends[0].Property.UnderlyingType=Ends[1].Type以及
Ends[1].Property.UnderlyingType=Ends[0].Type
●CommonValue.Property(公用值.属性)中的一个来自公用值关联中的两个实体中的每一个。
替换实现和句法
以下是对象关系型数据的数据模型的一种替换实现。对此替换实现的描述使用模式定义语言,它是此替换实现的表达的许多可能形式中的一种。还要注意,其中有许多与上文中所描述的前一实现的类似之处,但是仍然有例如命名和句法形式的许多明显的差异。
在此替换描述中,关系如今可使用<Association>或<Composition>元素在顶层定义。无需在源(或父)上定义属性以定义Ref关联(或合成)。以下是在关系上引入的操作行为:OnCopy、OnSerialize、OnSecure以及OnLock。EntitySets(实体集)仅在EntityContainerType(实体容器类型)内被定义,而不在EntityType(实体类型)内被定义。NavigationProperty(导航属性)不再被使用,而RelationshipProperty(关系属性)是以稍微不同的语义来使用的。
显式的Ref类型的属性是对实体的无范围界定的引用,并且不创建关系。RelationshipProperty隐式地是Ref类型(或Collection(Ref))。关系范围是在实体容器类型的<Scope>(范围)从句内指定的。
关系已被变得更加抽象。在前一实现中,关系是由实体内Ref或集合值的属性隐式地定义的——这预示了一种实现关系的方法。在这里,关系现在是在顶层定义的。这将关系元数据从类型声明中移除,从而实现了类型重复使用。
分层。引用关联、条件关联和关联实体都是在<Association>元素内定义的。这反映了该元模型具有两个实体之间的关联的核心概念这一事实;它是基于引用、条件、还是通过关联实体被相关是由<Association>内的各种标签和子元素指定的。专用概念(引用、条件、关联实体)在核心概念(关联)之上分层。
核心建模与持久化的脱离。出于两个目的在前一实现中使用了实体集合的概念。第一,是作为命名和引用经持久化的实体分组的方法,第二,是作为定义合成的方法。因此,仅仅是为将合成建模,就必须处理持久化。实体集合如今是纯粹的分组/范围界定概念;它们不被允许为实体类型内的字段。合成是通过指定关于各参与实体的抽象元数据而被定义在顶层的。通过将持久化与合成脱离,该模型就变得更加灵活和正交。
集合的简化。因为现在仅在EntityContainerType(实体容器类型)(以前称为EntityDatabaseType(实体数据库类型))内允许实体集合,所以只有内联集合可以是实体或复合类型的属性。这导致了集合语义的简化。不再需要区别实体集合和内联集合。只有“集合”,且它们被用来集合内联类型。
指定操作语义的能力。此实现指定关系——关联或合成——并在任何关系上正交地指定操作行为,而无论该关系的类型是什么。由此,现在就能够在任何关系上指定OnCopy、OnSerialize、OnSecure、OnLock行为。同样,这提供更多的灵活性,并捕捉更大的情形集合。
实体的任意分组。WinFS的“Item”(项目)概念实际上是数个实体(例如,Item实体、ItemFragment实体和被包含的实体)的操作分组。如前所定义的合成对将此概念建模而言限制性过大。有了指定操作语义的能力,将实体集合从关系定义脱离就允许拮取和选择操作行为并将其应用于实体的任意分组。
重命名。一些名字被改变以更好地反映它们的语义。例如:(a)EntityCollection(实体集合)被改为EntitySet(实体集),因为这现在是实体的无序分组;它还与经典ER建模中所使用的属于一致;(b)EntityDatabaseType(实体数据库类型)被改为EntityContainerType(实体容器类型)以消除术语“数据库”,因为它有许多持久化/操作/管理涵义;(c)InlineCollection(内联集合)被改为Collection(集合),因为这是此实现模型中唯一允许的集合种类。
EntityDatabase(实体数据库)不再被使用,但是它现在是EntityDatabaseType(实体数据库类型)的一个实例。现在在<Association>元素中定义了<AssociationEntityType>(关联实体类型)。
因此,一数据模型描述应用程序所关注的各件数据的形状和语义(约束、行为)以及它们中间的关系。
图19示出CDM的该替换实现的4个主要概念。和以前一样,这4个概念是类型、实例、实体和关系。图19示出可与通常处理以下不同种类的数据的LOB应用程序相关联的数据的子集:订单、顾客、订单线、地址、供应商、产品、雇员、等等。考虑被标记为Customer(顾客)的框。在CDM中,这被称为实体,并表示应用程序处理的顶层数据单元。Customer具有数个字段:CustomerID(顾客ID)、CompanyName(公司名)、ContactName(联系人名)、Address(地址)和Phone(电话)。每个字段都有一个类型,它定义了进入该字段的数据的结构。已经可以看到,CustomerID是固定长度的串。CompanyName和ContactName字段也是串类型。Customer本身具类型化。因为Customer是实体,所以此类型可被称为实体类型。还注意到,Address字段与其它字段不同:它拥有其它字段形式的内部结构。在CDM中,这样一个字段的类型被称为复合类型。相反,CustomerID、CompanyName和ContactName的类型都是简单类型。Phone字段由数个电话号码组成,其中每一个都是一个串。这被称为集合类型。类型指定结构(以及对各值的某些约束);实际的数据被存储在这些类型的实例中。类型和实例分别类似于类和对象。图19示出Customer(顾客)、Order(订单)和OrderDetail(订单细节)的实例。
Customer(顾客)和Address(地址)两者在它们都具有内部结构(由多个字段合成而成)这一意义上是相似的。但是在语义上和操作上,Customer与Address是不同的。Customer担当查询、数据改变操作、事务、持久化以及共享的单元。另一方面,Address总是存活在Customer内,并且不可被独立引用或者独立处理。在CDM中,此类顶层数据单元被称为实体。所有其它数据都被视为内联于实体。
现在来看Order(订单),商务规则要求每个订单都具有对应的顾客。这是由Order实体和Customer实体之间的关系来建模的。CDM支持不同种类的关系。Order和Customer之间的关系被称为关联。关联通常被用来将实体中间的对等关系建模。每个订单都由数个订单线合成而成(如果从一书商订购了5本书,则关于每本书的信息就是一条订单线)。这被建模为另一种类的关系——合成。合成内的每个OrderLine(订单线)都是一个实体。
数据的形状通过定义类型来描述。概念上,类型是给予值集的名字。例如,如果某事物是int(整数)类型,则指定了正好是整数范围的值的范围。类型的概念的准确定义需要涉及类别理论,这在此文献的范围之外。因此,在此文献中类型的概念被假定为在形式上是原始概念。类型系统是一种用于定义类型并将其与语言构造相关联的机制。
居于CDM中心的是它的类型系统。类似于CLR,使用此类型系统定义的数据被视为是强类型化的。换言之,期望此实现规定对类型规则毫无例外的严格强制执行;期望所类型化在编译时是已知的;以及期望任何类型转换在其作用上是可预测的。
在最高层,CDM类型系统定义两种类型:实体类型和内联类型。实体类型具有唯一的标识,并构成一致的操作单元。直观上,实体被用来将数据模型内的“顶层”概念建模,例如,Customer(顾客)、Order(订单)、Suppliers(供应商)、等等。内联类型是被包含的类型。它们被包含在实体类型内。它们仅在包含实体的上下文内存活、死亡、被处理和被引用。非常粗略地看,实体类型类似于CLR中的引用类型,而内联类型类似于值类型。这是有限的类比,且仅在如CLR值类型等内联类型不具有独立存在,而如CLR引用类型等实体类型可独立存在并可被独立引用这一意义上适用。
有数种内联类型:标量类型、复合类型、XML类型、FILESTREAM(文件流)类型、以及这些类型的集合。这些类型中的一部分在下文中更加详细地描述。
采用模式定义语言(SDL)作为描述类型的句法。SDL类似于C#中用于定义类的子集,或者SQL的数据定义语言(DDL)子集。SDL是以XML表达的(但它不是基于XSD的)。贯穿此描述,将适用SDL片段来说明所描述的概念。
标量类型在某种意义上是类型系统中可用的最简单的类型。它们不具有系统可见的任何内部结构。标量类型标识单个值。CDM定义3种标量类型:简单类型、枚举类型和Ref(引用)类型。
简单类型被内建在本系统中,原始类型由本系统提供。CLR值类型被作为CDM中的简单类型使用——诸如System.String(系统.串)、System.Boolean(系统.布尔)、System.Byte(系统.字节)、System.Intl6(系统.16位整数)等等。CDM还支持System.Storage(系统.存储)和System.Data.SqlTypes(系统.数据.Sql类型)名字空间中所定义的许多类型(System.Storage.ByteCollection、System.Data.SqlTypes.SqlSingle……)。
枚举类型定义符号名的集合——诸如(红,蓝,绿)或(春,夏,秋,冬)等。枚举类型的实例具有范围在此集合上的值。
Ref类型的实例是定义实体的值。对Ref类型的描述在下文中提供。
简单类型可被用来构建更加复杂的类型。复合类型可具有名字或可保持匿名。
命名的复合类型具有名字和一组成员。成员可简单至一名字和标量类型。每个成员都是标量类型(在此例中是简单类型)。诸如这些数据成员等数据成员可被称为属性。
复合类型中可存在两个其它种类的成员:方法和经计算的属性,它们将在下文中描述。复合类型还可包含其它复合类型。
匿名复合类型,如其名所示,在结构上类似于复合类型,但不能被用来声明基于其的属性。匿名复合类型被作为查询结果返回(诸如在从实体投射字段子集的查询中等)。它们存在于CDM中以确保查询封闭。SDL不具有用于声明这些类型的句法。
注意命名和匿名复合类型之间的一个区别:具有完全相同的结构但有不同名字的两个命名的复合类型被视为是不同的类型。但是具有完全相同的结构的两个匿名复合结构被视为是同一类型。
实体类型在结构上类似于复合类型,因为它是从标量类型和其它复合类型构建出来的类型。但是,语义上和操作上它是非常不同的——实体是可经由标识(各种操作的一致性单元等)唯一引用的。实体类型是以类似于复合类型的方式定义的。
集合存储内联类型的0个或多个实例。在以下示例中,考虑Person(个人)类型:此类型存储关于一个人的联系信息。通常,名字、家庭地址、工作地址、家庭电话、工作电话、移动电话以及电子邮件ID(取最常用的子集)被存储。注意,在此列表中,有两个地址和三个电话号码。可使用CDM将这些建模为集合,如下例中所示:
1.<ComplexType Name=″Person″>
2.<Property Name=″Name″Type=″String″/>
3.<Property Name=″EmailID″Type=″String″/>
4.<Property Name=″Addresses″Type=″Collection(Address)″/>
5.<Property Name=″PhoneNumbers″Type=″Collection(String)″/>
6.</ComplexType>
第4行为Addresses(地址)字段定义Address(地址)元素的集合;第5行为PhoneNumbers(电话号码)字段定义String(串)元素的集合。因此,该个人可具有例如一个Person对象下的两个集合——Addresses和PhoneNumbers。Addresses集合包含Address类型的两个实例,而PhoneNumbers集合包含String类型的两个实例。在CDM中,可为简单和复合类型定义集合。
具有数组的语义的集合常常是合乎需要的。数组是其中元素被排序和索引的集合。注意,数组是有序的,但不必是经分类的。例如,[1,4,5,3]是有序集合,但却未经分类。它是有序的,因为可要求第二个元素并能确保(在不存在显式改变的前提下)获得‘4’。
当集合类型的<Property>上的<Collection>子元素的Array(数组)属性被设为真时,就使其成为数组。Array是其值默认为“false”的可选属性。
通常,应用程序所使用的数据模型具有许多不同的类型。这些类型中的一些将完全脱离的概念建模,例如Customer(顾客)和Order(订单)。这些类型不共享任何成员。但其它类型将相互具有少量相似性但仍不相同的概念建模。例如,考虑Customer(顾客)和Employee(雇员)。近似它们将完全不同的概念建模,但是它们之间仍有潜在的公用性线索——两者都具有地址、电话号码和名字属性。它是与某人取得联系所需的信息。换言之,它是联系信息。
图20示出CDM支持类型继承的概念。集成允许一个类型从另一个类型继承属性、方法和经计算的属性。在此例中,Employee和Customer继承Contact(联系人)。在这里,Contact被成为超类型或基类型。Employee和Customer被成为子类型或派生类型。子类型化不需停止在单个等级;子类型也能够成为另一个类型的父类型——例如,Employee可以是Manager的基类型,Customer可以是PreferredCustomer(优先顾客)的基类型,等等。以此方式,可以构成整个继承分层结构,如图20中所示。
即使上例仅示出属性的继承,但是派生类也从它们的基类型继承方法和经计算的属性。CDM遵守CLR中继承方法(行为)的语义。下例中示出以上继承分层结构的(部分)SDL规范:
1.<ComplexType Name=″Contact″>
2.<Property Name=″Name″Type=″String″/>
3.<Property Name=″Address″Type=″Address″/>
4.<Property Name=″Phone″Type=″String″/>
5.</ComplexType>
6.<ComplexType Name=″Customer″BaseType=″Contact″>
7.<Property Name=″CustomerID″Type=″String″/>
8.<Property Name=″CompanyName″Type=″String″/>
9.</ComplexType>
10.<ComplexType Name=″PreferredCustomer″BaseType=″Customer″>
11.<Property Name=″PreferenceCode″Type=″String″/>
12.<Property Name=″CreditLimit″Type=″Decimal″/>
13.</ComplexType>
14.<!--Similar Declarations for Employee and Manager-->
如上文中所说明,继承的一个目的是在多个类型中间共享类属概念。继承的另一个目的是可扩展性。甚至在ISV实现和部署了继承分层结构以后,顾客认可经由继承来扩展类型以适应于他们的目的。使此可扩展性生效的关键因素是值可代换性(也成为多态性)的概念:派生类型的每个实例也是基类型的一个实例。因此,如果Manager是从Employee派生的,则Manager的每个实例也是Employee的一个实例。因此,当查询所有雇员(基类型)时,所有的经理(派生类型)也被返回。
图21示出适用于此实现的CDM类型的分类法。在此节中,提供了CDM类型系统内类型的适当分类。当在其较大的语义上下文中检查数据时,几乎所有数据在其类型的域上都会以这样或那样的形式被约束。CDM允许在不同类型上指定各种约束。
简单类型约束。简单类型的可允许的值集能以各种方式来限制,诸如限制长度(串和二进制)、精度、范围(小数)、等等。默认的约束允许指定默认值。校验约束指定属性值上的布尔表达式。如果此表达式的值为假,则该属性值无效。
集合类型约束。以下约束在集合上被支持:ElementOccurs(元素出现)约束指定集合的最小和最大基数。Unique(唯一的)约束可被用来确保集合元素值的唯一性。ElementConstraint(元素约束)可被用来指定对集合底层的类型的约束(例如,如果定义类型Decimal(小数)的集合,则此<ElementConstraint>可被用来指定精度和范围。
Check(校验)约束指定一布尔查询表达式。要使集合被视为有效,则此表达式的值应为真。注意,此约束适用于整个集合属性,而不是集合内的个体元素。
建议类型设计者总是对Collection(集合)定义唯一的约束,特别是在预期该集合将包含大量元素的情况下。在运行时,当集合的一个元素被更新时,唯一性约束使本实现能够将单个元素作为更新的目标,而不是重写整个集合。这减少了更新时间和网络通信量。
派生类型约束。通过使用派生类型约束就能够约束派生类型内的基类型属性。考虑各个航空公司所提供的常用的飞行计划。例如,联合航空公司有一个成为Mileage Plus的计划。此计划有数个会员等级——1K会员、首席执行官会员、首席会员和“普通”会员。为了成为首席会员,必须至少飞行25,000英里或30个付费段;对于首席执行官和1K而言,这些数字分别是50,000/60和100,000/100。注意,当定义派生类型约束时,这些约束应当与基类型约束一致。例如,如果基类型的collection(集合)字段上的ElementOccurs(元素出现)约束指定最小值为1而最大值为50,则派生类型约束应有大于1的最小值和小于50的最大值。
可为空性约束。简单和复合类型两者都可以指定可为空性约束。这意味着此类型的实例可存储NULL值。这是由<Property>元素上的Nullable属性指定的。
注意,集合属性不应被设为可为空,而可为空即使在复合类型的属性上也是被允许的。该Nullable属性的默认值是“true”。
迄今,已经提供了由此替换实现的CDM类型系统所提供的核心建模能力。CDM是内建类型、定义复合类型、创建枚举、表达约束继承和值代换(多态)的能力的富集。
一旦这些类型被设计并部署在系统中,应用程序即开始创建和操纵这些类型的实例。对类型实例执行诸如复制、移动、查询、删除、备份/恢复(对于经持久化的数据)等各种操作。以下,描述CDM的操作语义。
类型和实例。类型定义数据的结构。实际的数据被存储在类型实例中。在例如面向对象的语言中,类型和实例被成为类和对象。
图22示出CDM的此实现中的类型和实例的概念。图22中的椭圆是实际数据,而立方是类型,即元数据。
实体和内联类型。再来看由假定的LOB应用程序所使用的数据,一方面,它有诸如Customer(顾客)和Order(订单)等类型,而另一方面,它还具有诸如Address(地址)和AddressLine(地址线)等类型。这些类型中的每一个都具有一个结构,每一个结构都可被解构为多个字段。但是,在Customer类型和Address类型之间有两个关键差异。Customer类型的实例具有独立存在性,而AddressType的实例仅存在于例如Customer类型实例内。
在这个意义上,Customer是顶层类型;此类型的实例独立存在,被独立引用(“请示出公司名是……的顾客”),并被独立处理。另一方面,Address是被包含的类型——其实例仅存在于顶层类型实例的上下文内,例如,“顾客的地址”,或“订单的送货地址”等等。
Customer类型具有标识,而Address类型没有。Customer的每个实例都可被唯一标识,且可对其进行引用。Address不能在诸如Customer等类型外被单独标识。此基本区别在CDM中由实体类型和内联类型的概念形式化。在以上LOB的例子中,Customer是实体类型,而Address是内联类型。
实体的特征。即使实体类型在结构上类似于复合类型,但是它具有数个区分其与内联类型的特征。这些特征附于实体实例特定的操作语义。Entity(实体)是实体类型的实例。实体是可独立存在的CDM数据的最小单元。这隐含以下特征:
标识:每个实体都具有一个标识。此标识被确保在其生命期中引用唯一的实体。标识的存在隐含必须对其实体进行引用。
实体标识是实体是“顶层”数据单元的原因所在——每个实体都是可引用的,因此可在查询、更新以及其它操作中使用。
一致性单元:查询和更新被保证在实体等级是一致的。实体是大多数CDP操作的目标——诸如复制、移动、删除、备份、恢复等等。这些操作并不将内联类型作为目标。
事务单元:事务在实体的等级发生。换言之,实体可被单独处理,但内联类型总是在包含实体的上下文内被处理。
关系的单元:关系是在实体、而不是内联类型的等级被指定的。实体经由合成和引用关联相关;内联类型实例不可以是关系的源或目标。
持久化的单元:实体是持久化的单元。内联类型并不将它们自身持久化,而是仅作为实体的一个部分持久化。实质上,内联类型通过值来起作用——因子,它们必须作为实体的一个部分被存储。
但是注意,CDM本身既不蕴含也不要求实体被持久化。无论实体是在存储器中还是被持久化,CDM都保持一致。
共享的单元:实体是本数据模型中共享的单元。例如,LOB应用程序有产品的概念。供应商提供一种或多种产品;订单有一个或多个产品。为了避免产品信息的冗余存储,可定义产品实体,而对此实体的实例的引用可被插入到订单和供应商实体内。如果另一方面,产品是内联类型,则订单和供应商两者都必须包含产品实例,这导致冗余存储以及随之而来的插入、删除和更新异常。
图23示出如何使用SDL声明实体和内联类型。实体是使用<EntityType>(实体类型)元素声明的,如第14-27行中所示。实体类型的属性是内联类型(按照定义)。有数种内联类型。标量类型:回忆上文,标量类型可被进一步细分为简单、Ref和枚举类型。简单内联类型被内建在CDM框架中——在它们已被声明并可供使用的意义上。在图23的示例中,在第8、9、10、11、12、15和18行中示出这些类型的使用。
枚举类型是使用<EnumerationType>(枚举类型)元素来声明的,如第1-5行所示。一经声明,这些类型即可在任何复合或实体类型(见第8行)中使用。
XML和FILESTREAM类型(此例中未示出)是内建类型,但严格来说不是标量(即,本数据模型可在有限程度上推理这些类型的内部)。
复合类型是使用<ComplexType>(复合类型)元素来声明的,如第7-13行所示。复合类型的属性可以是任何内联类型——标量、集合、或复合类型。一经声明,复合类型即可在任何复合或实体类型内被使用。
集合类型是使用Collection(集合)关键字后跟内联类型的名字来声明的。在第22行示出了AddressType(地址类型)的集合。
如前文中所述,实体的一个基本特征是它具有唯一的标识这一事实。实体标识被保证在实体更新后仍然存活,并且在其整个生命期都继续标识同一实体。实体还具有关键字属性。此关键字是由一个或多个属性合成而成。要求实体关键字在EntitySet(实体集)内是唯一的。实体关键字可被各实现用来生成实体标识。实体关键字是使用<EntityType>(实体类型)元素的“Key”(关键字)属性来指定的。只要关键字中至少又一个属性是不可为空的,标量(包括Ref类型)或复合类型的属性的任何集合就可为实体类型起到关键字的作用。集合类型的属性不应是关键字的一部分。
注意,仅实体类型分层结构的基类型可指定关键字。派生类型自动从基类型继承该关键字。这支持使值可代换性(多态性)确定性地起效。
实体应用。因为实体具有标识,所以实体引用是可能的。在CDM的这一实现中,实体应用主要被用于关系导航。例如,顾客实体经由顾客订单关系与订单实体相关。给定一个订单,就能够使用该订单实体上的一特殊属性(成为关系属性)来找到相关联的顾客。此属性是Ref(顾客)类型。关键字Ref标识这是对另一种实体类型的应用。
在实体类型或复合类型内部显式定义Ref类型的属性也是可能的。此属性起到对被引用的实体的“指针”的作用。Ref类型的属性的存在并不定义或蕴含包含实体类型和被引用实体类型之间的关系。关系不应被显式定义。在经持久化的实体的情形中,引用是持久的。
内联类型。实体或者在顶层独立存活,或者被包含在实体集内。实体不能字节嵌入另一实体或复合类型内。另一方面,复合类型可被嵌入另一复合类型或实体类型内。即,实体和复合类型两者都可具有其类型为复合类型的属性。
标量类型和集合也可被嵌入其它复合类型或实体类型中。这就是复合类型、集合和标量类型被统称为内联类型的原因所在。
实体集和实体容器。这里提供两种情形来帮助描述实体实例存活在何处。实体实例被持久化在某个数据存储中。CDM本身被仔细构思制作为存储不可知的。在理论上,它可被在各种存储技术上实现。实体还具有存储器中的透明存在。CDM并不指定它们如何在存储器中被具体化,以及如何令它们可供应用程序使用。应用程序通常处理各种类型的实体的多个实例。这些实例或可在顶层自己独立存活,或可被包含在实体集内。实体集包含给定类型(或其子类型)的实体的实例。实体关键字在实体集内是有意义的。实体集内的每个实体都应具有唯一的关键字。
实体容器是一个或多个实体集的分组。实体容器被用于界定关联和合成关系的范围。实体容器还是在其上定义了备份、恢复、用户、角色和其它此类语义的持久化和管理单元。
模式是用于持类型化、关系和其它名字的组织解构。它提供了在其内通常的名字唯一性规则适用的名字空间。模式是使用<Schema>(模式)元素来定义的,并且是SDL文件的登程元素。所有实体、关系、复合类型等都是在模式内定义的。在其它地方定义的模式可用<Using>元素来导入,而在其中定义的类型可使用它们完全限定的名字来引用。通过使用如下形式的完全限定的句法来直接使用另一个模式中的类型(例如,无需<Using>元素)也是可能的:名字空间.类型名。<Using>是用于减少类型创建的句法捷径。可通过提供在任何已部署的模式中定义的类型的完全限定的名字来使用该类型。
一旦类型被写入SDL,CDM规范即对应该发生什么保持缄默。就被写入SDL的类型而言,实现了CDM的CDP提供取SDL描述并将这些类型部署在存储上的工具。取决于存储的特性,此部署可能涉及存储级抽象的创建。例如,如果存储是RDBMS,则部署将创建对应于模式和类型的数据库和表;它还可能创建约束和数据模型强制实施的SQL代码。或者,可通过将数据库的表映射到CDM类型来将CDP配合现有数据库使用。
除了创建存储级的项目以外,CDP工具还将生成对应于类型和关系的CLR类。该实现可使用<Schema>(模式)元素的Namespace(名字空间)属性来创建用于界定这些类的范围的CLR名字空间。CDP还支持将现有对象模型映射到CDM类型。注意,CDM类型不要求存储。存储器中的部署是可能的。
任何有意义的现实世界数据的集合总是具有其组成部分中间的关系。例如:顾客下了一个或多个订单,订单包含订单细节,产品可来自一个或多个供应商,等等。在此句中,数据以斜体示出,而它们中间的关系以下划线示出。很清楚,关系的概念是构成任何数据建模努力的组成部分。关系型模型并不显式地支持关系;主关键字、外来关键字和引用完整性提供了实现关系所蕴含的部分约束的工具。CDM的关键字值是它支持关系为本数据模型本身内的一等概念的手段。这允许更简单和丰富的建模能力。关系支持还扩展至CDM查询,这允许关系在查询中被显式引用,并提供基于关系的导航能力。
图24示出CDM所支持的许多种关系。在现实世界的建模情形中,存在着许多不同种类的关系——它们具有不同的度数(一元的、二元的……),多重性(1-1、1-多、多-多……)以及语义(包含、对等……)。CDM具有将所有这些不同类型的关系建模的能力。在CDM中,关系是在实体的等级被定义的。有两种将实体相关的方式:关联和合成。关联将“对等”关系建模,而合成将“父子”关系建模。
建模语义可要求相关实体表现出各种操作的单元的行为。例如,考虑图24的订单和订单线之间的包含关系。预期对订单的复制或串行化操作也会导致相关联的订单线的复制或串行化是合理的。CDM至少定义了5种操作:删除、复制、串行化、保护和锁定。可响应于这些操作,在有关实体上指定行为。注意,除了引用关联和合成以外,还存在另外两种将实体相关的方式:条件关联和关联实体。
关联是数据建模中最常用和最有用的关系。关联的经典示例是Customer(顾客)和Order(订单)实体之间的关系。通常,此关系包括每个订单与恰好一个顾客相关联的多重性。每个顾客有0个或多个订单。该关系还可包括操作行为:将有关实体如同作为一个单元来操作是有用的。例如,当具有未结订单的顾客被删除、复制或串行化时,对应的订单也被删除、复制或串行化可能是合乎需要的。
<Association>(关联)元素被用来将此关系建模。
1.<EntityType Name=″Order″Key=″OrderId″>
2.<Property Name=″OrderId″
3. Type=″String″/>
4.<!--Other Properties-->
5.</EntityType>
6.
7.<EntityType Name=″Customer″Key=″CustomerId″>
8.<Property Name=″CustomerId″
9. Type=″String″/>
10.<!--Other Properties-->
11.</EntityType>
12.
13.<Association Name=″Order_Customer″>
14.<End Type=″Order″Multiplicity=″*″/>
15.<End Type=″Customer″Multiplicity=″1″>
16.<OnDelete Action=″Cascade″/>
17.</End>
18.</Association>
<End>上的“Type”(类型)属性定义参与此关系的实体类型。
“Multiplicity”(多重性)属性定义该端点的基数。在此例中,指定了有恰好一个顾客(第15行上的值为“1”)对应于0个或多个订单(第14行上值为“*”)。此属性的其它值有:
●“0..1”——0个或1个
●“1”——恰好1个
●“*”——0个或多个
●“1..*——1个或多个
●“n”——恰好n个
●“n..m”——在n和m之间,包括n和m,其中n小于或等于m。
第16行上的<OnDelete>元素指定删除操作的操作行为。它具有一个属性,即可具有3个值中的一个的“Action”(行动)。Cascade(级联)-删除属于该顾客的所有订单。这即是上例中所示出的情况。Restrict(限制)-防止在存在未结订单的时候删除顾客。RemoveAssociation(移除关联)-移除订单和顾客之间的关系。注意,为了具有一致的语义,<OnDelete>元素仅在关系的各端点中的一个上被允许。
CDM允许在如下的其它操作上指定行为:复制、串行化、保护和锁定。它们都遵循如为删除行为示出的同一模式——通过使用<OnOperation Action=”...”>形式的子元素。该操作行为指定既可在关联上也可在合成上实现。
关联将对等关系建模。合成将包含(父子)关系建模。合成的经典示例有Order(订单)和对应于它的Line(线)之间的关系。订单线完全受其父订单的控制。在语义上,它在包含订单以外没有任何有意义的存在。删除订单就强制删除所有订单线。因此Order和Line实体被称为是经由合成(即,Order是由一个或多个Line实体合成而成的)相关的。
合成关系具有以下3个特征:
唯一性:给定的父实体的子实体在它们自己中间应当具有唯一的关键字。例如,属于一Order的Line应具有唯一的关键字以将其与同一Order的所有其它Line区分开来。实现此特征的常用方法是通过将子实体的关键字和父实体的标识相结合来派生子实体的标识。
级联删除:删除父实体就删除了子实体。
多重性:父实体的多重性是1。这表达了Line不能在没有Order的情形中存在这一语义。
<Composition>(合成)元素被用来将合成建模。
注意,无需为父实体指定“多重性”,因为这对于合成而言总是为1。实际上,为合成的父实体指定除1以外的“多重性”是错误的。可为子实体指定多重性,它可具有上述的任何值。
可在合成上指定操作行为——为复制、串行化、保护和锁定操作。注意,无需指定<OnDelete>,因为合成总是具有级联的删除语义。以下是错误的:指定<OnDelete Action=”x”>其中x不等于“Cascade”,以及在子端点上指定<OnDelete>。
将相关实体如同作为一个单元来操作常常是有用的。例如,当复制Order实体时,令对应的Line实体也被复制通常是合乎需要的。CDM允许为以下各种操作指定这些行为:删除、复制、串行化、保护和锁定。所使用的一般模式是定义<OnOperation Action=”value”/>形式的子元素。操作可以是删除、复制、串行化、保护、或锁定。取决于操作,“Action”的值可以是Cascade、Restrict、RemoveAssociation等等。
在指定操作语义时应记住以下几点:所有<OnOperation.../>元素仅应在个关系端点中的一个上指定。(例如)在Customer上指定<OnDelete>并在Order上指定<OnCopy>可能是不合法的。这里的概念模型是关系的各端点中的一个是处于控制角色;操作语义从该实体级联至所有其它端点。无需为合成指定<OnDelete.../>。按照定义,删除合成的父实体就将该操作级联至子实体。所有<OnOperation.../>元素都应在合成的父实体上指定。指定<OnDelete>或<OnSecure>且Action=”Cascade”的端点的多重性应当为“1”。否则,语义就不一致。
CDM中的关系是在参与其间的类型以外定义的。这些类型本身无需具有特殊属性来建立关系。例如,Order_Customer(订单_顾客)关系可使用顶层<Association>元素来指定;Customer和Order类型内不具有属性或其它标识性标记来指示它们参与了彼此的关系。
可想像用于在查询或API中从关系的一端导航到另一端的各种机制。例如,CDP API具有对应于每个关系的静态类;此类具有可被用于导航的方法。举Order_Customer(订单_顾客)为例,该类将被命名为Order_Customer(订单_顾客),而方法将被命名为GetOrdersGivenCustomer(...)诸如此类。
但是,最直观的方法是在关系的任一端上实际具有一属性。例如,如果Order有一称为Customer的属性,则导航就是访问属性那么简单。为实现关系导航的这一简单模式,CDM具有关系属性的概念。它们被定义在实体上,用于表达对相关实体的导航的目的。关系属性是使用<RelationshipProperty>(关系属性)元素来定义的。<RelationshipProperty>元素有3个属性:“Name”(名字)定义该属性的名字。可在查询或API中使用此名字来导航到关系的其它端点。“Relationship”(关系)指定关联或合成的名字。“End”(端点)标识导航目标。既可为关联关系,也可为合成关系定义关系属性,并可在关系的任一端定义关系属性。
注意,和“常规”属性不同,关系属性不具有“Type”(类型)属性。这是因为它们被隐式地定义为实体Ref(或实体Ref的集合)的类型。此实体引用被用来导航到目标实体。
取决于其作为目标的端点的多重性,关系属性或是单个实体Ref,或是多个实体Ref的集合。以下表格示出“Multiplicity”(多重性)可能的值,以及对应的关系属性的类型。
Multiplicity(多重性) | 关系属性的类型 |
“0..1” | Ref(实体类型),可为空=”true”(真) |
“1” | Ref(实体类型),可为空=”false”(假) |
“*” | Collection(Ref(实体类型)),<ElementOccurs Minimum=”0”Maximum=”unbounded”/> |
“1..*” | Collection(Ref(实体类型)),<ElementOccurs Minimum=”1”Maximum=”unbounded”/> |
“n” | Collection(Ref(实体类型)),<ElementOccurs Minimum=”n”Maximum=”n”/> |
“n..m” | Collection(Ref(实体类型)),<ElementOccurs Minimum=”n”Maximum=”m”/> |
如上文中所述,实体可在顶层“独立”存在,或驻留在实体集(其本身在实体容器内)内。在关系的两个端点的上下文内考虑这一情况。在“自由流动的”实体的情形中,关系的两端存在于实体的海洋内的某个地方。考虑当实体被分组为多个实体集时。例如,考虑以下模式片段:
1.<EntityContainerType Name=″LOBData″>
2.<Property Name=″Orders″Type=″EntitySet(Order)″/>
3.<Property Name=″GoodCustomers″Type=″EntitySet(Customer)″/>
4.<Property Name=″BadCustomers″Type=″EntitySet(Customer)″/>
5.</EntityContainerType>
6.<EntityType Name=″Customer″Key=″CustomerId″>
7....
8.</EntityType>
9.<EntityType Name=″Order″Key=″OrderId″>
10....
11.</EntityType>
12.<Association Name=″Order Customer″>
13.<End Type=″Order″Multiplicity=″*″/>
14.<End Type=″Customer″Multiplicity=″1″>
15.<OnDelete Action=″Cascade″/>
16.</End>
17.</Association>
实体容器(LOBData)有3个实体集:Orders(订单)、GoodCustomers(好顾客)和BadCustomer(坏顾客)。GoodCustomer中的所有顾客实体具有相当好的信用,并因此被认为是值得下订的。BadCustomers在付款上有拖欠。这里明显的商务规则是只想要GoodCustomers下Order。换言之,限制Customer_Order(顾客_订单)的范围以使只有GoodCustomers中的实体能够具有Orders。此外,所有Orders必须驻留在Orders实体集中。这是通过在<EntityContainerType>(实体容器类型)内使用<Scope>(范围)元素来实现的,如下所示:
1.<EntityContainerType Name=″LOBData″>
2.<Property Name=″Orders″Type=″EntitySet(Order)″/>
3.<Property Name=″GoodCustomers″Type=″EntitySet(Customer)″/>
4.<Property Name=″BadCustomers″Type=″EntitySet(Customer)″/>
5.<Scope Relationship=″Order_Customer″>
6.<End Type=″Customer″EntitySet=″GoodCustomers″/>
7.<End Type=″Order″EntitySet=″Orders″/>
8.</Scope>
9.</EntityContainerType>
<Scope>(第5行)元素有一个属性——“Relationship”(关系)——它标识其端点被界定范围的关联或合成。与关系的每个端点一一对应的<End>子元素被用来指定将此端点的范围所界定到的实体集。在第6行上可以看到,Customer端点的范围被界定到GoodCustomer实体集;而在第7行上,Order端点的范围被界定到Orders实体集。
如果被部署的模式具有实体容器,则每个关系的每隔端点的范围被界定到该实体容器内一唯一的实体集。如果显式地缺少对应于给定关联或合成的<Scope>从句,则本实现将端点的范围界定到默认的实体集。进行隐式界定范围的方式是实现定义的。
CDM允许为合成指定更加严格的范围界定规则。考虑Order和Line之间的合成。在不存在对应Order的情况下存在Line是无意义的。因此,包含Line实体的实体集应强制实施每隔Line都应是唯一的Order的子实体这一商务规则。这是使用<Requires>(要求)元素来实现的。
1.<EntityContainerType Name=″LOBData″>
2.<Property Name=″Orders″Type=″EntitySet(Order)″/>
3.<Property Name=″OrderLines″Type=″EntitySet(Line)″>
4.<Requires Relationship=″Order_Line″/>
5.</Property>
6.<Property Name=″ShipmentLines″Type=″EntitySet(Line)″>
7.<Requires Relationship=″Shipment_Line″/>
8.</Property>
9.<Property Name=″Customers″Type=″EntitySet(Customer)″/>
10.<Scope Relationship=″Order_Line″>
11.<End Type=″Order″EntitySet=″Order″/>
12.<End Type=″Line″EntitySet=″OrderLines″/>
13.</Scope>
14.<Scope Relationship=″Shipment_Line″>
15.<End Type=″Order″EntitySet=″Order″/>
16.<End Type=″Line″EntitySet=″ShipmentLines″/>
17.</Scope>
18.</EntityContainerType>
19.<EntityType Name=″Customer″Key=″CustomerId″>
20....
21.</EntityType>
22.<EntityType Name=″Order″Key=″OrderId″>
23....
24.</EntityType>
25.<EntityType Name=″Line″Key=″LineId″>
26....
27.</EntityType>
28.<Composition Name=″Order_Line″>
29.<End Type=″Order″Parent=″true″/>
30.<End Type=″Line″Multiplicity=″*″/>
31.</Composition>
32.<Composition Name=″Shipment_Line″>
33.<End Type=″Order″Parent=″true″/>
34.<End Type=″Line″Multiplicity=″*″/>
35.</Composition>
以下范围界定的要求被上例所满足:Shipement_Line(送货_线)的Line端点的范围应被界定到ShipementLines实体集(第16行)。ShipmentLines中的每个Line都应是Shipement_Line合成的一个端点。这是在第7行使用<Requires>元素来实现的。此元素具有一属性“Relationship”(关系),它标识该合成。Order_Line的Line端点的范围应被界定到OrderLines实体集(第12行)。OrderLines中的每个Line都应是Order_Line合成的一个端点(第4行)。如果实体集中没有出现<Requires>(要求)元素,则它不被约束为具有属于任何给定合成的实体。这在许多建模情形中是很重要的要求。注意,<Requires>元素可被用来仅指定一个合成名字。
对CDM的替换描述迄今对实体确切驻留在何处是不可知的。这些实体可驻留在存储器中,或实际上被持久地持久化在存储中。核心CDM不蕴含、不要求、也不关心这些实体驻留在何处——这些实体可驻留在存储器中,或者被持久化。以下是对经持久化的实体、以及CDM如何支持持久化的概念的描述。
实体容器是实体的顶层组织单元,并且是定义持久化语义的层次所在。实体是可被持久化的数据的最小单元。通常,经持久化的实体具有与其相关联的操作语义——诸如复制、移动、备份、恢复、串行化、等等。实体容器是可在其上定义这些语义的持久化的单元。它还是可在其中定义诸如备份、恢复、用户、角色等管理概念的组织单元。在这个意义上,实体容器类似于SQL数据库。
实体容器具有一个或多个实体集,其中驻留了所有的实体。因此,定义实体容器的实例就起动了存储分配过程。通常,类型设计者定义实体容器类型。CDM本身并不定义如何从该类型获得实体容器实例,以及如何将此实例映射到底层的存储解构(诸如实体容器→数据库,实体集→一个或多个表,等等)。CDP定义实体容器(以及其中所包含的类型)到SQL存储之间的规定的映射关系集合。CDP还允许同样情况的非规定的(用户可指定的)映射关系。
一般而言,应用程序能以其所选择的任何方式来组织实体——CDM不指示任何特定组织解构。但是当谈到经持久化的实体时,实体、实体集以及实体容器的语义蕴含某种解构组织。当实体被持久化:每隔实体都应存活在一实体集内;每个实体集应存活在一实体容器内;而实体容器应存活在顶层。
图25示出CDM中的经持久化实体的解构组织。这是数据的逻辑表示,而不是物理表示。所示的每个实体集都可被映射到例如表。此表几乎可以肯定具有用于表示关系的附加列。可以想像Orders(订单)实体集被映射到具有CustomerID(顾客ID)列的Orders表。因为CDM不规定存储映射关系,所以描述必须维持在逻辑的层次。可以看到,每个实体都驻留在实体集内。此外,每个实体集都被包含在实体容器(在实例图中是MyLobDB)内。为了完成这一对结构组织的描述,注意CDM存储由一个或多个实体容器组成。
不是所有的应用程序开发者都定义类型;他们中的大多数使用已由其它ISB定义和部署的类型。这里提供的是一种用于使类型的用户能够以特定方式扩展预定义的类型而不会损害原始类型的保真度的机制。实体扩展和可扩展枚举是CDM中所提供的用于允许类型的独立扩展的两种手段。
图26示出在CDM的这一实现中实体扩展的使用。为引发实体扩展的需要和使用,考虑ContactType(联系人类型)。它具有名字、地址和电话号码的标准属性。假定GPS(全球定位系统)软件ISV想要将纬度和经度信息添加到此类型中。实现这一目的的一种方法是修改实际的ContactType;这是不合乎需要的,因为系统中有此类型的许多其它用户。另一种方法是从ContactType派生出称为ContactWithGPSType(带有GPS的联系人类型)的一个新的类作为子类型。这将意味着,AddressType(地址类型)的所有用户现在必须改变他们的代码以使用ContactWithGPSType;此外,GPS信息不能被添加到系统中现有的联系人——它们必须被重新强制类型转换为这一新的类型。
CDM使用实体扩展的概念很好地解决了这个问题。实体扩展是可引用的、结构化的类型;它们可包含实体可包含的任何成员——属性、方法、以及经计算的属性。扩展是使用<EntityExtensionType>(实体扩展类型)来定义的。扩展类型不享有继承。<EntityExtensionType>可包含<EntityType>中可出现的任何元素。属性名在所有扩展上无须是唯一的,甚至在被扩展的类型的属性上也无须是唯一的。
生命期管理。扩展被紧密地绑定到实体,因为每个扩展类型指定了它所扩展的实体类型。所有实体扩展都具有Ref(T)类型的名为“Entity”的默认属性,其中T是ExtendsType(扩展类型)的值,它指向此实体是其扩展的实体实例。这在图26中被示为扩展内的实体关键字。
扩展在其所扩展的实体外不具有任何独立的存在。CDM要求扩展的生命期管理是实现的一个部分——即,实现将在对应的实体被删除时删除所有扩展。在这个意义上,扩展表现出它们是对应实体的合成的行为。即使实体扩展实例被视为包含实体所定义的数据的内聚单元的一个部分,但是除非由应用程序使用事务显式地管理,否则在对实体和扩展的改变上没有任何一致性保证。
实例管理,如果InstanceManagement=”Implicit”,则扩展中所定义的所有属性应当或者是可为空的,或者指定了默认值,或者是最小出现约束为0的集合类型。注意,一元内联类型的属性不能指定默认值,因此必须是可为空的。这允许对扩展执行查询,就好像它总是存在的。
如果InstanceManagement=”Explicit”,则应用程序应当使用在公用数据模型的查询语言中定义的操作来将扩展添加到实体实例,或从实体实例移除扩展。还提供了一种测试扩展是否存在的手段。
防止扩展。类型设计者可能想要防止创建给定类型的扩展。这可使用<EntityType>(实体类型)或<AssociationEntityType>元素上的“Extensible”(可扩展)属性来实现。当被设为“true”时(这是默认值),即可为此实体定义<EntityExtensionType>(实体扩展类型)。这可被设为“false”以防对此类型的扩展。
可扩展枚举和枚举别名。当供应商或它们的用户发展出一组已部署的类型时,优势需要向现有的枚举添加名字。例如,考虑称为ToyotaCarModels(丰田汽车模型)的枚举,它在2795中可能具有以下名字:[Corolla,Camry,MR2,Celica,Avalon]。但是,在2005年,它需要这些额外的名字:Prius,Echo,Matrix,以及Solara。
枚举可使用<EnumerationExtensionType>元素来扩展。这在以下示例中示出:
1.<EnumerationType Name=″C″Extensible=″true″>
2.<EnumerationMember Name=″P″/>
3.<EnumerationMember Name=″Q″/>
4.<EnumerationMember Name=″R″AliasesMember=″Q″/>
5.</EnumerationType>
6.
7.<EnumerationExtensionType Name=″D″ExtendsType=″C″>
8.<EnumerationMember Name=″Q″/>
9.<EnumerationMember Name=″S″/>
10.<EnumerationMember Name=″T″AliasesMember=″C.R″/>
11.</EumerationExtensionType>
12.<EnumerationExtensionType Name=″E″ExtendsType=″C″>
13.<EnumerationMember Name=″T″/>
14.<EnumerationMember Name=″U″AliasesMember=″D.T″/>
15.</EnumerationExtensionType>
在第7行中,枚举类型‘C’被扩展以添加名字‘Q’、‘S’和‘T’。在第12行,通过添加名字‘T’和‘U’来对‘C’进行单独的扩展。因为枚举成员总是受到底层的基类型或枚举扩展类型的限制,所以在扩展中复制名字是可以的(此例中的D.T和E.T)
现有枚举成员名有别名常常是有用的。这个情况的经典例子出现在季节枚举中。在美国,季节是[spring(春),summer(夏),fall(秋),winter(冬)]。在英国或印度,“fall”被称为“autumn”。能够同时定义这两个名字,但令它们在概念上映射到同一枚举成员是合乎需要的。<EnumerationMember>(枚举成员)元素中的“AliasesMember”(别名成员)定义了对应于现有名字的别名。在此例中,C.R、D.T和E.U都是C.Q的别名,因此不表示独特的名字。
图27示出替换实现中阐明与类型相关的模型的语义的CDM元模型片段。
图28示出替换实现中阐明与属性相关的模型的语义的CDM元模型片段。
图29示出替换实现中阐明与关联相关的模型的语义的CDM元模型片段。
图30示出图29的UML合成图,该图示出其中所示关系的数个方面。
图31示出替换实现的高级关系。
CDM类型系统
下表以抽象句法的形式给出CDM类型系统,并展示出本系统的递归结构:有限语法所蕴含的合法语句的有限集合。首先,完全给出本类型系统,然后再给出说明文本和小例子。
结构类型
structuralType∷=simpleType|tupleType|collectionType
simpleType∷=scalar|enum|cname|sname|Ref<ename>
tupleType∷={...,structuralType aname[#],...}
collectionType∷=(列表|集合|多重集|...)<structuralType>
标称类型
declaration∷=typeSynonym|complexType|entityType|entitySet|
entityContainer|binaryRelation
typeSynonym∷=类型shame=structuralType
complexType∷=复合类型cname[extends cname][constraint]
structuralType
entityType∷=实体类型ename[extends ename][constraint][rname]
structuralType
entitySet∷=实体集esname<ename>
entityContainer∷=实体容器ecname<...,(esname|collectionType),...>
binaryRelation∷=关系rname<(ename|rname),(ename|rname)>constraint
基类型
aname符号属性名(即,成员名)
ename符号实体类型名
cname复合类型的符号名
sname其它类型的符号同义词
rname二元关系的符号名
esname实体集的符号名
ecname实体集合的符号名
scalar不带明显内部结构的基类型
enum枚举符号的类型
constraint一阶谓词演算的表达式
结构类型。第一个定义框是包含CDM结构类型的递归封闭的子语法。此子语法中的语句仅可引用(1)同一子语法中的其它项,(2)标称类型,仅通过名字,(3)最后一个框——基类型中的项。基类型仅包括要在其它地方开发的各种名字空间和直接类型。结构类型不可被直接实例化,只有一个例外(实体容器中的集合类型)。相反,它们构建实体类型,这是一种标称类型,并且是将数据实例化的主要方式。
structuralType∷=simpleType|tupleType|collectionType
structuralType是simpleType(简单类型)、tupleType(元组类型)、或者collectionType(集合类型)
simpleType(简单类型)是scalar、enum、cname、sname、或对ename的引用。scalar是不带明显内部结构的基类型,正如机器原子整数、SQL小数、或者.NET串或DateTime(日期时间)。一种很重要的标量类型是GUID。此类型具有每个示例在空间和时间上都全局唯一这一属性。它的主要用途是作为系统生成的类型或代理关键字。enum是如C#、Visual Basic或其它.NET编程语言中所见的直接枚举类型。cname是complexType(复合类型)——以下所定义的标称类型之一的名字。sname是typeSynonym(类型同义词),typeSynonym在语义上和内联地写命名类型的定义是相同的。注意,snames可不引用标称类型:它们纯粹是结构类型的同义词。最后,ename是entityType(实体类型)的名字,entityType是主要的一类标称类型。ename被包括在文字Ref<>符号中以强只有实体类型才具有一等引用。对实体的引用可在关系型数据库中将外来关键字建模。CDM通过基于类型的关系将此用法形式化。
一般而言对等同而言有两个方面:第一,两个类型表达式是否表示同一类型;第二,单个给定类型的两个实例是否相等。属于对于前者采用术语“类型上的等同”,对于后者采用“值上的等同”或“实例上的等同”。
简单类型上的等同是很直接的:两个简单类型或者显然相同,或者显然不同(enum必须具有相同顺序的相同符号标签)。简单类型的值上的等同原则上是由逐位比较定义的。在实践中,一些.NET类型会有更为有关的等同操作。只要每个简单类型都必须提供取该类型的两个实例并返回布尔值的等同操作符就足够了。
tupleType(元组类型)是structuralType aname形式的一个或多个对,其中每一个都后跟一可任选的散列标志,所有这些都包括在‘波形括号’中。元组类型就好像C#类定义的负荷,递归地,它由成员或属性组成,其中每一个都有一个名字和structralType中的一个。属性名是aname类型,即,是从与ename、cname等截然不同的符号名字域中取出的。通过名字对属性的任何引用必须是无岐义的。
元组类型上的等同定义如下:当且仅当两个元组类型的属性具有相同的名字和类型并且按相同顺序出现时,这两个元组类型相等。因此,{TA A,TB B}与{TBB,TA A}是不同的元组类型。原因是要在CDM的实现中支持位置访问句法。当元组类型的两个实例的类型和值递归相等时,这两个实例相等。
散列标志表示组成关键字规范的属性,即,在某些情况下,被散列标记的属性的值全体必须在集合类型集内或在entitySets(实体集)内是唯一的。如果类型中一个以上属性具有散列标志,则关键字是复合关键字,它由所有被标记的属性按其在文本中定义的顺序串接组成。复合关键字可跨越多个元组类型,因此,例如,在
{TA A{TB B#}{TC C#}}
中,关键字规范是{B,C}。稍长的例子有:
{String personName,
{Int a,Int b,Int c}socialSecurityNumber #,
{String street,
String city,
String state,
{Int station,Int block}zipCode}address}
那是具有名为personName(人名)、socialSecurityNumber(社会保障号)、和address(地址)三个属性的名片的小型元组类型。这些属性分别具有以下三种类型:用于人名的自由形式的串,包括社会保障号的三个部分、并用散列标志标记以起到实体集或集集合中唯一的关键字作用的嵌套元组,以及包含街道、城市、州和两部分邮政编码、并同样被表示为更深层嵌套元组的嵌套元组。
collectionType(集合类型)或是List(列表),或是Set(集合),或是其它某种类型,其中每一个都以另一种结构类型作为参数。大多数情况下,集合类型是作为实体的组件被间接实例化的。但是,它们可在实体容器内被直接实例化,如以下所述。
列表。list是structuralType的实例的有序集合。“有序”意味着有从正数1,2...到该集合的元素的映射关系。“有序”不应与“经分类”混淆:列表[1,3,2]是有序但未经分类的;[1,2,3]是有序并经分类的。特例即对是很常见的。对是长度为2的列表。
列表类型上的等同在列表的成员的结构类型上是递归的。如果(1)有相同个数的成员;(2)各成员是递归相等的;以及(3)成员按相同顺序出现,则列表类型的两个实例是相等的。例如:List<Int>是正数列表的类型。
集合。set是structuralType的实例的无序集合,其中不允许复制。Set<Int>是正数集合的类型。用于插入成员、测试成员和计算合集、交集的操作等等。
集合类型上的等同在该集合的成员的结构类型上是递归的。如果一集合类型的两个实例包含相同个数的成员,且这些成员的值是独立于顺序递归相等的,则这两个实例相等。
从1开始向上计数是数学惯例;编程语言倾向于从0开始向上计数。但是,从1还是0开始计数的不确定获得数学上相同的情况。连基本如自然数集合(写为N)的事物有时被定义为0,1...而有时被定义为1,2...
多重集。multiset(多重集)是structuralType的实例的无序集合,其中允许复制。例如,
Multiset<Set<String>>
是串集的多重集的类型,而
Multiset<{String personName,DateTime birthdate}>
是人名和生日的匿名元组类型的实例的多重集的类型。
多重集类型上的等同在该多重集的成员的结构类型上是递归的。如果(1)多重集类型的两个实例包含相同个数的成员;且(2)独立于顺序,但考虑重复次数,这些成员的值递归相等,则这两个实例是相等的。因此[1,1,2,3]和[2,1,3,1]作为多重集是相等的,但[1,1,2,3]和[1,2,2,3]是不相等的。数学上,多重集最直接的表示是多重性计数和值对的集合。如果这样来表示多重集,则它们的等同是自动的,取决于集合等同和对等同。
标称类型。标称类型具有在其域内必须被唯一地命名这一区别性特征。标称类型中的两个类型参与子类型化关系。这两个类型是complexType(复合类型)和entityType(实体类型)。结构类型的子类型化在理论上要复杂得多,因此在CDM中是不允许的。
实体集是标称的,既因为它们的名字是Ref<e>类型的实体引用的一部分,又因为它们是确立实例树根节点的一个方法。在该角色中,它们必须具有名字,以使应用程序可检索实例数据。实体集合也必须是被命名的,因为它们也确立实例树的根节点。类型同义词是标称类型,因为它们的本质是命名。最后,关系是标称的,以使关联实体可根据名字来共享和引用它们。
标称类型上的等同在某种意义上要比结构类型上的等同简单。在其最严格的形式中,两个标称类型具有相同名字而在其定义中具有即使是句法上的任何差异都是错误的。
标称类型的值上的等同也可利用命名。特别地,当且仅当实体类型的两个实例的引用相等时,这两个实例是相等的。这是称对实体的引用为其标识的原因所在。
以上是6个不同种类的标称类型声明。类型同义词将特定的sname引入snames域中。当sname在别处被使用时,用其所引用的structuralType代替sname。例如,
Type toyContactCard=
{String personName,
{Int a,Int b,Int c} socialSecurityNumber #,
{String street,String city,String state,
{Int station,Int block}zipCode} address}
定义了以上所示出的名片的类型同义词。在本来必须复制粘贴或键入逐字定义的任何地方,都可使用该类型同义词toyContactCard。
complexType(复合类型)引入cname,它(1)可任选地扩展了另一个复合类型;其中(2)每个实例都服从以一阶谓词演算形式表达的可任选的约束;且(3)具有由structuralType表示的附加结构,即意味着给定的结构类型被添加到祖先的结构类型中,且不允许属性的冲突。
CDM允许单继承,这意味着复合类型至多可扩展另一个复合类型,但允许递归,从而直接祖先进而至多可扩展另一个复合类型。
复合类型是最丰富的一种结构化CDM内联类型。内联类型具有尽管能够在其它类型定义中根据名字引用它们,但是不可能将它们直接实例化,也不可能引用可能出现在实体中的实例这一区别性特征。同样元组类型的经散列标记的属性形式的嵌入关键字规范在复合类型的上下文中被忽略。
复合类型和类型同义词之间的区别是,前者可享有继承但受到限制。顺便提及,注意一些约束可在编译时通过理论证明和模型检查技术被静态检查。其它约束可在运行时被检查,在此情形中编译器必须发出约束检查代码。例如:
ComplexType betterContactCard toyContactCard
定义了具有由上述类型同义词所指定的负荷的复合类型。
ComplexType employeeRecord extends betterContactCard
{Int employeeNumber,Int departmentNumber}
基于已定义的较佳的名片,定义了雇员记录的复合类型。它具有betterContactCard的所有属性,以及被内联地写入的显式元组的所有属性。
entityType(实体类型)引入ename,它(1)可任选地扩展另一实体类型;其中(2)所有实例都服从一可任选的约束;(3)该约束可任选地根据其rname引用关系;并且(4)具有由structuralType表示的附加结构,这意味着给定的结构类型被线性串接到祖先实体类型的结构类型,且不允许属性的冲突。
关键字规范(散列标记)也被串接,这意味着具有祖先的实体类型的关键字规范是被包括的元组类型的关键字规范按照线性顺序的串接。
实体类型应当具有关键字规范。这表示实体类型在其继承链中必须至少具有带有至少一个散列标记的一个元组类型。此限制在语义上被强制实施,以不至于令句法过于复杂。
可任选的rname说明了CDM关联实体,它们是带有额外属性的二元关系。详见以下关系一节。
CDM允许单继承,这意味着实体类型至多可递归地扩展另一个实体类型。实体类型不可扩展复合类型,而复合类型不可扩展实体类型。换言之,复合类型和实体类型占据分离的子类型空间。
实体类型是最丰富的一种参与entitySets(实体集)的结构化CDM类型,其中元组中经散列标记的属性构成关系型数据库普通意义上的主关键字。此外,实体实例具有标识,这是它们被串接到其实体集的标识的关键字值。3这些标识构成在语法框1中出现的显式Ref<ename>项的值。
实体类型是在实体即关系或表的CDM模型的上下文中总可被直接实例化的主要的一种CDM类型,同样这是在普通意义的关系型数据库上。例如:
EntityType employeeEntity employeeRecord基于以上所定义的复合类型employeeRecord定义了实体类型。就此而言,迄今被忽略的经散列标记的属性重新获得了重要性。回忆前文,employeeRecord扩展使用具有以下嵌入属性类型同义词toyContactCard的betterContactCard,
{Int a,Int b,Int c}socialSecurityNumber #
该属性上的散列标志标识社会保障号将是employeeEntity实例的实体集中的主关键字。如果与社会保障号相比,用户更想用雇员号做关键字,则就需要定义雇员号被散列标记而社会保障号未被散列标记的新的元组类型,或使用以下的散列标志操纵操作来从旧的类型创建新的类型。
entitySet(实体集)是ename类型的实体的命名集合。复制实体实例在实体集中是不允许的,且实体类型必须具有关键字规范,即,用散列标志标记的一个或多个属性。实体集的名字esname被引入到esnames这一独特的域中。
EntitySet employees<employeeEntity>
是雇员实体的实体集的类型,它使用社会保障号作为关键字。
entityContainer(实体容器)是一个或多个项的命名集合,其中每一个项或是由其esname表示的实体集,或是匿名集合类型。
EntityContainer<employees>
是持有名为employees的实体集的实例的实体容器的类型。在实例容器中将集合类型实例化的方法是TBD。否则,实例容器只是一个或多个实体集的封装。
关系。CDM要求以下正则形式的关系:(1)关联,(2)条件关联,(3)关联实体,(4)合成。这些都是算术关系的同一低层概念的变体,我们同样将它们形式化。
数学关系是集合的笛卡尔积的子集,它令该子集的所有成员都满足某种约束。考虑一个或多个集合的列表(A1,A2,...,An),也写为Ai,i=1..n。这些集合的笛卡尔积,写为C=A1×A2×…×An,是n元有序元组集
笛卡尔积是从集合列表可构造的最大关系,因为该约束没有过滤掉任何成员。
为用比全笛卡尔积要少的成员来构造关系,约束必须过滤掉一些成员。例如,考虑雇员号的集合,1到100,写为1..100,和部门号的集合,1到10。将雇员与部门相关的一个方法如下,定义符号>作为该关系的名字:
其中,‘div’是数论整除。这将雇员1到10与部门1相关,雇员11到20与部门2相关,依此类推。谓词是三个部分
和(e-1)div10=d-1的联合。
此例隐式地发生以指定雇员和部门之间多对1的关系。使用关系的名字作为中缀‘操作符’是标准的速记法:
一阶谓词演算足以表达实际关注的所有约束,包括唯一性、多重性、引用和条件成员关系。CDM对实践中某些重要或非常常用的约束的模式给予名字。例如,关系型数据库系统常常通过外来关键字实现1对多的关系。CDM引用约束是外来关键字的值必须作为主关键字出现在目标实体集中的语句。该外来关键字的值是ef<ename>类型的实例。谓词演算中的模式可被提取以代表引用约束类。
非正式地,约束是个体项通过如‘与’、‘或’和‘非’等连接词的合成。每个项都是一个布尔类型的表达式,它可根据ename和aname引用实体的属性;可引用约束;可引用如≤等比较运算符;可引用由诸如
和^等量词引入的变量;以及引用一些特殊的、有副作用的操作约束,例如在以下句法中所提供的:
operationalConstraint∷=On(Delete|Copy|Serialize)<ename>(Cascade|Restrict|Remove)
9种形式的操作约束中的每一种根据其ename引用二元关系中的两个实体类型中的一个。Cascade(级联)意味着操作Delete(删除)、Copy(复制)或Serialize(串行化)应被传播到该关系中的另一个实体类型的实例。Restrict(限制)意味着该操作应仅在另一实体类型的实例独立执行兼容操作的情况下发生。Remove(移除)意味着当该操作完成时该关系本身应被移除。
约束的另一种特殊形式是多重性约束:
multiplicityConstraint∷=(multiplicity(one|many|n1..m1)enamel to(one|many|n2..m2)ename2)
CDM对不落入以上任何类别的约束使用术语条件约束。对于合成约束的类是否应被标识,业界仍未达成一致。
entitySet(实体集)从逻辑上讲是一元关系,其中笛卡尔积是很小的,仅由一个集合组成。binaryRelation(二元关系)是二元关系,其中笛卡尔积命名两个集合。三元、四元等关系是可用越来月大的笛卡尔积来设计的。但是二元关系实际上满足所有的实际情形,此外,所有较大的关系可被平凡地构建为二元关系的合成。
binaryRelation∷=Relation rname<(ename|rname),(ename|rname)>constraint
binaryRelation(二元关系)将rname引入rnames的域中,并定义了实体对上的二元关系或满足强制约束的其它关系。在对是实体而不是关系的基本情形中,对是全体实体类型集合的笛卡尔积的成员。相关种类的一方或双方是其它关系的递归情形支持较大元的关系的合成构建。
EntityType department {String deptName,Int deptNo #}
EntitySet departments <department>
Relation empDepts <department,employeeEntity>
(multiplicity one department to many employeeEntity)
添加对应于部门的实体类型和实体集,并声明从部门到雇员实体的一对多关系。有用于实现这一关系的选项。例如,可通过联合表或通过外来关键字约束来实现这一关系。
关联。CDM关联是二元关系,如上所述。
条件关联。所有二进制关系都是条件的,这意味着约束是强制的。因此,CDM条件关联是二进制关系,如上所定义。
关联实体。实体类型可任选地根据rname引用二元关系。这一实体说明了CDM的关联实体。
合成。满足以下两个准则的二进制关系是CDM合成:有多个约束,其中两个实体类型中至少一个多重性为1;以及对该实体类型有OnDelete ename Cascade形式的操作约束。
类型等级的操作
将复合类型或实体类型转换为结构类型。它将complexType(复合类型)和entityType(实体类型)的位置互换。
写betterContactCard和写toyContactCard是一样的,因为betterContactCard是通过声明ComplexType betterContactCard toyContactCard,而从toyContactCard构建的。
定义了二进制操作++,它将两个元组类型——或命名它们的同义词——串接以构成另一元组类型。写
{String personName}++{{Int a,Iht b,Int c}socialSecurityNumber#}
和写
{String personName,{Int a,Int b,Int c} socialSecurityNumber #}.是一样的。
将命名属性从元组类型中移除。如果输入的元组类型不具有命名属性则这是一个空操作(nop)。写
{String personName,Address address}--personName
和写
{Address address}
是一样的。
将其自变量的元组类型中的所有属性的所有散列标志取下。写{String personName,{Int a,Int b,Int c} socialSecurityNumber #}StripHashes
和写
{String personName,{Int a,Int b,Int c} socialSecurityNumber}是一样的。
(tuple Type|sname)aname AddHash-!tupleType导致命名属性被散列标记的元组类型。如果该属性已被散列标记,则它保持不变。写
{String personName,{Int a,Int b,Int c} socialSecurityNumber}
personName AddHash
和写
{String personName #,{Int a,Int b,Int c} socialSecurityNumber}是一样的。
现在参考图32,图中示出了用于执行该CDM体系结构的计算机的框图。为了给本发明的各个方面提供附加的上下文,图32和以下讨论旨在提供对可在其中实现本发明的各个方面的适用的计算环境的简要的、一般的描述。尽管以上是在可在一台或多台计算机上运行的计算机可执行指令的上下文中描述了本发明,但是本领域技术人员将会认识到,还可结合其它程序模块和/或作为硬件和软件的合成来实现本发明。
一般而言,程序模块包括执行特定任务或实现特定抽象数据类型的例程、程序、组件、数据结构等等。此外,本领域技术人员将会认识到,本发明的方法可用其它计算机系统配置来实施,包括但处理器或多处理器计算机系统、小型计算机、大型计算机、以及个人计算机、手持式计算设备、基于微处理器的或可编程的消费者电子设备、等等,其中每一个都可被操作地耦合到一个或多个相关联的设备。
所示出的本发明的方面还可在分布式计算环境中实施,其中某些任务时有通过通信网络链接的远程处理设备执行。在分布式计算环境中,程序模块可位于本地和远程记忆存储设备中。
计算机通常包括各种计算机可读介质。计算机可读介质可以是可由计算机访问的任何可用介质,并包括易失性和非易失性介质、可移动和不可移动介质。作为示例,而非限制,计算机可读介质可包括计算机存储介质和通信介质。计算机存储介质包括以用于存储诸如计算机可读指令、数据结构、程序模块或其它数据等信息的任何方法或技术实现的易失性和非易失性、可移动和不可移动介质。计算机存储介质包括,但不限于,RAM、ROM、EEPROM、闪存或其它存储器技术,CD-ROM、数字视频盘(DVD)或其它光盘存储,磁带盒、磁带、磁盘存储或其它磁存储设备,或可用来存储所需信息并可由计算机访问的任何其它介质。
再次参考图2,用于实现本发明的各个方面的示例性环境3200包括计算机3202,计算机3202包括处理器3204、系统存储器3206和系统总线3208。系统总线3208将包括但不限于系统存储器3206的系统组件耦合到处理单元3204。处理单元3204可以是各种可购买的处理器中的任何一种。双微处理器和其它多处理器体系结构也可作为处理单元3204使用。
系统总线3208可以是数种类型的总线结构中的任何一种,它可被进一步互连到存储器总线(带或不带存储器控制器)、外围总线、以及使用各种可购买的总线体系结构中的任何一种的局部总线。系统存储器3206包括只读存储器(ROM)3210和随机存取存储器(RAM)3212。基本输入/输出系统(BIOS)存储在诸如ROM、EPROM、EEPROM等非易失性存储器3210中,该BIOS包含在诸如启动时帮助在计算机3202内各元件之间传递信息的基本例程。RAM 3212还可包括诸如静态RAM等高速RAM用于将数据高速缓存。
计算机3202还包括内置硬盘驱动器(HDD)3214(例如,EIDE、SATA),其中该内置硬盘驱动器3214还可被配置成供在适当底座(未示出)中进行外置使用;软磁盘驱动器(FDD)3216(例如,读或写可移动磁盘3218)和光盘驱动器3220(例如,读CD-ROM盘3222,或者读或写诸如DVD等其它高容量光介质)。硬盘驱动器3214、磁盘驱动器3216和光盘驱动器3220可分别通过硬盘驱动器接口3224、磁盘驱动器接口3226和光盘驱动器接口3228被连接到系统总线3208。供外置驱动器实现使用的接口3224包括通用串行总线(USB)和IEEE 1394接口技术中的至少一种或者两者。其它外置驱动器连接技术也是在本发明的构想之内。
各驱动器及其相关联的计算机可读介质提供了数据、数据结构、计算机可执行指令等的非易失性存储。对于计算机3202,各驱动器和介质容纳合适的数字形式的任何数据的存储。尽管以上对计算机可读介质的描述引用了HDD、可移动磁盘、以及诸如CD或DVD等可移动光盘,但是本领域技术人员应当认识到,诸如zip驱动器、磁带盒、闪存卡、卡式盒带等计算机可读的其它类型的介质也可在该示例性操作环境中使用,此外,任何此类介质可包含用于执行本发明的方法的计算机可执行指令。
若干程序模块可被存储在驱动器和RAM 3212中,包括操作系统3230、一个或多个应用程序3232、其它程序模块3234和程序数据3236。操作系统、应用程序、模块和/或数据的所有或其部分还可被高速缓存在RAM 3212中。可以认识到,本发明可用各种可购买的操作系统或其合成来实现。
用户可通过例如键盘3238和定位设备(诸如鼠标3240)等一个或多个有线/无线输入设备将命令和信息输入到计算机3202中。其它输入设备(未示出)可包括话筒、IR遥控、操纵杆、游戏垫、记录笔、触摸屏等。这些及其它输入设备常常通过被耦合到系统总线3208的输入设备接口3242被连接到处理单元3204,但也可通过诸如并行端口、IEEE 1394串行端口、游戏端口、USB端口、IR端口等其它端口连接。
监视器3244或其它类型的显式设备也经由诸如视频适配器3246等接口被连接到系统总线3208。除了监视器3244以外,计算机通常还包括诸如扬声器、打印机等其它外围输出设备(未示出)。
计算机3202可使用经由无线和/或有线通信到诸如远程计算机3248等一个或多个远程计算机的逻辑连接在联网环境中操作。远程计算机3248可以是工作站、服务器计算机、路由器、个人计算机、便携式计算机、基于微处理器的娱乐装置、对等设备或其它普通网络节点、并且通常包括相对于计算机3202所描述的许多或全部元件,尽管出于简化目的,仅示出记忆/存储设备3250。所示的逻辑连接包括到局域网(LAN)3252和/或更大网络(例如,广域网(WAN)3254)的有线/无线连接。此类LAN和WAN网络环境常见于办公室和公司,并且便于诸如内联网等企业范围的计算机网络,所有这些都可被连接到例如因特网等全球通信网络。
当在LAN网络环境中使用时,计算机3202通过有线和/或无线通信网络接口或适配器3256连接到局域网3252。适配器3256可便于到LAN 3252的有线或无线通信,LAN 3252还可包括布置在其上用于域无线适配器3256通信的无线接入点。
当在WAN网络环境中使用时,计算机3202可包括调制解调器3258,或被链接到WAN 3254上的通信服务器,或具有用于通过WAN 3254建立通信的其它手段(诸如通过因特网)。可以是内置或外置、有线或无线设备的调制解调器3258经由串行端口3242被连接到系统总线3208。在联网环境中,相对于计算机3202描述的程序模块或其部分可被存储在远程记忆/存储设备3250中。可以认识到,所示网络连接是示例性的,并且可以使用在计算机之间建立通信链路的其它装置。
计算机3202可用于与操作上被布置在无线通信中的任何无线设备或实体通信,例如,打印机、扫描仪、台式和/或便携式计算机、便携式数字助理、通信卫星、与可无线检测标签相关联的任何设备物件或位置(例如,电话亭、报摊、休息室等)、以及电话。因此,通信可以是与常规网络等的预定结构,或者仅仅是至少两个设备之间的特定通信。
Wi-Fi或无线保真允许从家里的沙发上、宾馆房间的床上、或工作场所的会议室里无线地连接到因特网。Wi-Fi是类似于蜂窝电话中使用的无线技术,它使诸如计算机等设备能够在室内和室外发送和接收数据;在基站范围之内的任何地方。Wi-Fi网络使用称为IEEE 802.11(a、b、g等)的无线电技术来将计算机相互连接,连接到因特网,以及连接到有线网络(使用IEEE 802.3或以太网)。Wi-Fi网络在未注册的2.4和5GHz无线电波段,以例如11Mbps(802.11a)或54Mbps(802.11b)的数据率,或与同时包含这两个波段(双波段)的产品操作,因此网络可提供类似于许多办公室中所使用的基本10BaseT以太网网络的实际性能。
现在参考图33,图中示出了可在其中使用CDM的示例性计算环境3300的示意框图。系统3300包括一个或多个客户机3302。客户机3302可以是硬件和/或软件(例如,线程、进程、计算设备)。客户机3302可通过使用本发明来容纳例如cookie和/或相关联的上下文信息。
系统3300还包括一个或多个服务器3304。服务器3304也可以是硬件和/或软件(例如,线程、进程、计算设备)。服务器3304可通过使用本发明来容纳例如执行变换的线程。客户机3302和服务器3304之间一种可能的通信可以是适应于在在两个或多个计算机进程之间被发送的数据分组的形式。数据分组可包括例如cookie和/或相关联的上下文信息。系统3300包括通信框架3306(例如,诸如因特网等全球通信网络),该通信网络可被用来便于客户机3302和服务器3304之间的通信。
可经由有线(包括光纤)和/或无线技术来便于通信。客户机3302被操作地连接到可被用来将信息(例如,cookie和/或相关联的上下文信息)本地存储到客户机3302的一个或多个客户机数据存储3308。类似地,服务器3304被操作地连接到可被用来将信息本地存储到服务器3304的一个或多个服务器数据存储3310。
以上所描述的包括所揭示的发明的示例。当儿,要描述组件和/或方法每一个可构想的合成是不可能的,但本领域普通技术人员可以认识到,许多进一步的合成和变换是可能的。由此,本发明旨在包括落入所附权利要求书的精神和范围的所有此类改变、修改和变体。此外,就在具体实施方式或所附权利要求书中使用术语“包括”的意义而言,这一术语旨在和术语“包含”在所附权利要求书中被作为过渡词所解释的那样成为包含性的。
Claims (20)
1.一种便于公用数据访问的计算机实现的系统,包括:
实体组件,用于提供在多个完全不同的应用程序上具有统一标识的数据实体;以及
关系组件,用于定义两个或多个所述数据实体之间的关系。
2.如权利要求1所述的系统,其特征在于,所述数据实体至少满足以下至少一项:包括在其上定义属性的实体类型,以及接收类型化的参数。
3.如权利要求2所述的系统,其特征在于,所述实体类型包括标识数据。
4.如权利要求1所述的系统,其特征在于,所述两个或多个实体之间的关系是关联,从而使所述两个或多个实体经由显式的源-目标数据而彼此相关。
5.如权利要求1所述的系统,其特征在于,所述两个或多个实体之间的关系是关联的,从而使所述两个或多个实体通过关联实体被链接在一起。
6.如权利要求1所述的系统,其特征在于,所述两个或多个实体之间的关系是合成,从而使第一实体是第二实体的一个组成部分。
7.如权利要求1所述的系统,其特征在于,所述数据实体是通过被添加到实体表中而被持久化的,其中所述实体表是实体的类型化集合。
8.如权利要求1所述的系统,其特征在于,所述关系是被直接表达的。
9.如权利要求1所述的系统,其特征在于,所述数据实体包括类型为以下各项中的一个的成员:内联类型、实体类型、表类型、枚举类型和数组类型。
10.如权利要求9所述的系统,其特征在于,所述内联类型在它驻留在其中的实体所强加的范围以外没有任何标识。
11.如权利要求1所述的系统,其特征在于,所述数据实体可由关键字引用。
12.如权利要求1所述的系统,其特征在于,所述实体组件包括由以下至少一项组成的实体成员:属性、导航属性、经计算的属性和方法。
13.如权利要求1所述的系统,其特征在于,所述实体之间的关系是条件的。
14.如权利要求1所述的系统,其特征在于,所述关系的范围可被界定到仅适用于特定表。
15.一种用于提供完全不同的应用程序上的公用数据访问的计算机实现的方法,包括:
提供一实体,所述实体是紧密相关的数据的单个标识,并且是可唯一标识的;
标识所述实体的结构为属性,并标识所述实体的行为为方法;以及
使用关系表达实体之间的语义连接。
16.如权利要求15所述的方法,其特征在于,所述实体包括执行以下各项中的一个的实体成员:为特定类型的实例分配存储,便于在由关联相关的实体上进行查询,是经计算的属性,以及表示能被执行的操作。
17.如权利要求16所述的方法,其特征在于,所述实体成员满足以下至少一项:包括类型,或者取类型参数。
18.如权利要求16所述的方法,其特征在于,所述实体成员包括其数据被内联地存储在所述实体上的内联类型。
19.如权利要求16所述的方法,其特征在于,所述实体成员包括表类型,所述表类型是指定实体类型的实例的无序集合。
20.一种便于完全不同的应用程序上的公用数据访问的系统,包括:
用于提供实体的装置,所述实体是紧密相关的数据的单个标识,并且可被唯一标识;
用于标识所述实体的结构为属性,并标识所述实体的行为为方法的装置;以及
用于使用显式的源-目标关系、通过关联将两个或多个所述实体相关的装置;
用于以父子关系、通过合成将两个或多个实体相关的装置;以及
用于通过实体关联将两个或多个实体相关的装置。
Applications Claiming Priority (3)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
US65729505P | 2005-02-28 | 2005-02-28 | |
US60/657,295 | 2005-02-28 | ||
US11/228,731 | 2005-09-16 |
Publications (1)
Publication Number | Publication Date |
---|---|
CN1828594A true CN1828594A (zh) | 2006-09-06 |
Family
ID=36946989
Family Applications (1)
Application Number | Title | Priority Date | Filing Date |
---|---|---|---|
CN 200610004632 Pending CN1828594A (zh) | 2005-02-28 | 2006-01-26 | 对象关系型数据的数据模型 |
Country Status (1)
Country | Link |
---|---|
CN (1) | CN1828594A (zh) |
Cited By (9)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN104317913A (zh) * | 2014-10-28 | 2015-01-28 | 用友软件股份有限公司 | 属性组合的筛选方法和属性组合的筛选装置 |
CN105512350A (zh) * | 2016-02-26 | 2016-04-20 | 上海全成通信技术有限公司 | 一种网站多级内容管理方法及装置 |
CN105760409A (zh) * | 2015-03-04 | 2016-07-13 | 机械工业第六设计研究院有限公司 | 分布式对象与关系型数据库映射方法 |
CN105824883A (zh) * | 2016-03-10 | 2016-08-03 | 中电海康集团有限公司 | 一种可动态扩展数据关联网络图的表示方法及系统 |
CN106802947A (zh) * | 2017-01-13 | 2017-06-06 | 中国工商银行股份有限公司 | 实体关系图的数据处理系统及方法 |
CN109241151A (zh) * | 2017-06-29 | 2019-01-18 | 阿里巴巴集团控股有限公司 | 一种数据结构的转换方法、装置及电子设备 |
CN109587174A (zh) * | 2019-01-10 | 2019-04-05 | 广东电网有限责任公司信息中心 | 用于网络防护的协同防御方法和系统 |
CN112163049A (zh) * | 2020-09-29 | 2021-01-01 | 北京中电普华信息技术有限公司 | 将业务对象映射为数据实体的方法及装置 |
CN113762028A (zh) * | 2020-06-03 | 2021-12-07 | Sap欧洲公司 | 从文本文档进行数据驱动的结构提取 |
-
2006
- 2006-01-26 CN CN 200610004632 patent/CN1828594A/zh active Pending
Cited By (15)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN104317913B (zh) * | 2014-10-28 | 2017-11-24 | 用友网络科技股份有限公司 | 属性组合的筛选方法和属性组合的筛选装置 |
CN104317913A (zh) * | 2014-10-28 | 2015-01-28 | 用友软件股份有限公司 | 属性组合的筛选方法和属性组合的筛选装置 |
CN105760409A (zh) * | 2015-03-04 | 2016-07-13 | 机械工业第六设计研究院有限公司 | 分布式对象与关系型数据库映射方法 |
CN105512350A (zh) * | 2016-02-26 | 2016-04-20 | 上海全成通信技术有限公司 | 一种网站多级内容管理方法及装置 |
CN105824883A (zh) * | 2016-03-10 | 2016-08-03 | 中电海康集团有限公司 | 一种可动态扩展数据关联网络图的表示方法及系统 |
CN106802947B (zh) * | 2017-01-13 | 2019-11-29 | 中国工商银行股份有限公司 | 实体关系图的数据处理系统及方法 |
CN106802947A (zh) * | 2017-01-13 | 2017-06-06 | 中国工商银行股份有限公司 | 实体关系图的数据处理系统及方法 |
CN109241151A (zh) * | 2017-06-29 | 2019-01-18 | 阿里巴巴集团控股有限公司 | 一种数据结构的转换方法、装置及电子设备 |
CN109241151B (zh) * | 2017-06-29 | 2022-05-10 | 阿里巴巴集团控股有限公司 | 一种数据结构的转换方法、装置及电子设备 |
CN109587174A (zh) * | 2019-01-10 | 2019-04-05 | 广东电网有限责任公司信息中心 | 用于网络防护的协同防御方法和系统 |
CN109587174B (zh) * | 2019-01-10 | 2021-07-27 | 广东电网有限责任公司信息中心 | 用于网络防护的协同防御方法和系统 |
CN113762028A (zh) * | 2020-06-03 | 2021-12-07 | Sap欧洲公司 | 从文本文档进行数据驱动的结构提取 |
CN113762028B (zh) * | 2020-06-03 | 2024-06-21 | Sap欧洲公司 | 从文本文档进行数据驱动的结构提取 |
CN112163049A (zh) * | 2020-09-29 | 2021-01-01 | 北京中电普华信息技术有限公司 | 将业务对象映射为数据实体的方法及装置 |
CN112163049B (zh) * | 2020-09-29 | 2024-04-09 | 北京中电普华信息技术有限公司 | 将业务对象映射为数据实体的方法及装置 |
Similar Documents
Publication | Publication Date | Title |
---|---|---|
CN1828594A (zh) | 对象关系型数据的数据模型 | |
CN1820266A (zh) | 用于将应用程序与基于项的存储平台接口的系统和方法 | |
CN1820245A (zh) | 用于基于项目的存储平台中的数据建模的系统和方法 | |
CN1828527A (zh) | 用于跨不同应用程序框架的数据服务的平台 | |
CN1739107A (zh) | 为可由硬件/软件接口系统管理的信息单元提供同步服务的系统和方法 | |
CN1961294A (zh) | 为可由硬件/软件接口系统管理的信息单元提供关系和分层同步服务的系统和方法 | |
CN1182467C (zh) | 可扩充的分布企业应用集成系统 | |
CN1869923A (zh) | 系统数据接口及相关体系结构 | |
CN1609795A (zh) | 用于计算机平台的编程接口 | |
US7734657B2 (en) | Containment hierarchy in a database system | |
CN101048732A (zh) | 面向对象的数据集成服务体系结构 | |
CN1585945A (zh) | 用于将xml模式映射到对象关系数据库系统的机制 | |
CN1679026A (zh) | Web服务设备和方法 | |
CN1604082A (zh) | 用于任意数据模型的映射体系结构 | |
CN1838165A (zh) | 工作项跟踪系统的工作项规则 | |
US20060195460A1 (en) | Data model for object-relational data | |
US7613715B2 (en) | Map and data location provider | |
CN101076793A (zh) | 企业数据集成系统的体系结构 | |
CN1609794A (zh) | 用于计算机平台的编程接口 | |
CN1359489A (zh) | 用于构筑建模工具的装置和方法 | |
CN1601510A (zh) | 分布式计算系统的架构和分布式应用程序的自动设计,部署及管理 | |
CN1839403A (zh) | 经改进的慈善管理系统和商务方法 | |
CN1834908A (zh) | 用于将开发模式应用于基于组件的应用程序的系统和方法 | |
CN1524216A (zh) | 软件构件插件程序结构的系统和方法 | |
CN1811772A (zh) | 企业信息集成平台 |
Legal Events
Date | Code | Title | Description |
---|---|---|---|
C06 | Publication | ||
PB01 | Publication | ||
CI02 | Correction of invention patent application |
Correction item: Priority Correct: 2005.09.16 US 11/228,731 False: Lack of priority second Number: 36 Page: The title page Volume: 22 |
|
COR | Change of bibliographic data |
Free format text: CORRECT: PRIORITY; FROM: MISSING THE SECOND ARTICLE OF PRIORITY TO: 2005.9.16 US 11/228,731 |
|
C10 | Entry into substantive examination | ||
SE01 | Entry into force of request for substantive examination | ||
AD01 | Patent right deemed abandoned |
Effective date of abandoning: 20060906 |
|
C20 | Patent right or utility model deemed to be abandoned or is abandoned |