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

使用过.NET的小伙伴们知道,在我们的实体模型中,除了一些简单模型外,还有一些复杂类型,如几个简单的类型组合而成的类型;而EF除了在实现基本的增删改查之外,也支持复杂类型的实现。

那么如何手动构造复杂类型(ComplexType)以及复杂类型的简单动作呢?一般比如:一张用户表User,其中有两个字段FirstName和LastName,那么对应的User实体类将会FirstName和LastName两个属性。如果我们想把FirstName和LastName合成一个UserName属性时,并且想要在EF中实现这个想法,我们就需要用到复杂类型。

目前,由于EF不能显示支持复杂类型,所以我们也无法在VS中的可视化设计器中设计该复杂类型,所以我们只能暂时手动修改实体类型,以便可以支持复杂类型的属性。有如下几个步骤:

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

在后续的介绍中,我会针对User表对应的实体类来增加复杂属性TelePhone,其中复杂属性TelePhone由Tel,NickName,Emal组成。

一、产生实体模型

实体模型我们可以使用VS自带的可视化设计器来实现。了解过EF的基础的朋友应该知道这个设计,具体步骤这里就复述了。我产生的实体模型UserInfoEntity.edmx。

二、修改CSDL文件

产生实体文件后,我们可以使用Notepad++打开实体模型,找到实体模型中关于CSDL定义的部分,然后找到实体类型名为Users的定义节,删除原来的Tel,NickName,Emal属性定义,增加一个名为TelePhone的属性节点。代码如下所示:

 <EntityType Name="Users">
  <Key>
    <PropertyRef Name="UsersID" />
  </Key>
  <Property Name="UserID" 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>

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

<ComplexType Name="CommonTelePhone">
  <Property Name="Address" Type="String" MaxLength="60" Unicode="true" FixedLength="false" />
  <Property Name="NickName" Type="String" MaxLength="30" Unicode="true" FixedLength="false" />
  <Property Name="Region" Type="String" MaxLength="15" Unicode="true" FixedLength="false" />
  <Property Name="Emal" Type="String" MaxLength="10" Unicode="true" FixedLength="false" />
  <Property Name="Tel" Type="String" MaxLength="15" Unicode="true" FixedLength="false" />
</ComplexType>

到此,CSDL的修改部分已完毕。

三、MSL文件

找到MSL部分的定义,修改Users部分的影射定义。代码如下所示(请注意ComplexProperty 节):

 <EntitySetMapping Name="Users">
  <EntityTypeMapping TypeName="IsTypeOf(NorthwindModel.Customers)">
    <MappingFragment StoreEntitySet="Customers">
      <ScalarProperty Name="UserID" 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="NickName" ColumnName="NickName" />
        <ScalarProperty Name="Region" ColumnName="Region" />
        <ScalarProperty Name="Emal" ColumnName="Emal" />
        <ScalarProperty Name="Tel" ColumnName="Tel" />
      </ComplexProperty>
      <ScalarProperty Name="Phone" ColumnName="Phone" />
      <ScalarProperty Name="Fax" ColumnName="Fax" />
    </MappingFragment>
  </EntityTypeMapping>
</EntitySetMapping>

到此,MSL的修改部分已完毕。

四、重新产生实体类文件

我们可以使用EmdGen2工具来重新生成实体类.cs的文件。对于EmdGen2工具的使用方法就不在这里介绍了。具体可百度或者查看我之后关于EmdGen2工具的使用方法的博客。那么这里的具体操作就是如下所示。

将修改好的模型文件(edmx),拷贝到emdgen2.exe目录下,然后在命令行中输入:Emdgen2 /codegen cs NorthwindEnites.edmx。执行此命令后,会在当前文件夹中生成一个NorthwindEnites.cs的文件,也就是实体类的代码文件。接着将文件名改成:NorthwindEnites.Designer.cs,这一步骤主要是和edmx对应起来。

最后,将 NorthwindEnites.edmx 和NorthwindEnites.Designer.cs 文件添加到项目中。

至此,复合类型的修改完毕。

按照上述操作步骤,我们可以给Employess也增加一个Address 的复杂类型属性。

接下来,我们看看具体使用代码:

查询

public void TestAddress()
        {
            using (var db = new NorthwindModel.NorthwindEntities1())
            {
                Console.WriteLine("Get first users addresss :");
                var cts = db.Customers.Take(5);
                foreach (var c in cts)
                {
                    Console.WriteLine("Address:{0},Tel:{1},NickName:{2},Emal:{3}",
                        c.Address.Address, c.Address.Tel, c.Address.NickName, c.Address.Emal);
                }
                Console.WriteLine("Get first Employess address:");
                var emp = db.Customers.Take(5);
                foreach (var c in emp)
                {
                    Console.WriteLine("Address:{0},Tel:{1},NickName:{2},Emal:{3}",
                        c.Address.Address, c.Address.Tel, c.Address.NickName, c.Address.Emal);
                }
            }
        }

添加

