EF支持复杂类型的实现

本节,将介绍如何手动构造复杂类型(ComplexType)以及复杂类型的简单操作。
通常,复杂类型是指那些由几个简单的类型组合而成的类型。比如:一张Customer表,其中有FristName和LastName字段,那么对应的Customer实体类将会有FristName和LastName这两个属性。当我们想把FirstName和LastName合成一个名为CustomerName属性时,此时,如果要在EF中实现这个目的,那么我们就需要用到复杂类型。
目前,由于EF不能显示支持复杂类型,所以我们无法在VS里的可视化设计器里面来设计我们需要的复杂类型。所以,我们需要手动修改实体模型,以便使其支持复杂类型的属性。修改的主要步骤有以下几步:

1> 产生实体模型
2> 修改CSDL文件
3> 修改msl文件
4> 重新生成模型实体类

在后续的介绍,我使用数据库使用的是NorthWind,并针对Customer表对应的实体类来增加复杂属性Address,其中复杂属性Address由Address,City,Region,Country和PostalCode这个几个组合而成。
下面,介绍具体的操作步骤:

第一步:产生实体模型
实体模型的产生我们可以直接通过在VS可视化设计器来产生(如果不会,请参考《Entity Framework 学习初级篇1--EF基本概况》)。或者使用EdmGen工具来产生(EdmGen工具位于:系统盘符:\WINDOWS\Microsoft.NET\Framework\v3.5下面)。具体步骤就不复述了。
我产生的实体模型文件是:NorthwindEnites.edmx

第二步:修改csdl文件
产生了实体模型后,我们使用记事本或其他文本编辑工具打开实体模型,(小技巧:可以把实体模型后缀.edmx改为.xml,然后把实体模型文件直接拖到VS里面进行修改,这样修改起来比较方便,待修改完毕后,将后缀改回来即可。)
接着,开始手动修改csdl文件,找到模型文件中关于csdl定义的部分,然后找到实体类型名为Customers的定义节,删除原来的Address,City,Region,Country,PostalCode属性定义,然后添加一个名为Address的属性,如下代码所示:

<EntityType Name="Customers">
  <Key>
    <PropertyRef Name="CustomerID" />
  </Key>
  <Property Name="CustomerID" Type="String" Nullable="false" MaxLength="5" Unicode="true" FixedLength="true" />
  <Property Name="CompanyName" Type="String" Nullable="false" MaxLength="40" Unicode="true" FixedLength="false" />
  <Property Name="ContactName" Type="String" MaxLength="30" Unicode="true" FixedLength="false" />
  <Property Name="ContactTitle" Type="String" MaxLength="30" Unicode="true" FixedLength="false" />
  <Property Name="Address" Type="NorthwindModel.CommonAddress" Nullable="false"></Property>
  <Property Name="Phone" Type="String" MaxLength="24" Unicode="true" FixedLength="false" />
  <Property Name="Fax" Type="String" MaxLength="24" Unicode="true" FixedLength="false" />
  <NavigationProperty Name="Orders" Relationship="NorthwindModel.FK_Orders_Customers" FromRole="Customers" ToRole="Orders" />
  <NavigationProperty Name="CustomerDemographics" Relationship="NorthwindModel.CustomerCustomerDemo" FromRole="Customers" ToRole="CustomerDemographics" />
</EntityType>

接着,需要添加一个名为CommonAddress复杂类型的定义,具体如下代码:

<ComplexType Name="CommonAddress">
  <Property Name="Address" Type="String" MaxLength="60" Unicode="true" FixedLength="false" />
  <Property Name="City" Type="String" MaxLength="15" Unicode="true" FixedLength="false" />
  <Property Name="Region" Type="String" MaxLength="15" Unicode="true" FixedLength="false" />
  <Property Name="PostalCode" Type="String" MaxLength="10" Unicode="true" FixedLength="false" />
  <Property Name="Country" Type="String" MaxLength="15" Unicode="true" FixedLength="false" />
</ComplexType>

至此,csdl部分修改完毕。

第三步,修改msl文件:
找到msl部分的定义,修改Customers部分的影射定义。具体代码如下(请注意ComplexProperty节):

