5.2.3 Describing the database in the storage schema
在OrderIT例子的EDMX文件里,存储模型在edmx:Edmx/edmx:Runtime/edmx:StorageModels路径下。
但是如果你想手动创建文件,你可以为他起名OrderIT.ssdl,并在链接字符串引用他。
Schema
Schema是存储模型的根元素。他比概念模型中的Schema多了两个属性。
Provider-----指定ADO.NET提供程序
ProviderMainfestToken-----指定数据库版本号(SQL Server 2000,2005,2008).
下面是Scmema元素的一个例子:
<Schema
Namespace="OrderITModel.Store"
Alias="Self" Provider="System.Data.SqlClient"
ProviderManifestToken="2008" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/" xmlns="http://schemas.microsoft.com/ado/2009/02/edm/ssdl"> ... </Schema>
EntityContainer
EntityContainer声明了之后要描述的文件里的所有数据库对象。他只有一个表示container名称的属性Name。设计器给他复制是他的命名空间加上后缀
(suffix)StoreContainer。在存储模型里只有一个EntityContainer元素,因为对象属于单一的数据库。在EntityContainer里,你可以为每个表或视图创建一个EntitySet元素。
相对于在概念模型里,EntitySet在存储模型中有更多的属性:
Name--指定对象的逻辑名称。设计器使用表的名称,但是这不是强制性的(mandatory)。
EntityType--代表对象的FQN(fully qualified name),使用{namespace}.{name}格式。
Schema--表示表的拥有者。
Table--表的实体名称。Table不是必须添加的,当他被省略(omitted)的时候,Name被使用。
store:Type--确定对象时表还是视图。
下面是代码片段:
<EntityContainer Name="OrderITModelStoreContainer"> <EntitySet Name="Order" EntityType="OrderITModel.Store.Order" store:Type="Tables" Schema="dbo" /> <EntitySet Name="OrderDetail" EntityType="OrderITModel.Store.OrderDetail" store:Type="Tables" Schema="dbo" /> </EntityContainer>
EntityType
用EntityType元素描述对象,就像(much as)在概念模型文件一样。你必须为放在EntityContainer里的每个EntitySet元素创建一个元素。在概念文件里,classes是继承层
次结构(inheritance hierarchy)的一部分,他有一个EntitySet和很多的EntityType。数据库本身(natively)不支持继承,所以在存储文件里,不可能有一个实体集对应许多表或视
图。每个EntityType节点有一个Name属性,他的值必须匹配entity container里的EntitySet的Name属性。
Property与在CSDL里的副本有相同的属性,加上一些其他的来满足数据库的需要:
Collation--Specifies the collation of the column
DefaultValue--指定列的默认值
Unicode--指定值是不是字符编码
代码片段:
<EntityType Name="Order"> <Key> <PropertyRef Name="OrderId" /> </Key> <Property Name="OrderId" Type="int" StoreGeneratedPattern="Identity" Nullable="false" /> <Property Name="ShippingAddress" Type="nvarchar" Nullable="false" MaxLength="50" /> <Property Name="ShippingCity" Type="nvarchar" Nullable="false" MaxLength="50" /> <Property Name="ShippingZipCode" Type="nvarchar" Nullable="false" MaxLength="15" /> <Property Name="ShippingCountry" Type="nvarchar" Nullable="false" MaxLength="30" /> <Property Name="EstimatedShippingDate" Type="datetime" Nullable="false"/> <Property Name="ActualShippingDate" Type="datetime" Nullable="false" /> <Property Name="CustomerId" Type="int" Nullable="false" /> </EntityType> <EntityType Name="OrderDetail"> <Key> <PropertyRef Name="OrderDetailId" /> </Key> <Property Name="OrderDetailId" Type="int" StoreGeneratedPattern="Identity" Nullable="false" /> <Property Name="Quantity" Type="smallint" Nullable="false" /> <Property Name="UnitPrice" Type="decimal" Nullable="false" Precision="29" Scale="29" /> <Property Name="Discount" Type="decimal" Nullable="false" Precision="29" Scale="29" /> <Property Name="OrderId" Type="int" Nullable="false" /> <Property Name="ProductId" Type="int" Nullable="false" /> </EntityType>
存储模型也完成了,现在你只需要将概念模型和存储模型链接起来。
5.2.4 Creating the mapping file
在OrderIT例子的EDMX文件里,edmx:Edmx/edmx:Runtime/edmx:Mappings是映射部分的路径。如果你想创建自己的文件,你可以创建OrderIT.msl然后在链接字符串
里指定他。
Mapping and EntityContainerMapping
Mapping节点的声明是固定的。StorageEntityContainer属性用来指定存储模型容器,CdmEntityContainer属性用于概念模型,看代码:
<Mapping Space="C-S" xmlns="http://schemas.microsoft.com/ado/2008/09/mapping/cs"> <EntityContainerMapping CdmEntityContainer="OrderITEntities" StorageEntityContainer="OrderITModelStoreContainer"> ... </EntityContainerMapping> </Mapping>
在实体容器被链接后,下一步是将表和视图映射到类。这个用在EntityContainerMapping元素内的EntitySetMapping元素来完成。
EntitySetMapping, EntityTypeMapping, and MappingFragment
EntitySetMapping节点让你去声明哪个实体集是你要映射的(记住,在一个实体集内你可以有多个类)。他只有一个属性Name,用来指定实体集名字。
在EntitySetMapping里面,你为每个实体添加一个EntityTypeMapping元素。通过TypeName属性设定实体类型,设定的必须格式为IsTypeOf(EntityName),EntityName
是实体的完全名称。
现在我们来映射表。因为一个类个可以映射到一个活多个表(Order映射到Order表,但是Shirt映射到Product和Shirt表),在EntityTypeMapping元素里你可以为每个涉及的
表指定一个MappingFragment元素。他只有StoreEntitySet属性,他必须匹配在存储模型里的实体集的Name属性。代码:
<EntitySetMapping Name="Orders"> <EntityTypeMapping TypeName="IsTypeOf(OrderITModel.Order)"> <MappingFragment StoreEntitySet="Order"> ... </MappingFragment> </EntityTypeMapping> </EntitySetMapping>
<EntitySetMapping Name="OrderDetails"> <EntityTypeMapping TypeName="IsTypeOf(OrderITModel.OrderDetail)"> <MappingFragment StoreEntitySet="OrderDetail"> ... </MappingFragment> </EntityTypeMapping> </EntitySetMapping>
ScalarProperty and ComplexProperty
ScalarProperty 两个属性:
Name--代表属性名。
ColumnName--代表被映射的列。
ComplexProperty 两个属性:
Name--指定类里的属性名称。
TypeName--包含复杂类型的完全名称。
ComplexProperty 本身是没有用的。你要将他的属性映射到列,这可以用嵌套ScalarProperty元素来完成。
注意:因为复杂类型可以嵌套(nested),你可以将一个ComplexProperty放到另一个ComplexProperty里。
代码:
<EntitySetMapping Name="Orders"> <EntityTypeMapping TypeName="IsTypeOf(OrderITModel.Order)"> <MappingFragment StoreEntitySet="Order"> <ScalarProperty Name="Id" ColumnName="Id" /> <ComplexProperty Name="ShippingAddress" TypeName="OrderITModel.AddressInfo"> <ScalarProperty Name="Address" ColumnName="ShippingAddress" /> <ScalarProperty Name="City" ColumnName="ShippingCity" /> <ScalarProperty Name="ZipCode" ColumnName="ShippingZipCode" /> <ScalarProperty Name="Country" ColumnName="ShippingCountry" /> </ComplexProperty> <ScalarProperty Name="EstimatedShippingDate" ColumnName="EstimatedShippingDate" /> <ScalarProperty Name="ActualShippingDate" ColumnName="ActualShippingDate" /> </MappingFragment> </EntityTypeMapping> </EntitySetMapping>
<EntitySetMapping Name="OrderDetails"> <EntityTypeMapping TypeName="IsTypeOf(OrderITModel.OrderDetail)"> <MappingFragment StoreEntitySet="OrderDetail"> <ScalarProperty Name="Id" ColumnName="Id" /> <ScalarProperty Name="Quantity" ColumnName="Quantity" /> <ScalarProperty Name="UnitPrice" ColumnName="UnitPrice" /> <ScalarProperty Name="Discount" ColumnName="Discount" /> </MappingFragment> </EntityTypeMapping> </EntitySetMapping>