代码改变世界

实体框架映射白皮书(EntityFrameworkMappingWhitePaper)(转)

2010-05-08 22:39  Kevin-wang  阅读(500)  评论(0编辑  收藏  举报

    1:EF支持的映射场景

     

    简单的映射

    场景:实体数据模型(EDM)中的每个实体都映射到了存储端(即数据库)的单个表。这是实体数据类型和存储架构间最简单的 映射情况。

     

    例子:

     

    实体数据模型:

    实体容器:Test_Simple_Model_Northwind

    实体集Ccategories

    实体Ccategory

    {

    Int CategoryID;

    String CategoryName;

    String Description;

    }

    存储架构:

    存储实体容器:Test_Simple_Target_Northwind

    表:dbo.Northwind.Scategories

    {CagetoryID(int),CategoryName(nvarchar(10)),Description

    (nvarchar(max))}

    映射(MSL)文件:

     

     

    备注:使用 EdmGen 工具对现有数据库生成文件时都是简单(一对一)的映射。

     

    图一   单 表单实体映射

    备注:相关的CSDLSSDL文件请查看附录 A

     

    纵向实体分割

    纵向实体分割就是创建具有实体部分字段的表和存储实体剩余字段的其它表。Normalization本质上就是一个将实体垂 直分割的过程。在纵向分割中,EDM中的一个表可以被映射到两个或多个不同的表格。

    备注:在纵向实体分割场景中,存储端中只有主键和主键联合(Join)是允许的。

    下面这个例子中,EDM中定义的实体Category映射了两个表:SCategories1ScategoriesDate1Scategories1表中包含CategoryID(主键),CategoryNameDescripion这几个字段,而在SCategoriesDate1表中包含CategoryID(重复了!)和CreatedDate两个字段。

    图二

    映射MSL)文件:

     

    基于EDM端条件的横向实体分割

    横向分割就是把不同的实体实例放到不同的表中。譬如高优先级别的订单会被存储在HighPriortyOrders表中,同时低优先级别的订单就被保存在别的表中。这两部分的表就是HighPriorityOrdersRegularOrders,同时在EDM端里通过两个表的联合来提供一个所有订单 的整体视图。

     

    横向实体分割基于一个在MSL文件中定义的布尔条件。现在实体框架只能基于布尔条件,不过在将来也许会有更多的条件类型。< /p>

     

    图三 基于EDM端条件的横向实体分割

    例子中的映射(MSL)文件:

     

    关联

     

    关联定义于EDM中,它被用来定义两个实体类型之间的点对点关系。关联可以支持实体类型之间的真实关系。以下是EDM模型中所支持的关系类型:

    • 1-1
    • 1-*
    • 0..1-1
    • 0..1-*
    • *-*
    • Self association

     

    举个例子,在一个CSDL文件中,ProductCategory之间的关联这样定义:

     

    基数(Cardinality:上面 这个例子中每个Product关联到0或者1Category,每个Category都有个1或 者更多的Products

     

    业务行为(Operational BehaviorOnDelete 中的 cascade标志表示一个Category被删除了,那么它关联到的一个或者多个Products也会被删除。

     

    关联集

     

    关联中包含了指定的关联类型的关系实例。一个关联实例连接了用关联集关联的两个属于实体集的实体实例;譬如:给实体类型 E1 E2 一个关联类型 R,就给了关联E1(属 于实体集 ES1 E2(属 于实体集 ES2 R 的一个关联集。

    映射架构语言 (MSL)可以将EDM中定义的关联映射到数据库中包含的外键上。

    图四     实体关联的映射

    例子中的映射文件(MSL):

    1-1 关联

    实体数据模型:

    EDM的 定义片段(CSDL):

    映射定义片段(MSL):

     

    1对 多、多对多、自身关联部分的介绍省略)

     

    备注:完整的CSDLSSDLMSL文件可以到附录A中查看。

     

    衍生类型之间的关联

     

    实体类型的衍生类 型可以被指定为某关联类型的终端成员类型。

     

    例子:

    模型中定义了以下 的实体类型:

    说明:在TPHTable Per Hierarchy)和TPTTable Per Type)映射策略中支持此映射功能。TPCTable Per Concrete Class)则不支持。TCP中独有的限制使得它无法将关联指到子类型 中。通常不允许用TCP策略来映射关联;TCP的这种限制主要是源于关联的终端一定要映 射到单个表这个原因。

    结尾部分有更多关于TPHTPTTPC映射策略的内容。

     

    情形1TPH 映射架构

    如果存储是通过“TPH”实现的,那么MSL文件中“AssociationSetMapping”的定义部分里,外键必须要有条件:IsNull = false”:

    例如:

    情形2TPT映射架构

    使用TPT的时候没有指定条件

     

    映射抽象类型

    抽象类型只能用“IsTypeOf”关键字来映射。在TPH中,抽象类型的映射是可选的。即使被映射 了,抽象类型映射也没有指到它的映射对象的一个标志位。在TPT中,抽象类型需要有映射片段对应。TPC中 则不需要抽象类型映射。

     

    如果一个抽象类型 没有具体的实例化对象,映射这个抽象类型时映射加载器就会抛出一个错误。

     

    这有个在EDM中使用抽象类型的简单例子。这使用的是TPH, 因此我们不需要映射抽象类型。

    备注:附录A中有关于映射抽象类型的更多例子。

     

     

    CSDL中这个实体模型定义为:

    相应的MSL文件:

     

    继承

    TPH(Table Per Hierarchy)

    TPH中,每个级别(Hierarchy)中的所有类型都映射到在后 台存储端中的实际表中。为了实现TPH,创建一个表,它的结构包含了级别中的所有实体的属性。每个实体实例都代表一个元组(row),如果该实体没有这种属性,那么该元组的值为空(null)。这个表结构必须有主键,或者称之为 条件字段,通过它来定义一种条件,根据这个条件确定该行记录是那种类型。这个条件字段必须满足以下规则:

    • 所有定义类型映射的条件必须 是互斥的(即不相同)
    • 所有定义类型映射的条件必须 列举出所有基表中的记录
    • 用了映射条件的主键字段不能 映射到实体属性上

    CSDL 文件中的片段:

    MSL文 件中的片段:

    备注:附录A中含CSDLSSDLMSL文件的完整部分

     

    TPT(Table Per Type)

    在一个继承级别 中,所有该等级的实体都被映射到了不同的表,每个对应表都含有对应实体的所有属性,包括这些实体的父实体属性及自身添加的属性。

    CSDL 片段:

    MSL片段:

     

    Table Per concrete Class

    每个继承级别的非 抽象实体类型都被映射到不同的表中。对每个非抽象实体,表结构中含有所有实体的属性,包括从父类型中继承的。

    CSDL 片段:

    MSL片段:

    复式类型映射:

    复式类型提供采用 富(结构化)有效载荷创建属性的机制。一个复式类型可以包含在别的复式类型中。服饰类型定义中包含它的名称和有效载荷;通过所属实体类型来定义它的区别。 复式类型的有效载荷与下面这个例子中的抽象实体类型很相似:

    MSL片段(映射到单表)

     

    上面这个例子中复式类型映射到实体所映射到的表中;我们也可以将它映射到别的表里,那MSL就 是:

     

    嵌套复式类型:

    CSDL片段:

    MSL片段(映射到3个不同的表)