<EntitySetMapping Name="Customers">
    <EntityTypeMapping TypeName="IsTypeOf(NorthwindModel.Customers)">
      <MappingFragment StoreEntitySet="Customers">
    <ScalarProperty Name="CustomerID" ColumnName="CustomerID" />
    <ScalarProperty Name="CompanyName" ColumnName="CompanyName" />
    <ScalarProperty Name="ContactName" ColumnName="ContactName" />
    <ScalarProperty Name="ContactTitle" ColumnName="ContactTitle" />
    <ComplexProperty Name="Address" TypeName="NorthwindModel.CommonAddress">
      <ScalarProperty Name="Address" ColumnName="Address" />
      <ScalarProperty Name="City" ColumnName="City" />
      <ScalarProperty Name="Region" ColumnName="Region" />
      <ScalarProperty Name="PostalCode" ColumnName="PostalCode" />
      <ScalarProperty Name="Country" ColumnName="Country" />
    </ComplexProperty>
    <ScalarProperty Name="Phone" ColumnName="Phone" />
    <ScalarProperty Name="Fax" ColumnName="Fax" />
      </MappingFragment>
    </EntityTypeMapping>
  </EntitySetMapping>

至此,msl部分修改完毕
第四步:重新产生实体类文件。
我们可以使用EmdGen2工具来重新实体类.cs文件。具体操作如下:
将修改好的模型文件(edmx),拷贝到使用edmgen2.exe同目录下,然后在命令行中输入:
Edmgen2 /codegen cs NorthwindEnites.edmx
执行此命令后,会在当前的文件夹下生成一个NorthwindEnites.cs代码文件,也就是实体类的代码文件。将改文件改名为:NorthwindEnites.Designer.cs(这步主要是和edmx对应起来)。
然后,将NorthwindEnites.edmx和NorthwindEnites.Designer.cs文件添加到项目中。
至此,复合类型的修改完毕。
按照同样的修改过程,我们可以给Employees也增加一个Address的复杂类型属性。
接下来,我们看看具体使用代码:

> 查询:

public void TestAddress()
{
    using (var db = new NorthwindModel.NorthwindEntities1())
    {
    Console.WriteLine("Get Five customer addresss :");
    var cts = db.Customers.Take(5);
    foreach (var c in cts)
    {
        Console.WriteLine("Address:{0},Country:{1},City:{2},PostalCode:{3}", c.Address.Address, c.Address.Country, c.Address.City, c.Address.PostalCode);
    }
    Console.WriteLine("Get Five Employess address:");
    var emp = db.Customers.Take(5);
    foreach (var c in emp)
    {
        Console.WriteLine("Address:{0},Country:{1},City:{2},PostalCode:{3}", c.Address.Address, c.Address.Country, c.Address.City, c.Address.PostalCode);
    }
    }
}

>  添加:

public void AddTest()
{
    using (var db = new NorthwindModel.NorthwindEntities1())
    {
    var customer = new NorthwindModel.Customers
    {
        CustomerID = "2009",
        CompanyName = "Complex Company",
        ContactName = "xray2005",
        Address = new NorthwindModel.CommonAddress
        {
        Address = "SiChuan,China",
        City = "ChengDou",
        Country = "China",
        PostalCode = "610041",
        Region = "Chenghua"
        }
    };
    db.AddToCustomers(customer);
    db.SaveChanges();
    var cst = db.Customers.FirstOrDefault(c => c.CustomerID == "2009");
    Assert.IsNotNull(cst);
    Console.WriteLine("CustomerID:{0},CompanyName:{1},ContactName:{2},City:{3},Country:{4}", cst.CustomerID, cst.CompanyName, cst.ContactName, cst.Address.City, cst.Address.Country);
    }
}

>  条件查询:

public void QueryTest()
{
    using (var db = new NorthwindModel.NorthwindEntities1())
    {
    var cst = db.Customers.FirstOrDefault(c => c.Address.City == "ChengDou");
    Assert.IsNotNull(cst);
    Console.WriteLine("CustomerID:{0},CompanyName:{1},ContactName:{2},City:{3},Country:{4}", cst.CustomerID, cst.CompanyName, cst.ContactName, cst.Address.City, cst.Address.Country);
    }
}

最后,补充说明:
1, 在VS的可视化设计器里,不支持复杂类型,所以修改后无法再在可视化设计器里修改模型(edmx文件)。
2, 复杂类型不能单独存在,它必须和某一实体相关起来。
3, 复杂类型不能包含导航属性,如导航到实体或实体集。
4, 复杂类型具有内部结构但没有 Key(主键) 属性的数据类型

