从4.1版本开始,EF开始支持Code First模式,值得注意的是Code First不是和DataBase First或Model First平级的概念,而是和EDM平级的概念。使用Code First不再需要EDM来维护实体与数据库之间的映射关系,这个映射完全通过代码来完成,并在程序开始运行时在内存中建立一个映射模型,这也就是Code First这个名称中Code的含义。 
随着Code First一起出现的是DbContext和DbSet类绝对可以称得上EF的核心功能,提供了与数据库通信,管理内存中实体的重要功能。

Entity Framework Profire

在正式介绍EF之前,首先介绍一款监听EF生成SQL语句文本的第三方软件Entity Framework Profire(收费版:但一个邮箱可试用一个月)。通过Entity Framework Profire,我们可以十分方便监听EF底层生成SQL语句的格式。 

安装之后,在Global.asax全局配置文件中添加初始化语句:

 App_Start.EntityFrameworkProfilerBootstrapper.PreStart();
  • 1

下面是使用EntityFrameworkProfiler监听到的SQL语句;

映射

通过Code First来实现实体映射模型有两种方式 Data Annnotation 和 Fluent API。 
Data Annotation需要在实体类的属性上以Attribute的方式表示主键、外键等映射信息。这种方式不符合解耦合的要求一般不建议使用 
第二种方式就是要重点介绍的Fluent API。Fluent API的配置方式将实体类与映射配置进行解耦合,有利于项目的扩展和维护。Fluent API方式中的核心对象是DbModelBuilder

重写DbContext的OnModelCreating(DbModelBuilder modelBuilder)方法,使用反射扫描程序集中所有继承自EntityTypeConfiguration<>的Map类,一次性添加到modelBuilder.Configurations集合中。

数据库上下文(继承自DbContext)

 public class EFDbContext : DbContext
{
public EFDbContext()
: base("DsUserCenterSQLConnection")
{ } public DbSet<Role> RoleList { get; set; } public DbSet<Menu> MenuList { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
var typesToRegister =Assembly.GetExecutingAssembly().GetTypes()
.Where(type => !String.IsNullOrEmpty(type.Namespace))
.Where(type => type.BaseType != null && type.BaseType.IsGenericType && type.BaseType.GetGenericTypeDefinition() == typeof(EntityTypeConfiguration<>));
foreach (var type in typesToRegister)
{
dynamic configurationInstance = Activator.CreateInstance(type);
modelBuilder.Configurations.Add(configurationInstance);
}
base.OnModelCreating(modelBuilder);
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

这样,OnModelCreating就大大简化,并且一劳永逸的是,以后添加新的实体映射只需要添加新的继承自EntityTypeConfiguration<>的XXXMap 类而不需要修改 OnModelCreating 方法。

1:1单向映射(OperaterInfo-DepartmentInfo) 
假设一个部门只有一个操作员,由于在数据库T_OperaterInfo表的字段DepartmentId并没有设置为外键,可将1:1通过1:N关联来实现

实体类OperaterInfo

 public class OperaterInfo
{
public int Id { get; set; } /// <summary>
/// 名字
/// </summary>
public string Name { get; set; } /// <summary>
/// 身份证号码
/// </summary>
public string IDCard { get; set; } /// <summary>
/// 手机号码
/// </summary>
public string Phone { get; set; } /// <summary>
/// 归属部门
/// </summary>
public int? DepartmentId { get; set; } /// <summary>
/// 导航属性-关联部门信息
/// </summary>
public virtual DepartmentInfo DepartmentInfo { get; set; }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

配置类OperaterInfoMap

 public class OperaterInfoMap : EntityTypeConfiguration<OperaterInfo>
{
public OperaterInfoMap()
{
ToTable("T_OperaterInfo");
HasKey(o => o.Id); HasOptional(o => o.DepartmentInfo).WithMany().HasForeignKey(s => s.DepartmentId);
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

实体类DepartmentInfo

 public class DepartmentInfo
{
public int Id { get; set; } /// <summary>
/// 部门名称
/// </summary>
public string DeptName { get; set; }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

配置类DepartmentInfoMap

  public class DepartmentInfoMap:EntityTypeConfiguration<DepartmentInfo>
{
public DepartmentInfoMap()
{
ToTable("T_DepartmentInfo");
HasKey(dept=>dept.Id);
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

控制台测试程序


class Program
{
static void Main(string[] args)
{
//初始化EntityFrameworkProfire
App_Start.EntityFrameworkProfilerBootstrapper.PreStart();
using (var dbContext = new EFDbContext())
{
//Include实现立即加载机制
var operaterList = dbContext.OperaterInfoList.Include("DepartmentInfo").ToList();
foreach (var opt in operaterList)
{
Console.WriteLine(string.Format("{0}:{1}",opt.Name,opt.DepartmentInfo.DeptName));
}
} Console.ReadLine();
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

执行结果

Profile监听到的结果就是上面的示例结果

然后我们修改上面的测试程序,将 Include(“DepartmentInfo”) 去掉,可发现控制台的执行结果并没有改变.

//Include实现立即加载机制
//var operaterList = dbContext.OperaterInfoList.Include("DepartmentInfo").ToList();
var operaterList = dbContext.OperaterInfoList.ToList();
  • 1
  • 2
  • 3

查看Profile的监听结果如下: 

EF框架:延迟加载与立即加载 
注意到 OperatorInfo 类中有一个导航属性DepartmentInfo(使用 virtual 修饰符修饰)

/// <summary>
/// 导航属性-关联部门信息
/// </summary>
public virtual DepartmentInfo DepartmentInfo { get; set; }
  • 1
  • 2
  • 3
  • 4

延迟加载可以理解为按需加载,EF并不会立即执行SQL加载数据,只有在执行ToList()、FirstOrDefault()方法时才会去查询数据库加载数据,但是延迟加载更多情况下是针对实体之间的关联属性(导航属性)。 
如上例:当我们去查询OperatorInfo的时候,EF默认不会关联查询导航属性DepartmentInfo信息;只有在我们需要DepartmentInfo时才会去查询数据库找出对应的DepartmentInfo。这时就会产生数据库查询的“N+1”问题,如此频繁的查询数据库将会导致数据库压力激增,对于服务器内存的消耗十分可怕,影响程序的响应速度。 
EF也允许我们通过编程的方式(.Include(“DepartmentInfo”))显式指定立即加载,在查询OperatorInfo时通过关联查询同时加载出DepartmentInfo。 
在具体的编程环境中,我们要根据实际情况去决定使用“延迟加载”或“立即加载”,这对于EF框架的查询优化十分有必要。

http://blog.csdn.net/u012578792/article/details/53374816

Entity Framework 6 Code First系列1: 实体类1:1配置的更多相关文章

  1. Entity Framework 6 Code First 系列:无需修改实体和配置-在MySql中使用和SqlServer一致的并发控制

    无需修改实体和配置,在MySql中使用和SqlServer一致的并发控制.修改RowVersion类型不可取,修改为Timestamp更不可行.Sql Server的RowVersion生成一串唯一的 ...

  2. 【极力分享】[C#/.NET]Entity Framework(EF) Code First 多对多关系的实体增,删,改,查操作全程详细示例【转载自https://segmentfault.com/a/1190000004152660】

      [C#/.NET]Entity Framework(EF) Code First 多对多关系的实体增,删,改,查操作全程详细示例 本文我们来学习一下在Entity Framework中使用Cont ...

  3. [C#/.NET]Entity Framework(EF) Code First 多对多关系的实体增,删,改,查操作全程详细示例

    本文我们来学习一下在Entity Framework中使用Context删除多对多关系的实体是如何来实现的.我们将以一个具体的控制台小实例来了解和学习整个实现Entity Framework 多对多关 ...

  4. EF(Entity Framework)系统学习系列

    好久没写博客了,继续开启霸屏模式,好了,废话不多说,这次准备重新系统学一下EF,一个偶然的机会找到了一个学习EF的网站(http://www.entityframeworktutorial.net/) ...

  5. Entity Framework 6.0 入门系列 第一篇

    Entity Framework 6.0 入门系列 第一篇 好几年前接触过一些ef感觉不是很好用,废弃.但是 Entity Framework 6.0是经过几个版本优化过的产物,性能和功能不断完善,开 ...

  6. Entity Framework 6 Code First新特性:支持存储过程

    Entity Framework 6提供支持存储过程的新特性,本文具体演示Entity Framework 6 Code First的存储过程操作. Code First的插入/修改/删除存储过程 默 ...

  7. AppBox升级进行时 - 拥抱Entity Framework的Code First开发模式

    AppBox 是基于 FineUI 的通用权限管理框架,包括用户管理.职称管理.部门管理.角色管理.角色权限管理等模块. 从Subsonic到Entity Framework Subsonic最早发布 ...

  8. Entity Framework 6.1 学习系列1--概况、安装

    原文:Entity Framework 6.1 学习系列1--概况.安装 Entity Framework:实体框架,看名字就知道是针对模型数据的.这是MS推出的一款ORM工具. 与NHibernat ...

  9. Entity Framework 之 Code First

    使用NuGet助您玩转代码生成数据————Entity Framework 之 Code First [前言] 如果是Code First老鸟或者对Entity Framework不感兴趣,就不用浪费 ...

随机推荐

  1. jenkins之Tomcat7+jdk1.7+jenkins

    目的 在开发中,需要经常频繁的对测试服务器进行部署,而且在多人协同中开发经常遇到的问题就是别人更新了他的代码,而你去更新你的代码时并没有更新到别人的代码,导致测试环境的代码不是最新,当然这个问题也好解 ...

  2. 简单介绍一下solr?

    简单介绍一下solr? Solr是一个独立的企业级搜索应用服务器,它对外提供类似于web-service的API接口.用户可以通过http请求,向搜索引擎服务器提交一定格式的XML文件,生成索引:也可 ...

  3. 【极角排序+双指针线性扫】2017多校训练七 HDU 6127 Hard challenge

    acm.hdu.edu.cn/showproblem.php?pid=6127 [题意] 给定平面直角坐标系中的n个点,这n个点每个点都有一个点权 这n个点两两可以连乘一条线段,定义每条线段的权值为线 ...

  4. Linux c内存泄漏检测

    在Linux下些C语言程序,最大的问题就是没有一个好的编程IDE,当然想kdevelop等工具都相当的强大,但我还是习惯使用kdevelop工具,由于没有一个习惯的编程IDE,内存检测也就成了在Lin ...

  5. PHP html_entity_decode() 函数

    html_entity_decode(string,flags,character-set) 把 HTML 实体转换为字符. html_entity_decode() 函数是 htmlentities ...

  6. Maven实战:Pom.xml详解

    什么是pom?    pom作为项目对象模型.通过xml表示maven项目,使用pom.xml来实现.主要描述了项目:包括配置文件:开发者需要遵循的规则,缺陷管理系统,组织和licenses,项目的u ...

  7. Docker如何部署Python项目

    Docker 部署Python项目 作者:白宁超 2019年5月24日09:09:00 导读: 软件开发最大的麻烦事之一就是环境配置,操作系统设置,各种库和组件的安装.只有它们都正确,软件才能运行.如 ...

  8. vue之列表渲染

    一.v-for循环用于数组 v-for 指令根据一组数组的选项列表进行渲染. 1.v-for 指令需要使用 item in items 形式的特殊语法,items 是源数据数组名, item 是数组元 ...

  9. 数据库设计三范式(3NF)

    问:当时你数据库是如何设计的? 答:当时是按照三范式规范设计的: 第一范式: 1:数据库的原子性,即保证数据库表的每一列都不可分割的 第二范式: 1:原子性,即保证数据库表的每一列都不可分割 2:表中 ...

  10. java集合系列之LinkedList源码分析

    java集合系列之LinkedList源码分析 LinkedList数据结构简介 LinkedList底层是通过双端双向链表实现的,其基本数据结构如下,每一个节点类为Node对象,每个Node节点包含 ...