上一博客学习了下基本的约定配置,留下几个遗漏的,这篇就是学习下遗漏一复杂类型。

一、什么是复杂类型?

书中说道:“复杂类型也可视作值类型(?)可以作为附加属性添加到其他类。复杂类型与实体类型的区别在于复杂类型没有其自己的键。它是依赖于其"宿主"类型跟踪变化 和持久化。一个没有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五的更多相关文章

  1. EF实体框架之CodeFirst四

    在EF实体框架之CodeFirst二中也提到数据库里面一般包括表.列.约束.主外键.级联操作.实体关系(E-R图).存储过程.视图.锁.事务.数据库结构更新等.前面几篇博客把表.存储过程.视图这些算是 ...

  2. EF实体框架之CodeFirst一

    对于SQL Server.MySql.Oracle等这些传统的数据库,基本都是关系型数据库,都是体现实体与实体之间的联系,在以前开发时,可能先根据需求设计数据库,然后在写Model和业务逻辑,对于Mo ...

  3. EF实体框架之CodeFirst二

    在codefirst一中也说了Mapping是实体与数据库的纽带,model通过Mapping映射到数据库,我们可以从数据库的角度来分析?首先是映射到数据库,这个是必须的.数据库里面一般包括表.列.约 ...

  4. EF实体框架之CodeFirst六

    上午的时候把复杂类型学习了一下,想着趁着周六日把Code First学习完,所以下午还是把Code First中的关系学习下.在数据库中最重要的恐怕就是E-R图了,E-R体现了表与表直接的关系.使用C ...

  5. EF实体框架之CodeFirst七

    前面的6篇博客基本把Code First学习的差不多了,今天这篇学习下code first中的并发控制和事务,基本也快学完了,顶多就差数据迁移. 在数据库中也是有锁和事务的概念,在C#中也是存在,当然 ...

  6. EF实体框架之CodeFirst三

    前两篇博客学习了数据库映射和表映射,今天学习下数据库初始化.种子数据.EF执行sql以及执行存储过程这几个知识. 一.数据库初始化策略 数据库初始化有4种策略 策略一:数据库不存在时重新创建数据库 D ...

  7. EF实体框架之CodeFirst八

    前面七篇基本把Code First学习了一下,不过code first中会出现一个问题,就是数据迁移的问题. 一.数据准备 还是在前面的demo上修改,这次使用Province和City类. publ ...

  8. C#.Net EF实体框架入门视频教程

    当前位置: 主页 > 编程开发 > C_VC视频教程 > C#.Net EF实体框架入门视频教程 > kingstone金士顿手机内存卡16G仅65元 1.EF实体框架之增加查 ...

  9. EF实体框架处理实体之间关联关系与EF延迟机制(下)

    在数据库中,表与表之间可能存在多种联系,比如,一对多,多对多的关系.当我们使用逻辑外键在数据库建立两张表之间的关系的时候,我们使用EF实体框架 必然也会将这种关系映射到我们的实体关系中来.所以,在我们 ...

随机推荐

  1. Swing应用开发实战系列之三:动态信息提示窗口

    这里所说的“动态信息提示窗口”可不同于JOptionPane中的Message窗口和Confirm窗口,它们都是静态的模态的,更重要的是线程阻塞的,迫使你必须选择某个动作才能继续执行.我们接下来要分享 ...

  2. ubuntu16.04下opencv安装笔记和例程

    问题: 最近重装了系统,需要重新配置opencv2.4.13,配置完成后每次都出现cmake error,google了报错,尝试了各种方法,都未解决问题,于是重新git clone 了opencv2 ...

  3. 初识zookeeper(一)之zookeeper的安装及配置

    1.简要介绍 zookeeper是一个分布式的应用程序协调服务,是Hadoop和Hbase的重要组件,是一个树型的目录服务,支持变更推送.除此还可以用作dubbo服务的注册中心. 2.安装 2.1 下 ...

  4. Linux awk

    一.简介 二.教程 1)过滤字符(对大小写很敏感) dir -l | awk '$3=="root" {print $1,$3,$4, $9;} ' cat tecmint_dea ...

  5. Linux vagrant+virtualbox环境搭建步骤

    Linux vagrant+virtualbox环境搭建步骤 Vagrant 是一款用来构建虚拟开发环境的工具,非常适合 php/python/ruby/java 这类语言开发 web 应用. 我们可 ...

  6. [转]How to insert a row between two rows in an existing excel with HSSF (Apache POI)

    本文转自:http://stackoverflow.com/questions/5785724/how-to-insert-a-row-between-two-rows-in-an-existing- ...

  7. codeforces 616E Sum of Remainders (数论,找规律)

    E. Sum of Remainders time limit per test 2 seconds memory limit per test 256 megabytes input standar ...

  8. Javascript中的对象和原型(3)

    在Javascript中的对象和原型(二)中我们提到,用构造函数创建的对象里面,每个对象之间都是独立的,这样就会降低系统资源的利用率,解决这样问题,我们就要用到下面提到的原型对象. 一 原型对象 原型 ...

  9. Sql注入截取字符串常用函数

    在sql注入中,往往会用到截取字符串的问题,例如不回显的情况下进行的注入,也成为盲注,这种情况下往往需要一个一个字符的去猜解,过程中需要用到截取字符串.本文中主要列举三个函数和该函数注入过程中的一些用 ...

  10. JS 浮点数运算丢失精度解决方案

    除法 function accDiv(arg1,arg2){ var t1=0,t2=0,r1,r2; try{t1=arg1.toString().split(".")[1].l ...