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

一. 简介

   我们在前面章节介绍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                 }

复制代码

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/438517.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

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

一. 简介 EF连接数据库有三种模式&#xff0c;分别是DBFirst、ModelFirst、CodeFirst&#xff0c;分别适用于不同的开发场景。 该章节&#xff0c;将主要介绍EF的DBFirst连接SQLServer数据库和MySql数据库两种操作方式 该模式在EF中出现的出现的最早&#xff0c;符合我们的传统…

linux禁止u盘自动运行,求设置U盘自动运行和禁止运行的方法。

方法一&#xff1a;这种方法比较简单&#xff0c;就是用户在放入U盘同时&#xff0c;按住Shift键直至U盘的指示灯熄灭&#xff0c;然后松开Shift键即可。这种方法是一种临时应急法&#xff0c;如果拥护之是偶尔项禁止自动播放功能&#xff0c;这种方法比较合适。方法二&#xf…

第十二节: EF的三种模式(二) 之 ModelFirst模式(SQLServer为例)

一. 简介 顾名思义&#xff0c;ModelFirst是模型优先&#xff0c;是DBFirst的逆向模式&#xff0c;先建立实体数据模型&#xff0c;然后根据实体数据模型来生成数据库&#xff0c;从而驱动整个开发流程.&#xff08;生成一个空的edmx文件&#xff0c;手动在里面建立实体模型&am…

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

一. 简介 【来自数据库的Code First模式】实质上并不是CodeFirst模式&#xff0c;而是DBFirst模式的轻量级版本&#xff0c;在该模式中取消了edmx模型和T4模板&#xff0c;直接生成了EF上下文和相应的类&#xff0c;该模式出现在VS2015版本以后。 该模式也是适用于数据库已经设…

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

一. 简介 1. 正宗的CodeFirst模式是不含有edmx模型&#xff0c;需要手动创建实体、创建EF上下文&#xff0c;然后生成通过代码来自动映射生成数据库。 2. 旨在&#xff1a;忘记SQL、忘记数据库。 3. 三类配置&#xff1a;One To One(one-to-zero-or-one)、One To Many、Many To…

第十五节: EF的CodeFirst模式通过DataAnnotations修改默认协定

一. 简介 1. DataAnnotations说明&#xff1a;EF提供以特性的方式添加到 domain classes上,其中包括两类&#xff1a; A&#xff1a;System.ComponentModel.DataAnnotations命名空间下的特性是表中列的属性的。 包括&#xff1a;Key、Required、MinLength和MaxLength、StringL…

第十六节: EF的CodeFirst模式通过Fluent API修改默认协定

一. 简介 1. 优先级&#xff1a;Fluent API > data annotations > default conventions. 2. 所有的Fluent API配置都要在 OnModelCreating这个重写方法中进行 3. 常见的配置&#xff1a; ① 获取表对应的配置根&#xff1a; var stu modelBuilder.Entity<XXX>(); ②…

安卓手机挂载Linux,android 挂载NFS教程

0&#xff0c;在Ubuntu新建nfs目录:#mkdir /home/shuimu/arm_project/rootfs将FORLINX_6410_yaffs2_v1.0.tgz复制到rootfs中&#xff0c;解压当前文件夹#tar–zxf FORLINX_6410_yaffs2_v1.0.tgz1.烧写mmc&#xff0c;uboot&#xff0c;zImage到开发板。2&#xff0c;在ubuntu上…

linux apache jk,Linux下Apache+Tomcat+JK实现负载均衡和群集的完整过程

感谢chaijunkun的精彩大作&#xff0c;真的辛苦了。最近在开发的项目需要承受很高的并发量。综合各种情况&#xff0c;决定使用ApacheTomcatJK的方式实现负载均衡&#xff0c;并且作为一个统一的服务还要实现群集(同步Session)。在网上找了很多资料&#xff0c;都是零零散散的&…

第十七节: EF的CodeFirst模式的四种初始化策略和通过Migration进行数据的迁移

一. 四种初始化策略 EF的CodeFirst模式下数据库的初始化有四种策略&#xff1a; 1. CreateDatabaseIfNotExists&#xff1a;EF的默认策略&#xff0c;数据库不存在,生成数据库&#xff1b;一旦model发生变化,抛异常&#xff0c;提示走数据迁移 2. DropCreateDatabaseIfModelCha…

linux笔记本不关机直接合上,笔记本电脑不关机直接合上行吗

