一. 简介

  我们在前面章节介绍EF基本增删改的时候,曾说过EF的SaveChanges()方法,会一次性的将所有的实体的状态变化统一提交到数据库,那么你是否想过EF的实体会有哪些状态变化呢?什么原因会导致其变化呢?我们怎么来追踪EF的实体变化呢?本章节以追踪EF实体状态变化的三种方式为线索,一一介绍上面疑问。

  废不多说,还是先把整理的结论贴出来,然后配合代码来介绍。

1. EF的实体状态总共有5种:Added、Deleted、Modified、Detached、unChanged

   ①. unChanged:属性值与数据库中属性值相同,没有发生任何变化,首次查询出来的实体的状态值为unChanged

  ②. Modified:实体中的某些属性的值或所有属性值与数据库中的发生了变化

    A:从数据库中查询出来的实体,直接改实体属性的值, 可以将实体状态改为 Modified。

    B:自己创建的实体,必须先Attach一下,直接改实体属性的值,才可以将实体状态改为 Modified。

  ③. Added: 实体将由上下文跟踪,但是在数据库中还不存在,

    Add()和 AddRange方法可以将实体状态变为:Added

  ④. Deleted:实体将由上下文跟踪并存在于数据库中,但是已被标记为在下次调用 SaveChanges 时从数据库中删除。

     A:从数据库中查询出来的实体,通过Remove方法, 可以将实体状态改为 Deleted。

     B:自己创建的实体,必须先Attach一下,然后Remove方法,才可以将实体状态改为 Deleted。

  ⑤. Detached: 调用AsNoTracking方法,取消实体状态追踪

2. 追踪方法一:DbEntityEntry 追踪单个实体的状态

   ①. db.Entry(XXX).State 来获取实体的状态

   ②. db.Entry(XXX).OriginalValues["txt1"] 可以获取属性的原始值

    ③. db.Entry(XXX).CurrentValues["txt1"] 可以获取属性的现在值

3. 追踪方法二:ChangeTracker 追踪EF上下文中所有实体的状态

  ①. db.ChangeTracker.Entries() 获取所有的实体状态变化 获取的是一个 IEnumerable<DbEntityEntry> 集合,遍历可以获取每个实体的状态变化

4. 追踪方法三:Local 获取单个实体状态发生增加、修改的实体集合(不含删除)

①. db.XXX.Local 获取的是XXX实体的集合

5. 删除状态和附加状态: AsNoTracking 和 Attach

二. 代码测试

1. 追踪方法一:DbEntityEntry  追踪单个实体的状态

 1        {2                     Console.WriteLine("-------------------追踪方法一:DbEntityEntry  追踪单个实体的状态--------------------------");3                     //修改前4                     var data1 = db.TestInfor.FirstOrDefault();5                     DbEntityEntry stata1 = db.Entry(data1);6                     Console.WriteLine("实体状态为:" + stata1.State);7                     //修改后8                     data1.txt1 = "fk";9                     DbEntityEntry stata2 = db.Entry(data1);
10                     Console.WriteLine("实体状态为:" + stata2.State);
11                     Console.WriteLine("txt1的原始值为" + stata2.OriginalValues["txt1"]);
12                     Console.WriteLine("txt1的现在值为" + stata2.CurrentValues["txt1"]);
13          }

 分析:修改后实体状态由Unchanged→Modified了。

2. 追踪方法二:ChangeTracker  追踪EF上下文中所有实体的状态

 1  {2                     Console.WriteLine("-------------------追踪方法二:ChangeTracker  追踪EF上下文中所有实体的状态--------------------------");3                     //1.增加操作4                     db.TestInfor.Add(new TestInfor()5                     {6                         id = Guid.NewGuid().ToString("N"),7                         txt1 = "1",8                         txt2 = "2"9                     });
10
11                     //2. 删除操作
12                     var data = db.TestInfor.FirstOrDefault();
13                     db.TestInfor.Remove(data);
14
15                     //3. 修改操作
16                     var data2 = db.TestInfor.Where(u => u.id == "123").FirstOrDefault();
17                     data2.txt2 = "mr123";
18
19                     //4. 另外一个实体的增加操作
20                     db.TestInfor2.Add(new TestInfor2()
21                     {
22                         txt11 = "1",
23                         txt22 = "2"
24                     });
25
26                     List<DbEntityEntry> entityList = db.ChangeTracker.Entries().ToList();
27                     foreach (var item in entityList)
28                     {
29                         Console.WriteLine("实体状态为:" + item.State);
30                     }
31
32 }

