zoukankan      html  css  js  c++  java
  • 第十节: 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                 }

  • 相关阅读:
    error C4430: missing type specifier int assumed. Note: C++ does not support defaultint 解决方法
    A performance evaluation of local descriptors——局部描述子评估译文(1,2,...)
    global mapper裁剪DEM文件的方法
    直方图学习笔记
    vc++如何将客户区存为bmp【zz】
    处理tiff格式dem数据的方法——输出xyz坐标
    处理tiff格式dem数据的方法——输出txt形式高程信息
    我的社区成立了
    Closed socket connection for client /39.103.162.230:56100 (no session established for client)
    Will not attempt to authenticate using SASL (unknown error) (org.apache.zookeeper.ClientCnxn)
  • 原文地址:https://www.cnblogs.com/yaopengfei/p/7780624.html
Copyright © 2011-2022 走看看