可以。笔记本电脑将盖子合住&#xff0c;对电脑是没有损害&#xff0c;系统的默认设置是合上盖子后电脑处于待机状态。这时电脑的大部分硬件都已经关闭&#xff0c;只有个别硬件为了唤醒计算机仍在运行&#xff0c;但都是低功耗&#xff0c;不浪费电&#xff0c;也不会加快计算…

第十九节: 结合【表达式目录树】来封装EF的BaseDal层的方法

一. 简介 该章节&#xff0c;可以说是一个简单轻松的章节&#xff0c;只要你对Expression表达式树、EF的基本使用、泛型有所了解&#xff0c;那么本章节实质上就是一个非常简单的封装章节&#xff0c;便于我们快捷开发。 PS&#xff1a;在该章节对于EF的上下文怎么处理&#xf…

115网盘linux 下载速度慢,linux vps 上 下载115网盘 的方法

大多数童鞋买的vps都是只支持linux系统的&#xff0c;因为版权的问题&#xff0c;windows系统的vps价格上面要贵一些。但是&#xff0c;遇到要下载网盘文件时&#xff0c;没有装桌面只有shell的linux vps就表示压力大了&#xff0c;幸好LV发现一个Linux vps下载115网盘的方法&a…

第二十节: 深入理解并发机制以及解决方案(锁机制、EF自有机制、队列模式等)

一. 理解并发机制 1. 什么是并发&#xff0c;并发与多线程有什么关系&#xff1f; ①. 先从广义上来说&#xff0c;或者从实际场景上来说. 高并发通常是海量用户同时访问(比如&#xff1a;12306买票、淘宝的双十一抢购)&#xff0c;如果把一个用户看做一个线程的话那么并发可…

第二十一节:ADO层次上的海量数据处理方案(SqlBulkCopy类插入和更新)

一. 简介 1. 背景&#xff1a; 虽然前面EF的扩展插件Z.EntityFramework.Extensions&#xff0c;性能很快&#xff0c;而且也很方便&#xff0c;但是该插件要收费&#xff0c;使用免费版本的话&#xff0c;需要定期更新&#xff0c;如果不更新&#xff0c;将失效&#xff0c;非…

第二十二节: 以SQLServer为例介绍数据库自有的锁机制(共享锁、更新锁、排它锁等)和事务隔离级别 :

一. 基本概念 1.共享锁&#xff1a;(holdlock) (1). select的时候会自动加上共享锁&#xff0c;该条语句执行完&#xff0c;共享锁立即释放&#xff0c;与事务是否提交没有关系。 (2). 显式通过添加(holdlock)来显式添加共享锁&#xff08;比如给select语句显式添加共享锁&…

r语言中1c0怎么表示什么,r语言表示或者用什么符号?

犯罪嫌疑人X1、对象名称中的句点(.)没有特殊意义。但美元符号($)却有着和其他语言中的句点类似的含义&#xff0c;即指定一个对象中的某些部分例如&#xff1a;(1)A$x是指数据框A中的变量x。(2)lm.x 指一个变量&#xff0c;lm$x则指对象lm的一个属性。2、 R不提供多行注释或块注…

第二十三节: EF性能篇(三)之基于开源组件 Z.EntityFrameWork.Plus.EF6解决EF性能问题

一. 开篇说明 EF的性能问题一直以来经常被人所吐槽&#xff0c;究其原因在于“复杂的操作在生成SQL阶段耗时长&#xff0c;且执行效率不高”&#xff0c;但并不是没有办法解决&#xff0c;从EF本身举几个简单的优化例子&#xff1a; ①&#xff1a;如果仅是查询数据&#xff0c…

c语言怎样计算栈的长度,数据结构与算法:栈 C语言实现

栈是仅在表尾进行插入、删除操作的线性表。即栈 S (a1, a2, a3, ………,an-1, an)&#xff0c;其中表尾称为栈顶 /top&#xff0c;表头称为栈底/base。由于只能在表尾进行操作&#xff0c;因此栈的运算规则就是“后进先出”(LIFO)和线性表类似&#xff0c;栈也有两种存储结构—…

WebApi系列(从.Net 到 .Net Core)【更新】

一. 简介 1. 什么是WebApi&#xff1f; WebApi是一个很广泛的概念&#xff0c;在这里我们特指.Net平台下的Asp.Net WebApi框架&#xff0c;它是针对各种客户端(浏览器、APP等)来构建Http服务的一个框架&#xff0c;它是一种RestFul风格的开发接口的技术&#xff0c;它比WebServ…