您的位置:首页 > 其它

[hystar整理]Entity Framework 教程 续一

2015-06-02 09:15 447 查看
EDM之CSDL CSDL定义了EDM或者说是整个程序的灵魂部分 – 概念模型。当前流行的软件设计方法通常都是由设计其概念模型起步。说概念模型可能比较抽象一个更容易接受的名字就是实体类。实体类是面向对象设计中一个最根本的组成部分,其体现了现实世界中对象作为一种计算中可以表示的对象设计方法。而EDM的CSDL就是要达到这样一个目的。这个在下文介绍Entity Framework优点时另有说明。
这个文件完全以程序语言的角度来定义模型的概念。即其中定义的实体、主键、属性、关联等都是对应于.NET Framework中的类型。下面xml element来自作业提交系统(有删节):
<!-- CSDL content -->
<edmx:ConceptualModels>
<Schema Namespace="ASSModel" Alias="Self" xmlns="http://schemas.microsoft.com/ado/2006/04/edm">
<EntityContainer Name="ASSEntities">
<FunctionImport Name="GETHOUSEWORKDONE" EntitySet="UpAssignments" ReturnType="Collection(Self.UpAssignments)">
<Parameter Name="StuID" Type="Int32" Mode="In" />
<Parameter Name="ClassID" Type="Int32" Mode="In" />
<Parameter Name="Semester" Type="String" Mode="In" />
</FunctionImport>
<!-- 以上删节 – 5个存储过程 -->

<EntitySet Name="Assignments" EntityType="ASSModel.Assignments" />
<EntitySet Name="Classes" EntityType="ASSModel.Classes" />
<EntitySet Name="Courses" EntityType="ASSModel.Courses" />
<EntitySet Name="SetCourses" EntityType="ASSModel.SetCourses" />
<EntitySet Name="Students" EntityType="ASSModel.Students" />
<EntitySet Name="Teachers" EntityType="ASSModel.Teachers" />
<EntitySet Name="UpAssignments" EntityType="ASSModel.UpAssignments" />

<AssociationSet Name="FK_SetCourses_Classes" Association="ASSModel.FK_SetCourses_Classes">
<End Role="Classes" EntitySet="Classes" />
<End Role="SetCourses" EntitySet="SetCourses" />
</AssociationSet>
<!-- 以上删节 – 6个关系集 -->

</EntityContainer>

<!-- 以下保留一个EntityType作为示例 -->
<EntityType Name="Students">
<Key>
<PropertyRef Name="StuID" />
</Key>
<Property Name="StuID" Type="Int32" Nullable="false" />
<Property Name="StuName" Type="String" Nullable="false" MaxLength="10" Unicode="true" FixedLength="true" />
<Property Name="Pswd" Type="String" Nullable="false" MaxLength="50" Unicode="false" FixedLength="true" />
<NavigationProperty Name="Classes" Relationship="ASSModel.FK_Students_Classes" FromRole="Students" ToRole="Classes" />
<NavigationProperty Name="UpAssignments" Relationship="ASSModel.FK_UpAssignments_Students" FromRole="Students" ToRole="UpAssignments" />
</EntityType>

<!-- 仅保留与上文AssociationSet对应的Association -->
<Association Name="FK_SetCourses_Classes">
<End Role="Classes" Type="ASSModel.Classes" Multiplicity="1" />
<End Role="SetCourses" Type="ASSModel.SetCourses" Multiplicity="*" />
</Association>
</Schema>
</edmx:ConceptualModels>
这部分XML文档,Schema是CSDL的根元素,其中定义的Namespace是用于ObjectContext与EntityClass的命名空间,Alias-别名为此命名空间Namespace指定一个易记的名称,在定义Alias之后,在此Schema内的Element均可以该Alias作为Namespace的别名。Alias的使用可以参考如下xml element:
<FunctionImport Name="GETHOUSEWORKDONE" EntitySet="UpAssignments" ReturnType="Collection(Self.UpAssignments)">
在这个根元素的内部的文档结构第一部分 – 实体容器大致如下:
<EntityContainer />
<FunctionImport />
<EntitySet />
<AssociationSet />
</EntityContainer>
下面的表格说明了这些节点及其属性的作用
EntityContainer
Name
EntityContainer的名称,其将作为产生的ObjectContext类的名称
EntitySet
Name
ObjectContext内与此Entity类型对应的属性名
EntityType
ObjectContext内与此Entity类型对应的属性的类型
AssociationSet
End
有两个End子节点,分别描述建立此关系的两个EntitySet
Role
对应到Association中End节的Role属性,起到将AssociationSet与Association相关连的作用。
FunctionImport
详见存储过程设计部分
可以看出,Entity与Assciation都被分开定义与两个部分,这样设计是出于当有多个EntityContainer时,其中的EntitySet或AssociationSet可以共享Entity或Association的定义。
接下来看一下CSDL中最后一部分,Entity与Association的定义。
首先是Entity:
<EntityType Name="Students">
<Key>
<PropertyRef Name="StuID" />
</Key>
<Property Name="StuID" Type="Int32" Nullable="false" />
<Property Name="StuName" Type="String" Nullable="false" MaxLength="10" Unicode="true" FixedLength="true" />
<Property Name="Pswd" Type="String" Nullable="false" MaxLength="50" Unicode="false" FixedLength="true" />
<NavigationProperty Name="Classes" Relationship="ASSModel.FK_Students_Classes" FromRole="Students" ToRole="Classes" />
<NavigationProperty Name="UpAssignments" Relationship="ASSModel.FK_UpAssignments_Students" FromRole="Students" ToRole="UpAssignments" />
</EntityType>
下表说明了其属性及其子节点与子节点的属性的含义:

EntityType
Name
Entity Class的名称
Abstract
是否为抽象类
BaseType
父类
Key
主键
Property
主键之属性
Name
属性名
Property
属性
Name
属性名
Type
属性类型
Nullable
是否允许null
MaxLength
属性最大长度
FixLength
是否固定长度
NavigationProperty
关系属性
Name
属性名
Relationship
对应的Association
FromRole、ToRole
区别关系两方的父与子

最后Association节,这是真正定义关系的地方。首先看示例:
<!-- 仅保留与上文AssociationSet对应的Association -->
<Association Name="FK_SetCourses_Classes">
<End Role="Classes" Type="ASSModel.Classes" Multiplicity="1" />
<End Role="SetCourses" Type="ASSModel.SetCourses" Multiplicity="*" />
</Association>
这一节符合以下结构:
<Association>
<End />
<ReferentialConstraint>
<Principal>
<PropertyRef />
</Principal>
<Dependent>
<PropertyRef />
</Dependent>
</ReferentialConstraint>
</Association>
属性及其子元素属性的说明:

Association
Name
Association的名称
End
类似于AssociationSet,Association也有两个End节点。
Name
End名称
Type
EntityType的名称
Role
此End的Role,与AssociationSet的End的Role属性相联系
Multiplicity
关联多重性,值为0、1或*
ReferentialConstraint
外键条件限制
Principal
主要条件
Role
对应于End中的Role
PropertyRef
外键属性
Name
属性名称
Dependent
依存条件
Role
对应于End中的Role
PropertyRef
外键属性
Name
属性名

另外上面示例未涉及的概念,如下:
视图
在EDM设计器中添加视图基本与添加实体表一致,所生成的xml自行对照。某些环境下可能无法添加视图,原因未知,另外对于没有主键的表目前版本EntityFramework支持不好,在设计器中无法添加,及时通过手工编辑xml的方式强行添加,在使用过程中也会出现问题。
ComplexType(复杂类型)
按MSDN中的例子,先描述如下场景。在一个销售系统中我们需要在一个订单中包含一个描述客户地址的实体,而这个实体又能良好的与存储模型映射起来,由于数据库不支持地址这种类型,所以我们可以将地址的每个字段与数据库相映射。且在概念模型中,及在C#代码可以控制的范围内,地址仍然作为一个独立的类型存在。由于EDM设计器不支持以可视化方式创建Complex Type,我们需要手动编辑CSDL与MSL来完成复杂类型的创建与映射。这部分示例将在介绍MSL后给出。

EDM之SSDL 这个文件中描述了表、列、关系、主键及索引等数据库中存在的概念。
<!-- SSDL content -->
<edmx:StorageModels>
<Schema Namespace="ASSModel.Store" Alias="Self" Provider="System.Data.SqlClient" ProviderManifestToken="2008" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" xmlns="http://schemas.microsoft.com/ado/2006/04/edm/ssdl">
<EntityContainer Name="ASSModelStoreContainer">
<EntitySet Name="Assignments" EntityType="ASSModel.Store.Assignments" store:Type="Tables" Schema="dbo" />
<!-- 省略7个EntitySet的定义 -->
</EntityContainer>

<!-- 以下省略7个EntityType的定义 -->
<EntityType Name="Assignments">
<Key>
<PropertyRef Name="AssID" />
</Key>
<Property Name="AssID" Type="int" Nullable="false" StoreGeneratedPattern="Identity" />
<Property Name="AssName" Type="nchar" Nullable="false" MaxLength="20" />
<Property Name="AssDes" Type="nvarchar" MaxLength="500" />
<Property Name="SCID" Type="int" Nullable="false" />
<Property Name="Deadline" Type="datetime" Nullable="false" />
<Property Name="QuesFileName" Type="nvarchar" MaxLength="500" />
<Property Name="QuesFileUrl" Type="nvarchar" Nullable="false" MaxLength="500" />
</EntityType>

<!-- 保留与CSDL中对应的Function -->
<Function Name="GETHOUSEWORKDONE" Aggregate="false" BuiltIn="false" NiladicFunction="false" IsComposable="false" ParameterTypeSemantics="AllowImplicitConversion" Schema="dbo">
<Parameter Name="StuID" Type="int" Mode="In" />
<Parameter Name="ClassID" Type="int" Mode="In" />
<Parameter Name="Semester" Type="varchar" Mode="In" />
</Function>

</Schema>
</edmx:StorageModels>
看文档的结构,SSDL与CSDL很详细,只是其中EntityType等使用数据库的概念的描述。
这其中有一个需要稍微介绍节点,DefiningQuery,首先看一下其出现的位置:
EntityContainer
EntitySet
DefiningQuery
通过查询定义一个SSDL的EntitySet
特定于存储的查询语句
DefiningQuery定义通过实体数据模型 (EDM) 内的客户端投影映射到数据存储视图的查询。此类映射是只读的。也就是说如果想要更新此类EntitySet,需要使用下文介绍存储过程时提到的定义更新实体的存储过程的方法,使用定义的存储过程来更新这样的EntitySet。当在实体类设计器中导入无主键的表时,会自动生成此类使用DefiningQuery定义的EntitySet,要式样Entity Framework提供的自动更新服务而不定义存储过程,需要给数据表添加一个适当的主键,删除DefiningQuery节点并更新数据模型。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: