EF实体框架之CodeFirst五
上一博客学习了下基本的约定配置,留下几个遗漏的,这篇就是学习下遗漏一复杂类型。
一、什么是复杂类型?
书中说道:“复杂类型也可视作值类型(?)可以作为附加属性添加到其他类。复杂类型与实体类型的区别在于复杂类型没有其自己的键。它是依赖于其"宿主"类型跟踪变化 和持久化。一个没有Key属性的类型,并且作为属性映射到一个或多个类型中,Code First就会将其视作为复杂类型。Code First将预设复杂类型的属性出现在宿主类型映射到数据库的表中。”
说简单一点就是,项目中有个类A,这个A,会被其他类引用到比如:实体类B 和 实体类C,但是建立数据库的时候,我们不想为这个分割类A建立表,而是把A类中的属性等建立到 B 和 C 映射的表中,这时候,我们管 A 叫做复杂类型。
二、复杂类型和实体类型的区别
首先还是定义两个类Person类和IDCard类还有数据库上下文。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.Entity;
using EFCodeFirstModels;
using System.Configuration; namespace EFCodeFirstDataAccess
{
public class EFCodeFirstDbContext:DbContext
{ public EFCodeFirstDbContext() : base("MyStrConn")
{
}
public DbSet<Person> Persons { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace EFCodeFirstModels
{
public enum SexType { Male, Female } [Table("Person")]
public class Person
{
[Key]
public string PersonId { get; set; }
//姓名 public string Name { get; set; }
//性别
public SexType Sex { get; set; }
//年龄
public int Age { get; set; } public IDCard Card { get; set; } public Person(string personId, string name, SexType sex, int age,IDCard card)
{
PersonId = personId;
Name = name;
Sex = sex;
Age = age;
Card = card; }
public Person() { }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; namespace EFCodeFirstModels
{ public class IDCard
{
//法定出生日期
public DateTime BirthDate { get; set; } }
}
在上面的IDCard中并没有主键,这个是需要留意的,然后呢新增一个Person对象在数据库上下文中。
using (var db=new EFCodeFirstDbContext())
{
IDCard card = new IDCard();
card.BirthDate = DateTime.Now;
Person p = new Person("","cuiyanwei",SexType.Female,,card);
db.Persons.Add(p);
db.SaveChanges();
Console.WriteLine("Scueess");
}
此时会生成下面的表结构。

上面可以看到Person表中增加了一个Card_BirthDate列,但是如果在IDCard类中增加一个主键,结果就会不一样。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; namespace EFCodeFirstModels
{ public class IDCard
{
[Key]
public int CardId { get; set; }
//法定出生日期
public DateTime BirthDate { get; set; } }
}

可以看到,数据库中多生成了一个表。Person表中增加了一个外键Card_CardId.
三、复杂类型嵌套
看到这你可能会问这也没提到复杂类型几个字啊,哪来的复杂类型了。上面的例子中IDCard虽然也是复杂类型,由于IDCard类中属性比较简单,没有嵌套这其他的类,所以EF就默认映射到Person表中了,但是假如IDCard类中有其他的类,属于类型嵌套的话那就麻烦了。首先看下如果有嵌套不指定会怎么样?
可以在IDCard类中增加一个属性,用来表示出生地方的经纬度(做个比喻,不可能人出生在一个经纬度的点上,也是大致的位置)。经纬度用Location类表示。
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace EFCodeFirstModels
{
//[ComplexType]
public class Location
{
//经度
public double Longitude { get; set; } //纬度
public double Latitude { get; set; } }
}
public class IDCard
{ //法定出生日期
public DateTime BirthDate { get; set; } //出生地的位置 经纬度
public Location BirthPlace { get; set; } }
同样新增一个Person对象,此时就会报下面的错误。

这是为什么呢?因为系统识别不了IDCard类是复杂类型。那怎么解决呢,很简单。只需指定IDCard是复杂类型就ok了。
[ComplexType]
public class IDCard

而在Location类上并没有指定复杂类型,这也将Location类认为是复杂类型。
EF实体框架之CodeFirst五的更多相关文章
- EF实体框架之CodeFirst四
在EF实体框架之CodeFirst二中也提到数据库里面一般包括表.列.约束.主外键.级联操作.实体关系(E-R图).存储过程.视图.锁.事务.数据库结构更新等.前面几篇博客把表.存储过程.视图这些算是 ...
- EF实体框架之CodeFirst一
对于SQL Server.MySql.Oracle等这些传统的数据库,基本都是关系型数据库,都是体现实体与实体之间的联系,在以前开发时,可能先根据需求设计数据库,然后在写Model和业务逻辑,对于Mo ...
- EF实体框架之CodeFirst二
在codefirst一中也说了Mapping是实体与数据库的纽带,model通过Mapping映射到数据库,我们可以从数据库的角度来分析?首先是映射到数据库,这个是必须的.数据库里面一般包括表.列.约 ...
- EF实体框架之CodeFirst六
上午的时候把复杂类型学习了一下,想着趁着周六日把Code First学习完,所以下午还是把Code First中的关系学习下.在数据库中最重要的恐怕就是E-R图了,E-R体现了表与表直接的关系.使用C ...
- EF实体框架之CodeFirst七
前面的6篇博客基本把Code First学习的差不多了,今天这篇学习下code first中的并发控制和事务,基本也快学完了,顶多就差数据迁移. 在数据库中也是有锁和事务的概念,在C#中也是存在,当然 ...
- EF实体框架之CodeFirst三
前两篇博客学习了数据库映射和表映射,今天学习下数据库初始化.种子数据.EF执行sql以及执行存储过程这几个知识. 一.数据库初始化策略 数据库初始化有4种策略 策略一:数据库不存在时重新创建数据库 D ...
- EF实体框架之CodeFirst八
前面七篇基本把Code First学习了一下,不过code first中会出现一个问题,就是数据迁移的问题. 一.数据准备 还是在前面的demo上修改,这次使用Province和City类. publ ...
- C#.Net EF实体框架入门视频教程
当前位置: 主页 > 编程开发 > C_VC视频教程 > C#.Net EF实体框架入门视频教程 > kingstone金士顿手机内存卡16G仅65元 1.EF实体框架之增加查 ...
- EF实体框架处理实体之间关联关系与EF延迟机制(下)
在数据库中,表与表之间可能存在多种联系,比如,一对多,多对多的关系.当我们使用逻辑外键在数据库建立两张表之间的关系的时候,我们使用EF实体框架 必然也会将这种关系映射到我们的实体关系中来.所以,在我们 ...
随机推荐
- 使用jsonp进行跨域访问
一.使用场景 当我们请求非本服务器的资源的时候,浏览器会禁止访问,并提示不允许跨域访问.此时我们可以使用jsonp这种请求方式,从其他服务器获取资源.在客户端调用提供jsonp支持的接口,获取json ...
- C语言的数据类型及其对应变量
声明,定义和初始化 声明标识符iden是告诉编译器"有这么一个变量var,具体var里是什么,你自己去看".声明只需要标识符的类型和标识符名字,C语言的任何标识符在使用前都需要声明 ...
- gdb调试常用命令
gdb 调试常用命令 gcc -g mian.c -o main.out -o (定制生成的可执行文件的名称,缺省时为a.out) -g 使gdb可调试,在编译的时候,产生调试信息 gdb main. ...
- Linux 学习之DNS服务器
概念: DNS:Domain Name System 域名系统 FQDN:Fully Qualified Domain Name 完整主机名 正向解析:由主机名查IP地址 SOA:开始验证(Start ...
- Linux 环境下如何使 Chrome 浏览器字体更漂亮
Windows 就免谈了,本身字体渲染技术 Cleartype 以及 DirectWrite 就稀烂得一塌糊涂.Mac 下面本来字体渲染就很好,所以关键就是在 Linux 下如何使 Chrome 的字 ...
- Java 如何有效地避免OOM:善于利用软引用和弱引用
Java 如何有效地避免OOM:善于利用软引用和弱引用 想必很多朋友对OOM(OutOfMemory)这个错误不会陌生,而当遇到这种错误如何有效地解决这个问题呢?今天我们就来说一下如何利用软引用和弱引 ...
- codeforces 484B B. Maximum Value(二分)
题目链接: B. Maximum Value time limit per test 1 second memory limit per test 256 megabytes input standa ...
- 常用中文字体 Unicode 编码
各大网站的字体选择 网站 字体 腾讯 font: 12px "宋体","Arial Narrow",HELVETICA; 淘宝 font: 12px/1.5 t ...
- Hibernate之Query接口的uniqueResult()方法
如果查询返回多个值用list()方法 public void testQuery(){ Configuration config = new Configuration().configure(); ...
- 第11章 Windows线程池(3)_私有的线程池
11.3 私有的线程池 11.3.1 创建和销毁私有的线程池 (1)进程默认线程池 当调用CreateThreadpoolwork.CreateThreadpoolTimer.CreateThread ...