前言
最近项目中用到了EF,初次接触,使用了基本的增删改查。而对于EF底层的原理,却没有了解的透彻。俗话说,知其然,还要知其所以然。
一、EF和ORM
ORM(Object-Relational-Mapping)对象关系映射,是将关系型数据库的表关系映射成面向对象中的对象模型。EF是将表实体的变化,映射到数据表的变化。
注意:ORM框架采用元数据来描述对象一关系映射细节,元数据一般采用XML格式,并且存放在专门的对象一映射文件中。只要提供了持久化类与表的映射关系,ORM框架在运行时就能参照映射文件的信息,把对象持久化到数据库中
二、EF如何实现ORM
EF是通过xml的方式实现映射的。这里采用DBFirst的方式生成EF实体模型,即Model1.edmx.使用xml编辑器打开,如图:
分为三层:存储层SSDL、概念层CSDL、映射层C-S
存储层SSDL代码示例:
<edmx:StorageModels>
<Schema Namespace="Model1.Store" Provider="Oracle.ManagedDataAccess.Client" ProviderManifestToken="12.1" Alias="Self" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" xmlns:customannotation="http://schemas.microsoft.com/ado/2013/11/edm/customannotation" xmlns="http://schemas.microsoft.com/ado/2009/11/edm/ssdl">
<EntityType Name="DEPTINFO">
<Key>
<PropertyRef Name="DEPTINFONO" />
</Key>
<Property Name="DEPTINFONO" Type="varchar2" MaxLength="32" Nullable="false" />
<Property Name="deptname" Type="varchar2" MaxLength="32" />
<Property Name="deptnumber" Type="number" Precision="38" Scale="0" />
<Property Name="deptboss" Type="varchar2" MaxLength="32" />
<Property Name="DEPTRESERVE1" Type="varchar2" MaxLength="24" />
<Property Name="DEPTRESERVE2" Type="varchar2" MaxLength="24" />
<Property Name="deptdesc" Type="varchar2" MaxLength="255" />
</EntityType>
存放数据库中表中字段信息(名称、类型、长度、精度范围等),与数据库内容一致
概念层CSDL代码示例:
<edmx:ConceptualModels>
<Schema Namespace="Model1" Alias="Self" annotation:UseStrongSpatialTypes="false" xmlns:annotation="http://schemas.microsoft.com/ado/2009/02/edm/annotation" xmlns:customannotation="http://schemas.microsoft.com/ado/2013/11/edm/customannotation" xmlns="http://schemas.microsoft.com/ado/2009/11/edm">
<EntityType Name="DEPTINFO">
<Key>
<PropertyRef Name="DEPTINFONO" />
</Key>
<Property Name="DEPTINFONO" Type="String" MaxLength="32" FixedLength="false" Unicode="false" Nullable="false" />
<Property Name="deptname" Type="String" MaxLength="32" FixedLength="false" Unicode="false" />
<Property Name="deptnumber" Type="Decimal" Precision="38" Scale="0" />
<Property Name="deptboss" Type="String" MaxLength="32" FixedLength="false" Unicode="false" />
<Property Name="DEPTRESERVE1" Type="String" MaxLength="24" FixedLength="false" Unicode="false" />
<Property Name="DEPTRESERVE2" Type="String" MaxLength="24" FixedLength="false" Unicode="false" />
<Property Name="deptdesc" Type="String" MaxLength="255" FixedLength="false" Unicode="false" />
<NavigationProperty Name="SAFEGUARDPLAN" Relationship="Self.FK_SGP_DEPTINFONO" FromRole="DEPTINFO" ToRole="SAFEGUARDPLAN" />
<NavigationProperty Name="SQUADRONINFO" Relationship="Self.FK_SQUAD_DEPTINFONO" FromRole="DEPTINFO" ToRole="SQUADRONINFO" />
</EntityType>
<EntityType Name="DEVICEINFO">
存放映射之后类中属性信息(名称、类型、最大长度、精度范围等),与c#类用法保持一致
C-S映射层代码示例:
<edmx:Mappings>
<Mapping Space="C-S" xmlns="http://schemas.microsoft.com/ado/2009/11/mapping/cs">
<EntityContainerMapping StorageEntityContainer="Model1StoreContainer" CdmEntityContainer="Entities1">
<EntitySetMapping Name="DEPTINFO">
<EntityTypeMapping TypeName="Model1.DEPTINFO">
<MappingFragment StoreEntitySet="DEPTINFO">
<ScalarProperty Name="DEPTINFONO" ColumnName="DEPTINFONO" />
<ScalarProperty Name="deptname" ColumnName="deptname" />
<ScalarProperty Name="deptnumber" ColumnName="deptnumber" />
<ScalarProperty Name="deptboss" ColumnName="deptboss" />
<ScalarProperty Name="DEPTRESERVE1" ColumnName="DEPTRESERVE1" />
<ScalarProperty Name="DEPTRESERVE2" ColumnName="DEPTRESERVE2" />
<ScalarProperty Name="deptdesc" ColumnName="deptdesc" />
</MappingFragment>
</EntityTypeMapping>
</EntitySetMapping>
C-S映射层是EF的核心,是将存储层SSDL中的表信息与概念层CDSL的类信息对应映射。
接下针对每一层的核心内容一一分析。