从今天开始我们开始讲解EF中的实体状态和数据操作,这篇文章先讲解实体状态。

我们通过前面的学习,知道EF通过上下位负责跟踪实体的状态,实体状态的位置是在命名空间 System.Dat.Entity 里的 EntityState,具体状态有如下5种:

  1. Detached
  2. Unchanged
  3. Added
  4. Deleted
  5. Modified

下面我们分辨来讲解一下

零、Detached

有时候我们只需要实体显示,而不需要实体更新,为了提高性能,我们就就不需要EF上下文对实体进行跟踪,这个时候我们就用到了 Detached 状态。我们只需要在查询的时候使用 AsNoTracking() 来世的查询出来的对象是 Detached 状态。实例代码如下:

var person = db.Person.AsNoTracking().Where(p=>p.Id==1).FirstOrDefault();

注:因为 AsNoTracking 是DbQuery类的方法,因此要首先调用 AsNoTracking 方法。

一、Unchanged

在这个状态下实体被上下文追踪,但是数据库中的值没有发生任何改变。如果实体不存在于数据库,但是该实体要被上下文追踪,同时实体值未发生改变,这个时候就可以通过 Attach 进行附加追踪,然后将实体状态标记为 Unchanged 。 实例代码如下:

using (var db = new EFDbContext())
{
var user =new User()
{
Name = "张三",
Age = 12
}
db.User.Attach(user);
db.Entry(user).State = EntityState.Unchanged;
db.SaveChanges();
}

二、Added

当进行新增操作时就会用到 Added 状态。标记为 Added 状态时,表明尸体上下文被追踪但是不存在于数据库中,当我们调用 SaveChanges 方法时数据将保存进数据库。如果要将实体状态标记为该状态,可以使用两种方法:

  1. 间接标记,通过 Add 方法调用,示例代码如下:
using (var db = new EFDbContext())
{
var user = new User()
{
Name = "张三"
Age = 12
}
db.User.Add(user);
db.SaveChanges();
}
  1. 显式标记,通过调用 Entry 方法,示例代码如下:
using (var db = new EFDbContext())
{
var user = new User()
{
Name = "张三"
Age = 12
}
db.Entry(user).State = EntityState.Added;
db.SaveChanges();
}

三、Deleted

如果需要将实体从数据库中删除,可以使用 Deleted 状态,当调用 SaveChanges 方法时数据将会从数据库中删除。和 Added 状态一样,删除实体可以使用两种方法:

  1. 通过调用 Remove 或者是 RemoveRange 方法,示例代码如下:
using (var db = new EFDbContext())
{
var user = db.User..Where(p => p.Id == 1).FirstOrDefault();
db.User.Remove(user);
db.SaveChanges();
}

注: Remove 用于删除单个实体, RemoveRange 用于删除多个实体。

  1. 显式标记,通过调用 Entry 方法,示例代码如下:
using (var db = new EFDbContext())
{
var user = db.User..Where(p => p.Id == 1).FirstOrDefault();
db.Entry(user).State = EntityState.Deleted;
db.SaveChanges();
}

四、Modified

当我们修改数据时,需要用到 Modified 状态,当调用 SaveChanges 方法时数据将会修改数据库中的数据。在EF中修改数据,只有一种方法,通过调用 Entry 方法,示例代码如下:

using (var db = new EFDbContext())
{
var user = db.User..Where(p => p.Id == 1).FirstOrDefault();
db.Entry(user).State = EntityState.Modified;
db.SaveChanges();
}

五、特别提示

所有状态之间几乎都可以通过 Entry(T).State 的方式进行强制状态转换,因为状态改变都是依赖于 Id 的( Added 除外)。我们通过下图来了解一下上面五种状态的相互转换:

Entity Framework 实体状态的更多相关文章

  1. Entity Framework 实体框架的形成之旅--实体框架的开发的几个经验总结

    在前阵子,我对实体框架进行了一定的研究,然后把整个学习的过程开了一个系列,以逐步深入的方式解读实体框架的相关技术,期间每每碰到一些新的问题需要潜入研究.本文继续前面的主题介绍,着重从整体性的来总结一下 ...

  2. Entity FrameWork(实体框架)是以ADO.NET Entity FrameWork ,简称为EF

    Entity FrameWork(实体框架)是以ADO.NET Entity FrameWork ,简称为EF Entity FrameWork的特点 1.支持多种数据库(MSSQL.Oracle.M ...

  3. Entity Framework 实体框架的形成之旅--实体数据模型 (EDM)的处理(4)

    在前面几篇关于Entity Framework 实体框架的介绍里面,已经逐步对整个框架进行了一步步的演化,以期达到统一.高效.可重用性等目的,本文继续探讨基于泛型的仓储模式实体框架方面的改进优化,使我 ...

  4. Entity Framework 实体框架的形成之旅--为基础类库接口增加单元测试,对基类接口进行正确性校验(10)

    本篇介绍Entity Framework 实体框架的文章已经到了第十篇了,对实体框架的各个分层以及基类的封装管理,已经臻于完善,为了方便对基类接口的正确性校验,以及方便对以后完善或扩展接口进行回归测试 ...

  5. Entity Framework 实体框架的形成之旅--几种数据库操作的代码介绍(9)

    本篇主要对常规数据操作的处理和实体框架的处理代码进行对比,以便更容易学习理解实体框架里面,对各种数据库处理技巧,本篇介绍几种数据库操作的代码,包括写入中间表操作.联合中间表获取对象集合.递归操作.设置 ...

  6. Entity Framework 实体框架的形成之旅--界面操作的几个典型的处理(8)

    在上篇随笔<Entity Framework 实体框架的形成之旅--数据传输模型DTO和实体模型Entity的分离与联合>里面,介绍了在Entity Framework 实体框架里面引入了 ...

  7. Entity Framework 实体框架的形成之旅--数据传输模型DTO和实体模型Entity的分离与联合

    在使用Entity Framework 实体框架的时候,我们大多数时候操作的都是实体模型Entity,这个和数据库操作上下文结合,可以利用LINQ等各种方便手段,实现起来非常方便,一切看起来很美好.但 ...

  8. Entity Framework 实体框架的形成之旅--Code First模式中使用 Fluent API 配置(6)

    在前面的随笔<Entity Framework 实体框架的形成之旅--Code First的框架设计(5)>里介绍了基于Code First模式的实体框架的经验,这种方式自动处理出来的模式 ...

  9. Entity Framework 实体框架的形成之旅--Code First的框架设计(5)

    在前面几篇介绍了Entity Framework 实体框架的形成过程,整体框架主要是基于Database First的方式构建,也就是利用EDMX文件的映射关系,构建表与表之间的关系,这种模式弹性好, ...

随机推荐

  1. Lincode刷题No.8

    8.Rotate String lintcode 题解1: class Solution { public: /** * @param str: An array of char * @param o ...

  2. Netty快速入门(09)channel组件介绍

    书接上回,继续介绍组件. ChannelHandler组件介绍 ChannelHandler组件包含了业务处理核心逻辑,是由用户自定义的内容,开发人员百分之九十的代码都是ChannelHandler. ...

  3. 简单工厂模式(C++)

    #include <iostream> using namespace std; class Fruit { public : ; }; class Banana :public Frui ...

  4. 原生javascript实现仿QQ延时菜单

    一.实现原理 定时器和排他思想 二.代码 <!DOCTYPE html> <html> <head> <title></title> < ...

  5. MapGIS注记文字无损转入ArcGIS软件

    在GIS软件中,注释是一种十分特殊的对象,虽然各类软件都支持注释,但它却不属于GIS的基本对象.因此通常的格式转换软件,都不对注释对象做特别的支持,我们最常见的Shape文件格式就只有点.线.面要素, ...

  6. input 只允许输入小数

    oninput = "value=value.replace(/[^\d]/g,'')" 输入浮点数不好使 突发奇想自己写一个与众不同的... oninput="valu ...

  7. P2365 任务安排 batch 动态规划

    batch ★☆   输入文件:batch.in   输出文件:batch.out   简单对比时间限制:1 s   内存限制:128 MB 题目描述 N个任务排成一个序列在一台机器上等待完成(顺序不 ...

  8. 求二叉树的深度,从根节点到叶子节点的最大值,以及最大路径(python代码实现)

    首先定义一个节点类,包含三个成员变量,分别是节点值,左指针,右指针,如下代码所示: class Node(object): def __init__(self, value): self.value ...

  9. RabbitMQ入门(二)工作队列

      在文章RabbitMQ入门(一)之Hello World,我们编写程序通过指定的队列来发送和接受消息.在本文中,我们将会创建工作队列(Work Queue),通过多个workers来分配耗时任务. ...

  10. HashMap在JDK7和JDK8中的区别

    在[深入浅出集合Map]中,已讲述了HashMap在jdk7中实现,在此就不再细说了 JDK7中的HashMap 基于链表+数组实现,底层维护一个Entry数组 Entry<K,V>[]  ...