第十節: 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                 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM