EF快速入门--直接修改(简要介绍ObjectContext处理机制)
原博文
http://www.cnblogs.com/fly_dragon/archive/2011/06/05/2073084.html
ObjectContext的处理机制
ObjectContext是Entity Framework封装了数据库访问的上下文,以及实体的映射关系元数据信息等。
EF帮我们封装好了这么一个统一的接口。让我们所有的操作都只通过这个一个实体上下文就可以实现了增删查改等所有对应数据库的操作。
当然,我们要了解EF的生成SQL的机制我们才能更好的使用EF帮我们生成效率更高的SQL脚本。
看一个实例:下图所示项目截图与实体模型图(一个简单的例子)
static void Main(string[] args)
{
SchoolDBEntities schoolDB = new SchoolDBEntities();
Student student = new Student();
student.Address = "北京上地";
student.Name = "飞龙";
student.Phone = "110";
schoolDB.Student.AddObject(student);
schoolDB.SaveChanges();
}
就是简单的网数据库中添加一条数据。
我们在上面代码红色背景地方加上断点【schoolDB是EF自动帮我们生成的继承自ObjectContext的上下文】并对schoolDB进行快速监视。
截图如下:

由于图篇幅有限,只截取了部分视图。在此我就简单介绍一下几个比较关键的属性。
(1):Connection,相信大家一下子就能猜到,当然它封装了EF连接数据库的XxxConnection(如:SqlConnection)。这个就不啰嗦了。
(2):ObjectStateManage,它职责是维护实体类型实例和关系实例的对象状态和标识管理。也是EF上下文中非常重要的一个属性。它帮我们把添加的实体放到添加队列里,把修改的实体放到修改的队列里,当然还有删除等的。每个实体做了修改时,EF帮我们把实体放到相应的队列中并修改相应的实体的状态(EntityState),当调用ObjectContext的SaveChanges()方法时,EF根据队列的情况以及EDMX元数据映射的信息生成最终的SQL脚本。
(3):上图中我们看到_addedEntityStore就是我们刚才所说的添加实体的一个集合,而且这里面的每个实体对应的EntityState(标志实体在内存中的状态,是个Enum类型)都是Added状态,当然这表示添加,最终生成SQL时是Insert Into... 当然还有删除的队列、修改的队列这个大家自己看一下就可以了。
(4):EntityState,实体对象的状态。标志我们开发人员对实体的相应的操作,如下表格是实体的相关状态以及说明(摘自MSDN)
| 成员名称 | 说明 |
|---|---|
| Detached | 对象存在,但没有被跟踪。 在创建实体之后、但将其添加到对象上下文之前,该实体处于此状态。 An entity is also in this state after it has been removed from the context by calling the Detach method or if it is loaded by using a NoTrackingMergeOption. 没有 ObjectStateEntry 实例与状态为 Detached 的对象关联。 |
| Unchanged | 自对象附加到上下文中后,或自上次调用 SaveChanges 方法后,此对象尚未经过修改。 |
| Added | 对象为新对象,并且已添加到对象上下文,但尚未调用 SaveChanges 方法。 在保存更改后,对象状态将更改为 Unchanged。 状态为 Added 的对象在 ObjectStateEntry 中没有原始值。 |
| Deleted | 对象已从对象上下文中删除。 在保存更改后,对象状态将更改为 Detached。 |
| Modified | 对象上的一个标量属性已更改,但尚未调用 SaveChanges 方法。 在不带更改跟踪代理的 POCO 实体中,调用 DetectChanges 方法时,已修改属性的状态将更改为 Modified。 在保存更改后,对象状态将更改为 Unchanged。 |
注:
对象上下文必须知道对象状态才能将更改保存回数据源。 ObjectStateEntry 对象存储 EntityState 信息。 ObjectContext 的 SaveChanges 方法根据每个对象的 EntityState 处理附加到上下文的实体和更新数据源。 有关更多信息,请参见Adding, Modifying, and Deleting Objects。
对象上下文中的对象状态由 ObjectStateManager 管理。 若要查找对象的状态,请调用以下 ObjectStateManager 方法之一:TryGetObjectStateEntry、GetObjectStateEntry 或GetObjectStateEntries。 ObjectStateEntry 的 State 属性定义该对象的状态。
总结:
EF是通过针对开发人员对实体做的修改,直接维护ObjectContext的实例中的实体操作集合并对单个实体对应的状态进行修改。最终根据此集合以及状态再加上表实体映射的元数据信息生成最终的SQL脚本。所以,我们在对应多个ObjectContext实例进行操作时要注意,调用实例自己的SaveChanges()方法时,它只会对自己实例内存空间的操作映射回数据库,而其他ObjectContext实例中的实体集合的修改都不受影响。而且EF自动帮我们做了缓存的处理,当我们第一次查询某个实体时它会自动帮我们从数据库取出数据,并装配成实体类交给我们开发人员,当第二次获取相同数据时,它会先从缓存中查找,如果已经存在数据了就立即返回,不会查询数据库。这就造成了一个问题,当ObjectContext实例如果一直不被销毁,那它的缓存会一直膨胀下去,所以在开发应用时,用单例直接处理EF的上下文也不是很合适。最好的方式应该是 在一次处理请求中(web开发)使用同一个ObjectContext实例即可,避免了多个上下文实例的维护,而且也不至于上下文实例日益膨胀。
EF实体中的修改
说到现在才进入正题,那我们怎么来进行修改呢?
不推荐方式一:
思路:先从ObjectContext取出实体,然后将前台传过来的DTO属性对应赋值到我们的实体上,然后调用ObjectContext的保证修改方法。
但是这种方式是最不提倡的,因为这样每次修改前都得先将数据查出来,经过SqlProfiler追踪,这么一个操作要对数据库进行两次的连接。这是不可忍受的!
推荐方式二:
思路:无需先查出实体,因为我们知道EF通过ObjectStateManage来控制添加、修改、删除队列以及实体的状态,我们所有可以通过在直接将DTO转化成实体,然后将实体对应的队列中,并且我们手动的将实体的状态处理好,再调用ObjectContext的保证修改方法,这样就避免了先查询后修改,两次数据库连接的问题了。实例代码如下:
static void Main(string[] args)
{
SchoolDBEntities schoolDB = new SchoolDBEntities();
//假设:网络传一个StudentDTO过来 ,将此DTO转化成 数据库实体
Student student = new Student();
student.Id = 1; // 假设DTO传过来的值,主键必须存在,不然会报错的
student.Address = "北京上地1";
student.Name = "飞龙1";
student.Phone = "1101";
//先将实体附加到实体上下文中
schoolDB.Student.Attach(student);
//手动修改实体的状态
schoolDB.ObjectStateManager.ChangeObjectState(student, EntityState.Modified);
//保存回数据库
schoolDB.SaveChanges();
}
总算把这块描述完了!希望对初学者有用!欢迎高手指正错误!
EF快速入门--直接修改(简要介绍ObjectContext处理机制)的更多相关文章
- Entity Framework快速入门--直接修改(简要介绍ObjectContext处理机制)
在介绍Entity Framework的修改实体到数据库的方法之前呢,我们先简要的介绍一下ObjectContext的处理机制. 1.ObjectContext的处理机制 ObjectContext是 ...
- 【个人笔记】002-PHP基础-01-PHP快速入门-02-PHP语言相关介绍输
002-PHP基础-01-PHP快速入门 02-PHP语言相关介绍 1.PHP是什么 Hypertext Preprocessor超文本预处理器 是一种通用开源脚本语言 Personal Home P ...
- JBPM4入门——1.jbpm简要介绍
本博文只是简要对JBPM4进行介绍,如需更详细内容请自行google 链接: JBPM入门系列文章: JBPM4入门——1.jbpm简要介绍 JBPM4入门——2.在eclipse中安装绘制jbpm流 ...
- AngularJS快速入门指南02:介绍
AngularJS是一个JavaScript框架.它可以通过<script>标记被添加到HTML页面中. AngularJS通过指令对HTML属性进行了扩展,然后通过表达式将数据绑定到HT ...
- SD卡中FAT32文件格式快速入门(图文详细介绍)【转】
本文转自:http://blog.csdn.net/mjx91282041/article/details/8904705 说明: MBR :Master Boot Record ( 主引导记录) D ...
- SD卡中FAT32文件格式快速入门(图文详细介绍)
说明: MBR :Master Boot Record ( 主引导记录) DBR :DOS Boot Record ( 引导扇区) FAT :File Allocation Table ( 文件分配表 ...
- WPF快速入门系列(3)——深入解析WPF事件机制
一.引言 WPF除了创建了一个新的依赖属性系统之外,还用更高级的路由事件功能替换了普通的.NET事件. 路由事件是具有更强传播能力的事件——它可以在元素树上向上冒泡和向下隧道传播,并且沿着传播路径被事 ...
- go语言快速入门教程
go快速入门指南 by 小强,2019-06-13 go语言是目前非常火热的语言,广泛应用于服务器端,云计算,kubernetes容器编排等领域.它是一种开源的编译型程序设计语言,支持并发.垃圾回收机 ...
- ElasticSearch实战系列六: Logstash快速入门和实战
前言 本文主要介绍的是ELK日志系统中的Logstash快速入门和实战 ELK介绍 ELK是三个开源软件的缩写,分别表示:Elasticsearch , Logstash, Kibana , 它们都是 ...
随机推荐
- Java基础教程——抽象类
抽象类 抽象类是介于普通类(class)和接口(interface)之间的一种特殊类. 接口的方法都不实现,类的方法都必须实现,抽象类里的方法可以实现,可以不实现. Java 8之后接口中可以实现方法 ...
- framework中的sentinel
引入切面: 切面+sentinel-web-servlet private void initDataSource() { String zkUrl = zaSentinelConfig.getDat ...
- vue微博回调空页面
1.vue微博回调空页面 注:微博回调空页面为:http://127.0.0.1:8888/oauth/callback/ 1.1 页面路径 components\oauth.vue <temp ...
- 2、Spring Cloud和dubbo简介
1.Spring Cloud简介 (1).Spring Cloud简介 SpringCloud,基于SpringBoot提供了一套微服务解决方案,包括服务注册与发现,配置中心,全链路监控,服务网关,负 ...
- Docker中搭建FastDFS文件系统(多图)
关于FastDFS FastDFS 是以 C 语言开发的一项开源轻量级分布式文件系统,他对文件进行管理,主要功能有:文件存储,文件同步,文件访问(文件上传/下载)等,特别适合以文件为载体的在线服务,如 ...
- PyQt(Python+Qt)学习随笔:Qt Designer中部件的 baseSize和sizeIncrement
1.baseSize 部件的 baseSize是部件的基础大小(单位:像素),如果部件设定了sizeIncrement,该属性用于在调整部件尺寸时计算部件应该调整到的合适值,但这个属性缺省值是QSiz ...
- 第15.13节 PyQt(Python+Qt)入门学习:Qt Designer的Spacers部件详解
一. 引言 在Designer的部件栏中,有两种类型的Spacers部件,下图中上面布局中为一个水平间隔部件(按钮1和按钮2之间的部件),下面布局中为一个垂直间隔部件(按钮3和4之间),如图: 这两种 ...
- 凌乱的与ctf无关的小知识点
(1)在网页中一般不要用记住密码.否则想要知道你的密码很简单. 例子:看样子很安全,别人无法通过这些来获得你的其他密码(尤其是想我这样密码强度不高的人),但是知道要修改前端的选项,你的密码就会被暴露. ...
- 【聊技术】在Android中实现自适应文本大小显示
本周的聊技术话题和大家说说如何在Android中实现自适应文本大小显示. 想象一下,在布局中,通常显示文本的区域大小是固定的,但是文本长度并不总是固定的.比如列表中的文章标题.界面下方的按钮文本等等. ...
- Nginx 转发时的一个坑,运维居然让我背锅!!
最近遇到一个 Nginx 转发的坑,一个请求转发到 Tomcat 时发现有几个 http header 始终获取不到,导致线上出现 bug,运维说不是他的问题,这个锅我背了. 新增的几个 header ...