3. 追踪方法三:Local 获取单个实体状态发生增加、修改的实体集合(不含删除)

 1                 {2                     Console.WriteLine("-------------------追踪方法三:Local 获取单个实体状态发生增加、修改的实体集合(不含删除)--------------------------");3                     //1.增加操作4                     db.TestInfor.Add(new TestInfor()5                     {6                         id = Guid.NewGuid().ToString("N"),7                         txt1 = "1",8                         txt2 = "2"9                     });
10
11                     //2. 删除操作
12                     var data = db.TestInfor.FirstOrDefault();
13                     db.TestInfor.Remove(data);
14
15                     //3. 修改操作
16                     var data2 = db.TestInfor.Where(u => u.id == "123").FirstOrDefault();
17                     data2.txt2 = "mr123";
18
19                     //4. 另外一个实体的增加操作
20                     db.TestInfor2.Add(new TestInfor2()
21                     {
22                         txt11 = "1",
23                         txt22 = "2"
24                     });
25
26                     var EntityList = db.TestInfor.Local;
27
28                     foreach (var item in EntityList)
29                     {
30                         Console.WriteLine("实体的值分别为:{0},{1},{2}", item.id, item.txt1, item.txt2);
31                     }
32
33                 }

 分析:这里的Local获取的是单个DBSet,发生了增加或修改操作,最终的获取的是实体集合。

4. 删除状态追踪和附加状态追踪(AsNoTracking 和 Attach)

 1                 {2                     Console.WriteLine("-------------------删除状态和附加状态(AsNoTracking 和 Attach) --------------------------");3 4                     //以修改为例测试状态5                     {6                         //1. 带状态追踪7                         var item = db.TestInfor.FirstOrDefault();8                         item.txt2 = "mr333+" + Guid.NewGuid().ToString("N").Substring(7);9                         Console.WriteLine("实体的状态为:" + db.Entry(item).State);
10                         int n = db.SaveChanges();
11                         if (n > 0)
12                         {
13                             Console.WriteLine("修改成功");
14                         }
15                         else
16                         {
17                             Console.WriteLine("没有相应的实体需要修改");
18                         }
19                     }
20                     {
21                         //2. 取消状态追踪
22                         var item = db.TestInfor.AsNoTracking().FirstOrDefault();
23                         item.txt2 = "mr333+" + Guid.NewGuid().ToString("N").Substring(10);
24                         Console.WriteLine("实体的状态为:" + db.Entry(item).State);
25                         int n = db.SaveChanges();
26                         if (n > 0)
27                         {
28                             Console.WriteLine("修改成功");
29                         }
30                         else
31                         {
32                             Console.WriteLine("没有相应的实体需要修改");
33                         }
34                     }
35                     {
36                         //3. 自己创建实体进行修改
37                         TestInfor item = new TestInfor()
38                         {
39                             id = "123"
40                         };
41                         db.TestInfor.Attach(item);
42                         item.txt1 = "fk3456";
43                         Console.WriteLine("实体的状态为:" + db.Entry(item).State);
44                         int n = db.SaveChanges();
45                         if (n > 0)
46                         {
47                             Console.WriteLine("修改成功");
48                         }
49                         else
50                         {
51                             Console.WriteLine("没有相应的实体需要修改");
52                         }
53                     }
54                 }

第十节: EF的三种追踪实体状态变化方式(DBEntityEntry、ChangeTracker、Local)相关推荐

  1. 第十四节: EF的三种模式(四) 之 原生正宗的 CodeFirst模式的默认约定

    一. 简介 1. 正宗的CodeFirst模式是不含有edmx模型,需要手动创建实体.创建EF上下文,然后生成通过代码来自动映射生成数据库. 2. 旨在:忘记SQL.忘记数据库. 3. 三类配置:On ...

  2. 第七节: EF的三种事务的应用场景和各自注意的问题(SaveChanges、DBContextTransaction、TransactionScope)

    一. 什么是事务 我们通俗的理解事务就是一系列操作要么全部成功.要么全部失败(不可能存在部分成功,部分失败的情况). 举一个事务在我们日常生活中的经典例子:两张银行卡(甲.乙),甲向乙转钱,整个过程需 ...

  3. 第十一节: EF的三种模式(一) 之 DBFirst模式(SQLServer和MySQL两套方案)

    一. 简介 EF连接数据库有三种模式,分别是DBFirst.ModelFirst.CodeFirst,分别适用于不同的开发场景. 该章节,将主要介绍EF的DBFirst连接SQLServer数据库和M ...

  4. 第十三节: EF的三种模式(三) 之 来自数据库的CodeFirst模式

    一. 简介 [来自数据库的Code First模式]实质上并不是CodeFirst模式,而是DBFirst模式的轻量级版本,在该模式中取消了edmx模型和T4模板,直接生成了EF上下文和相应的类,该模 ...

  5. SSO单点登录三种情况的实现方式详解

    SSO单点登录三种情况的实现方式详解 单点登录(SSO--Single Sign On)对于我们来说已经不陌生了.对于大型系统来说使用单点登录可以减少用户很多的麻烦.就拿百度来说吧,百度下面有很多的子 ...

  6. zynq学习03 zynq中三种实现GPIO的方式

    http://m.blog.csdn.net/article/details?id=52123465 http://blog.chinaaet.com/songhuangong/p/43084 本文介 ...

  7. Objective-C:三种文件导入的方式以及atomic和nonatomic的区别

    一.三种文件导入的方式比较:   类的前项声明@class.import.include: 1.采用@class 类名的方式,它会告诉编译器有这么一个类,目前不需要知道它内部的实例变量和方法是如何定义 ...

  8. 浅淡Webservice、WSDL三种服务访问的方式(附案例)

    Webservice Webservice是使应用程序以与平台和编程语言无关的方式进行相互通信技术. eg:站点提供访问的数据接口:新浪微博.淘宝. 官方解释:它是一种构建应用程序的普遍模型,可以在任 ...

  9. Python中的urllib,urllib三种不同的请求方式

    1.urllib获取服务器的资源 自定义爬虫的重要组件 获取百度首页的资源: #3.x的标准写法 import urllib.request import urllib.parse#百度的首页 fro ...

最新文章

  1. Tomcat中配置MySQL数据库连接池
  2. 实践自定义UI—RLF...(RelativeLayout LinearLayout FrameLayout....)
  3. 区块链BaaS云服务(8)京东 智臻链
  4. Vue—上手实践—快速入门
  5. java-接口与多态-
  6. rabbitmq-路由模式-routingkey
  7. ICCV2021 人脸深伪分析挑战赛 重磅来袭
  8. 软考信息系统项目管理师_管理科学(运筹学)2---软考高级之信息系统项目管理师034
  9. [转]Kali-linux安装之后的简单设置
  10. mysql返回上一层_mysql常用命令大全
  11. stm8L 触摸库使用教程 一步一步
  12. 调通sina33下的AP6212A0(WIFI+BT)V1.2
  13. 多模态交互在,数智化营销服中的技术实践
  14. Python 具名元组
  15. 自媒体免费编辑工具竞品分析 135编辑器乐观号媒号通三大功能优劣报告
  16. tensorboard使用界面介绍以及使用方法(看这篇就够了,都有源码可以直接测试)
  17. OD破解软件找断点方法系列【2】----万能断点法(XP系统)
  18. EXT4分区工具MiniTool Partition Wizard Home Edition
  19. 电脑计算机桌面什么安装,一般的软件是怎样安装到电脑桌面上的?
  20. Oracle安装时物理内存检查失败的解决方案:

热门文章

  1. python之各种装饰器的使用
  2. [NOIP2010提高组]关押罪犯
  3. 使用MvcContrib的FormHelper
  4. [剑指offer]面试题第[1]题[JAVA][二维数组中的查找][数组][二分]
  5. 南师大632c语言程序设计,单片机c语言学习心得632.docx
  6. md5与des算法有何不同_到底AI芯片和传统芯片有何区别?
  7. 包装类java_Java 包装类
  8. 1461B. Find the Spruce
  9. android 画布心形,Android CustomShapeImageView对图片进行各种样式裁剪:圆形、星形、心形、花瓣形等...
  10. ccs6 linux安装教程,【图片】【吧主帖】在LINUX(ubuntu)系统下装CCSv6方法(原创)【dsp吧】_百度贴吧...