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 , 它们都是 ...
随机推荐
- 使用Eclipse创建Maven的JSP项目
使用Eclipse创建Maven的JSP项目 MyEclipse2015根本不行,试过各种解决方案都无济于事. 创建Maven项目 此时项目上有错,pom.xml有错. 修改Java版本 生成web. ...
- websocket服务端开发
基于http请求以拉的方式去做服务器的推送,无论是实时性和有效字节都是差强人意的效果. 公司的im系统在与客户端的交互上实际上借助了websocket来实现服务器与客户端的事实消息推送,今天就来简单了 ...
- 区块链V1版本实现之五
代码重构: block.go文件: package main import ( "crypto/sha256" ) //定义区块结构 type Block struct { //前 ...
- webgl智慧楼宇发光效果算法系列之高斯模糊
webgl智慧楼宇发光效果算法系列之高斯模糊 如果使用过PS之类的图像处理软件,相信对于模糊滤镜不会陌生,图像处理软件提供了众多的模糊算法.高斯模糊是其中的一种. 在我们的智慧楼宇的项目中,要求对楼宇 ...
- Java动态代理设计模式
本文主要介绍Java中两种常见的动态代理方式:JDK原生动态代理和CGLIB动态代理. 什么是代理模式 就是为其他对象提供一种代理以控制对这个对象的访问.代理可以在不改动目标对象的基础上,增加其他额外 ...
- 牛客巅峰赛S2第6场题解
牛客编程巅峰赛S2第6场 A-StringⅡ 题目 题目描述 给出一个仅包含小写字母的字符串s,你最多可以操作k次,使得任意一个小写字母变为与其相邻的小写字母(ASCII码差值的绝对值为1),请你求出 ...
- 【系统设计】不同分类的商品动态添加扩展属性的方法(WMS、小型电商)
在做公司WMS系统的时候,遇到了一个商品模块的设计问题,具体业务流程如下. 客户提供需要存放的商品清单,根据商品清单生成收货单给客户,然后生成入库单进行商品入库操作. 在生成这两个单之前首先要录入商品 ...
- PHP代码审计分段讲解(1)
PHP源码来自:https://github.com/bowu678/php_bugs 快乐的暑期学习生活+1 01 extract变量覆盖 <?php $flag='xxx'; extract ...
- 解析php sprintf函数漏洞
php sprintf函数漏洞 0x01 了解sprintf()函数 1,sprintf(),函数是php中的函数 2,作用是将格式化字符串写入变量中 3,函数形式为sprintf(format,ar ...
- 你必须掌握的关于JVM知识点
对本文所持态度 抓住主要矛盾,抓住重点学习,然后从这些点展开学. 不管是面试别人,还是参加面试.都可以有收获. JDK体系结构与JVM架构解析 jdk jre javac jvm Java是怎么实现跨 ...