时间: 2024-10-01 02:51:23

EF支持复杂类型的实现的相关文章

EF学习笔记-2 EF之支持复杂类型的实现

使用过.NET的小伙伴们知道,在我们的实体模型中,除了一些简单模型外,还有一些复杂类型,如几个简单的类型组合而成的类型:而EF除了在实现基本的增删改查之外,也支持复杂类型的实现. 那么如何手动构造复杂类型(ComplexType)以及复杂类型的简单动作呢?一般比如:一张用户表User,其中有两个字段FirstName和LastName,那么对应的User实体类将会FirstName和LastName两个属性.如果我们想把FirstName和LastName合成一个UserName属性时,并且想要

HTML5:判断浏览器是否支持date类型

在某些情况下,我们需要判断当前浏览器是否支持date类型,如果支持的话,可以让用户用原生的datepicker来选取日期.如果不支持,则我们需要用自己实现的datepicker类库,来提供给用户. 在这里,我们使用Modernizr来实现这一功能,代码如下: 1 if (!Modernizr.inputtypes.date) { 2 $('input[type=date]').datepicker({ 3 }); 4 } HTML5:判断浏览器是否支持date类型,布布扣,bubuko.com

QML的property支持的类型

QML的property支持的类型 本文的qml 运行环境为qt4,在qt5中同样支持. 在Qt SDK 提供的文档中提及property支持类型 qml中的property的作用是动态为对象添加属性,并且添加的属性可以进行跟踪(值被修改了就会发出信号) 添加的属性,官方文档只提及了添加基础类型属性的说明 诸如:int, double,  bool, string, variant, color, real, vector3d, url, time, rect, size, enumeratio

Codeigniter 调试上传不支持的类型文件

打开 codeigniter\system\libraries\Upload.php 文件 找到执行方法 $this->_file_mime_type($_file); 注释后替换成 $this->_file_mime_type($_FILES[$field]); var_dump($this->file_type); die(); //abin add. 然后控制台查看输出的 mime类型是什么 再打开 codeigniter\application\config\mimes.php

原创弹出层插件,支持各类型内容,支持回调函数

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no, minimal-ui" /> <meta name="apple-mobile-web-app-

每天刷个算法题20160522:支持各种类型的并查集

版权所有.所有权利保留. 欢迎转载,转载时请注明出处: http://blog.csdn.net/xiaofei_it/article/details/51524671 为了防止思维僵化,每天刷个算法题.已经刷了几天了,现在发点代码. 我已经建了一个开源项目,每天的题目都在里面: https://github.com/Xiaofei-it/Algorithms 绝大部分算法都是我自己写的,没有参考网上通用代码.读者可能会觉得有的代码晦涩难懂,因为那是我自己的理解. 最近几天都是在写一些原来的东西

SpringMvc 支持一下类型Serlvet 原生的 API 作为目标方法的参数

/** * 可以使用 Serlvet 原生的 API 作为目标方法的参数 具体支持以下类型 * * HttpServletRequest * HttpServletResponse * HttpSession * java.security.Principal * Locale InputStream * OutputStream * Reader * Writer * @throws IOException */ @RequestMapping("/testServletAPI")

EF支持mysq相关配置数码

最近,项目考虑到安装部署方面:希望可以使用MySQL数据库,毕竟比较小巧.方便. 后来,自己通过测试发现EF可以支持mysql数据库,而且也可以通过codefirst模式进行开发:使用起来,跟sqlserver几乎一样.但是,在使用中遇到一些小问题,希望以后大家少走弯路.以下截图,是通过别人的博客copy的(偷懒). 通过NuGet安装MySql 之后,看到项目多出相关几个dll文件 接下來加入 MySQL 的 Model 无法使用EF 需要加入Provider 這時需要在 App.config

支持多种类型的数据集合作为数据源

jqGrid可以绑定三种类型的数据:XML,JSON和数组.使用不同的数据类型主要是设置datatype属性,它的值分别为'xml','json','local'(数组) $("#grid1").jqgrid( ........ datatype: "xml", ........ ); 下面则列举各种数据类型的格式 XML格式: <rows> <page></page> <total></total> &l