public void AddTest()
        {
            using (var db = new NorthwindModel.NorthwindEntities1())
            {
                var customer = new NorthwindModel.Customers
                {
                    UserID = "340956",
                    CompanyName = "JinShan Company",
                    ContactName = "xray2017",
                    Address = new NorthwindModel.CommonAddress
                    {
                        Address = "WuHan,China",
                        NickName = "AiXiaoJun",
                        Tel = "15290896766",
                        Emal = "[email protected]",
                        Region = "LiuHeng"
                    }
                };
                db.AddToCustomers(customer);
                db.SaveChanges();
                var cst = db.Customers.FirstOrDefault(c => c.CustomerID == "2009");
                Assert.IsNotNull(cst);
                Console.WriteLine("UserID:{0},CompanyName:{1},ContactName:{2},NickName:{3},Tel:{4}",
                    cst.UserID, cst.CompanyName, cst.ContactName, cst.Address.NickName, cst.Address.Tel);
            }
        }

有不对的地方请各位批评指正,互相学习!

原文地址:https://www.cnblogs.com/aixiaojun/p/8993194.html

时间: 2024-10-12 15:48:48

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

EF学习笔记(九):异步处理和存储过程

总目录:ASP.NET MVC5 及 EF6 学习笔记 - (目录整理) 上一篇:EF学习笔记(八):更新关联数据 本篇原文:Async and Stored Procedures 为何要采用异步? 一个Web服务器肯定有可用线程的限制,那么在一些访问量特别大的情况下,线程肯定会消耗完:这个时候服务器肯定处理不了请求,必须等线程里处理结束才可以处理请求: 在非异步的时候,很多线程都处于等待状态,并不是一直在工作,而是在等类似于I/O等处理结束: 采用异步的时候,当一个处理在等待I/O处理结束的时

EF学习笔记(十一):实施继承

学习总目录:ASP.NET MVC5 及 EF6 学习笔记 - (目录整理) 上篇链接:EF学习笔记(十) 处理并发 本篇原文链接:Implementing Inheritance 面向对象的世界里,继承可以很好的重用代码.在本章就对Instructor和Student两个类进行实施继承处理,这两个类有公用的属性,比如LastName等,也有私有的属性: 可以不用增加任何页面,进行修改一些代码,这些修改后的继承关系就会自动反应到数据库中. 通过下图可以看到两个类有哪些公用属性: 那么就可以建一个

EF学习笔记(八):更新关联数据

学习笔记主目录链接:ASP.NET MVC5 及 EF6 学习笔记 - (目录整理) 上一篇链接:EF学习笔记(七):读取关联数据 本篇原文链接:Updating Related Data 本篇主要考虑对于有关联的数据进行新增.删除.更新操作:比如Course .Instructor: 对于Course来说,新增时候必须定义属于哪个Department,所以在新增.更新操作的时候,必须要用户选择Department: MVC5在选择基础控制器及视图框架的时候,如果选择EF的操作框架,则会自动带一

python基础教程_学习笔记22:数据库支持

数据库支持 python数据库API 支持sql标准的可用数据库有很多,其中多数在python中都有对应的客户端模块. 全局变量 python DB API的模块特性 变量名 用途 apilevel 所使用的python db api版本 threadsafety 模块的线程安全等级 paramstyle 在sql查询中使用的参数风格 异常 异常 超类 描述 StandardError 所有异常的泛型基类 Warning StandardError 在非致命错误发生时引发 Error Stand

[Spring MVC]学习笔记--@RequestMapping支持的返回类型

下面针对官方文档列出的支持类型进行举例. (本篇例子存于github上, https://github.com/lemonbar/spring-mvc-resolvingview) 可以直接下载, 也可以在浏览器中打开进行查看(强烈建议看这个, 里面有详细的解释). git clone https://github.com/lemonbar/spring-mvc-resolvingview 准备工作 1. 在WEB-INF下增加一个jsp文件夹, 里面增加两个jsp文件, 为login.jsp和

《iOS应用逆向工程》学习笔记(四)iOS程序类型

越狱iOS中最常见的程序有Application, Dynamic Library和Daemon三类. 1.Application 除了传统意义上的App外,越狱iOS平台上还有两种App形式的存在:WeeApp(依附于NotificationCenter的App)和PreferenceBundle(依附于Settings的App),常见于Cydia平台. 普通App的bundle中存放的是可执行程序和所需资源,而framework的bundle中存放的是动态链接库. 主要关注App中的三个部分

IOS开发学习笔记-(2)键盘控制,键盘类型设置,alert 对话框

一.关闭键盘,放弃第一响应者,处理思路有两种 ① 使用文本框的 Did End on Exit 绑定事件 ② UIControl on Touch 事件 都去操作 sender 的  resignFirstResponder #import <UIKit/UIKit.h> @interface ViewController : UIViewController @property (weak, nonatomic) IBOutlet UITextField *txtUserName; @pro

C++学习笔记:不用sizeof判断int类型占用几个字节

#include <stdio.h> #include <string.h> char *change(int val, int base, char *retbuf) { static const char *str = "0123456789ABCDEF"; char *p; char buf[15]; p = buf+14; *p = 0; do { *--p = str[val % base]; } while( val /= base ); strcp

一起学ASP.NET Core 2.0学习笔记(二): ef core2.0 及mysql provider 、Fluent API相关配置及迁移

不得不说微软的技术迭代还是很快的,上了微软的船就得跟着她走下去,前文一起学ASP.NET Core 2.0学习笔记(一): CentOS下 .net core2 sdk nginx.supervisor.mysql环境搭建搭建好了.net core linux的相关环境,今天就来说说ef core相关的配置及迁移: 简介: Entity Framework(以下简称EF) 是微软以 ADO.NET 为基础所发展出来的对象关系对应 (O/R Mapping) 解决方案,EF Core是Entity