将概念模型映射到存储架构
实体框架 提供以对象为中心的表格格式数据视图(以实体类型表示)。应用程序开发人员只需考虑对从概念性模型生成的对象模型进行编程,而不必考虑数据库架构以及如何访问数据库对象并将这些对象转换为编程对象。实体框架 使用模型架构和映射将对实体的创建、读取、更新和删除操作转换为数据源中的等效操作。
注意 |
---|
本节中演示的所有映射文件片断都由 EDM 生成器 (EdmGen.exe) 工具生成。 |
概念性模型
概念性模型是定义 EDM 中的实体和关联的 实体数据模型 (EDM) 架构。定义此模型的 XML 语法称为概念性架构定义语言 (CSDL)。CSDL 中定义的每个实体类型都具有一个名称、一个用于唯一标识实例的键和一组属性。分配给属性的数据类型指定为简单类型(标量属性)或复杂类型(由一个或多个标量或复杂属性组成的类型)。附加属性还可以指定是否可为 null 值或分配默认值。关联定义实体之间的关系。实体框架术语中更加详细地介绍了 实体框架 语言元素和术语。
下面的 XML 片断表示 School EDM 的概念性模型的一部分,该部分定义通过 FK_Course_Department 关联相关的 Course 和 Department 实体类型(移除了其他实体和关联)。
<?xml version="1.0" encoding="utf-8"?>
<Schema Namespace="SchoolModel" Alias="Self"
xmlns="https://schemas.microsoft.com/ado/2006/04/edm">
<EntityContainer Name="SchoolEntities">
<EntitySet Name="Course" EntityType="SchoolModel.Course" />
<EntitySet Name="Department" EntityType="SchoolModel.Department" />
...
<AssociationSet Name="FK_Course_Department"
Association="SchoolModel.FK_Course_Department">
<End Role="Department" EntitySet="Department" />
<End Role="Course" EntitySet="Course" />
</AssociationSet>
...
</EntityContainer>
<EntityType Name="Course">
<Key>
<PropertyRef Name="CourseID" />
</Key>
<Property Name="CourseID" Type="Int32" Nullable="false" />
<Property Name="Title" Type="String" Nullable="false"
MaxLength="100" Unicode="true" FixedLength="false" />
...
<NavigationProperty Name="Department"
Relationship="SchoolModel.FK_Course_Department"
FromRole="Course" ToRole="Department" />
...
</EntityType>
<EntityType Name="Department">
<Key>
<PropertyRef Name="DepartmentID" />
</Key>
<Property Name="DepartmentID" Type="Int32" Nullable="false" />
<Property Name="Name" Type="String" Nullable="false" MaxLength="50"
Unicode="true" FixedLength="false" />
...
<NavigationProperty Name="Course" Relationship="SchoolModel.FK_Course_Department"
FromRole="Department" ToRole="Course" />
</EntityType>
...
<Association Name="FK_Course_Department">
<End Role="Department" Type="SchoolModel.Department" Multiplicity="1" />
<End Role="Course" Type="SchoolModel.Course" Multiplicity="*" />
</Association>
...
</Schema>
存储模型
一个单独的数据模型使用存储架构定义语言 (SSDL) 描述持久性数据(通常存储在关系数据库中)的逻辑模型。在 SSDL 文件中声明的属性的数据类型为存储模型的数据类型。此存储模型片断演示的示例为 School 数据库中通过 FK_Course_Department 外键相关的 Course 和 Department 表的存储元数据(移除了其他实体)。
<?xml version="1.0" encoding="utf-8"?>
<Schema Namespace="SchoolModel.Store" Alias="Self"
Provider="System.Data.SqlClient" ProviderManifestToken="2005" xmlns:store="https://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" xmlns="https://schemas.microsoft.com/ado/2006/04/edm/ssdl">
<EntityContainer Name="dbo">
<EntitySet Name="Course" EntityType="SchoolModel.Store.Course"
store:Type="Tables" />
<EntitySet Name="Department"
EntityType="SchoolModel.Store.Department" store:Type="Tables" />
...
<AssociationSet Name="FK_Course_Department"
Association="SchoolModel.Store.FK_Course_Department">
<End Role="Department" EntitySet="Department" />
<End Role="Course" EntitySet="Course" />
</AssociationSet>
...
</EntityContainer>
<EntityType Name="Course">
<Key>
<PropertyRef Name="CourseID" />
</Key>
<Property Name="CourseID" Type="int" Nullable="false" />
<Property Name="Title" Type="nvarchar" Nullable="false"
MaxLength="100" />
...
</EntityType>
<EntityType Name="Department">
<Key>
<PropertyRef Name="DepartmentID" />
</Key>
<Property Name="DepartmentID" Type="int" Nullable="false" />
<Property Name="Name" Type="nvarchar" Nullable="false"
MaxLength="50" />
...
</EntityType>
...
<Association Name="FK_Course_Department">
<End Role="Department" Type="SchoolModel.Store.Department"
Multiplicity="1" />
<End Role="Course" Type="SchoolModel.Store.Course" Multiplicity="*" />
<ReferentialConstraint>
<Principal Role="Department">
<PropertyRef Name="DepartmentID" />
</Principal>
<Dependent Role="Course">
<PropertyRef Name="CourseID" />
</Dependent>
</ReferentialConstraint>
</Association>
...
</Schema>
映射规范
映射规范使用映射规范语言 (MSL) 将概念性模型中声明的类型连接至存储模型中声明的数据库元数据。此 MSL 片断演示用于 School 模型中的 Course 和 Department 实体的概念性模型与存储模型之间的一对一映射。
<?xml version="1.0" encoding="utf-8"?>
<Mapping Space="C-S"
xmlns="urn:schemas-microsoft-com:windows:storage:mapping:CS">
<EntityContainerMapping StorageEntityContainer="dbo"
CdmEntityContainer="SchoolEntities">
<EntitySetMapping Name="Course">
<EntityTypeMapping TypeName="IsTypeOf(SchoolModel.Course)">
<MappingFragment StoreEntitySet="Course">
<ScalarProperty Name="CourseID" ColumnName="CourseID" />
<ScalarProperty Name="Title" ColumnName="Title" />
...
</MappingFragment>
</EntityTypeMapping>
</EntitySetMapping>
<EntitySetMapping Name="Department">
<EntityTypeMapping TypeName="IsTypeOf(SchoolModel.Department)">
<MappingFragment StoreEntitySet="Department">
<ScalarProperty Name="DepartmentID" ColumnName="DepartmentID" />
<ScalarProperty Name="Name" ColumnName="Name" />
...
</MappingFragment>
</EntityTypeMapping>
</EntitySetMapping>
...
<AssociationSetMapping Name="FK_Course_Department"
TypeName="SchoolModel.FK_Course_Department"
StoreEntitySet="Course">
<EndProperty Name="Department">
<ScalarProperty Name="DepartmentID" ColumnName="DepartmentID" />
</EndProperty>
<EndProperty Name="Course">
<ScalarProperty Name="CourseID" ColumnName="CourseID" />
</EndProperty>
<Condition ColumnName="DepartmentID" IsNull="false" />
</AssociationSetMapping>
...
</cs:EntityContainerMapping>
</Mapping>
讨论
此处讨论的 School 模型在概念性实体与数据库表之间使用简单的一对一映射,但是 实体框架 支持更加复杂的映射。例如,关系数据库可能使用多个表存储与每个员工相关的数据。一个表可能包含所有人员的联系信息,而另一个相关表可能包含仅与员工有关的信息。实体框架 使开发人员可以使用继承层次结构定义实体,并将一个实体映射到数据库中多个表的数据(提供对数据更新、插入和删除的完全支持)。有关更多信息,请参见 实体框架中的数据建模。