第二节:EF Core的常规“增删改”及状态的变化 您所在的位置:网站首页 win19042631更新 第二节:EF Core的常规“增删改”及状态的变化

第二节:EF Core的常规“增删改”及状态的变化

2024-01-02 12:30| 来源: 网络整理| 查看: 265

一. 整体说明

1. 本节用到的表

 

2. 状态说明补充

 ①.Detached: 游离的状态,与数据库没有什么交涉,比如新new一个实体,状态就是Detached。

 ②.Added: 增加的状态。

 ③.Deleted: 删除的状态。

 ④.Modified: 修改的状态。

 ⑤.Unchanged: 与数据库内容相比,未发生变化时的状态,从数据库中查询出来的对象就是Unchanged状态。

PS:查询出来的实体,AsNoTracking一下,就变成Detached游离状态了 。

1 using (DbContext db = new EFDB01Context()) 2 { 3 var d1 = db.Set().Where(u => u.id == "01").FirstOrDefault(); 4 Console.WriteLine(db.Entry(d1).State); //Unchanged 5 var d2 = db.Set().AsNoTracking().Where(u => u.id == "01").FirstOrDefault(); 6 Console.WriteLine(db.Entry(d2).State); //Detached 7 }

 

二. 增加

1. 原理

  修改实体到 Added 状态,调用 SaveChanges 时,生成 Insert 语句。

2. 几种增加情况

  (1). 新建实体,然后 db.Set().Add(u1); 或者 直接db.Add()方法,状态变化为:Detached→Added→Unchanged

  (2). 新建实体,直接修改状态 EntityState.Added,状态变化为:Detached→Added→Unchanged

1 { 2 var u1 = new T_UserInfor() 3 { 4 id = Guid.NewGuid().ToString("N"), 5 userName = "ypf", 6 userSex = "男", 7 userAge = 19, 8 addTime = DateTime.Now 9 }; 10 var u2 = new T_UserInfor() 11 { 12 id = Guid.NewGuid().ToString("N"), 13 userName = "ypf2", 14 userSex = "男2", 15 userAge = 19, 16 addTime = DateTime.Now 17 }; 18 var state1 = db.Entry(u1).State; 19 var state2 = db.Entry(u2).State; 20 21 db.Set().Add(u1); 22 db.Add(u2); 23 24 var state3 = db.Entry(u1).State; 25 var state4 = db.Entry(u2).State; 26 27 int count = db.SaveChanges(); 28 29 var state5 = db.Entry(u1).State; 30 var state6 = db.Entry(u2).State; 31 32 Console.WriteLine($"count={count}"); 33 Console.WriteLine($"{state1}→{state3}→{state5}"); 34 Console.WriteLine($"{state2}→{state4}→{state6}"); 35 } View Code 1 { 2 var u1 = new T_UserInfor() 3 { 4 id = Guid.NewGuid().ToString("N"), 5 userName = "ypf", 6 userSex = "男", 7 userAge = 19, 8 addTime = DateTime.Now 9 }; 10 var u2 = new T_UserInfor() 11 { 12 id = Guid.NewGuid().ToString("N"), 13 userName = "ypf2", 14 userSex = "男2", 15 userAge = 19, 16 addTime = DateTime.Now 17 }; 18 var state1 = db.Entry(u1).State; 19 var state2 = db.Entry(u2).State; 20 21 db.Entry(u1).State = EntityState.Added; 22 db.Entry(u2).State = EntityState.Added; 23 24 var state3 = db.Entry(u1).State; 25 var state4 = db.Entry(u2).State; 26 27 int count = db.SaveChanges(); 28 29 var state5 = db.Entry(u1).State; 30 var state6 = db.Entry(u2).State; 31 32 Console.WriteLine($"count={count}"); 33 Console.WriteLine($"{state1}→{state3}→{state5}"); 34 Console.WriteLine($"{state2}→{state4}→{state6}"); 35 } View Code

3. 批量增加

  调用AddRange方法,参数可以db.AddRange(u1, u2); 或者 db.AddRange(list); 批量增加最大的好处是生产一条sql语句,性能相对更高。

1 { 2 var u1 = new T_UserInfor() 3 { 4 id = Guid.NewGuid().ToString("N"), 5 userName = "ypf", 6 userSex = "男", 7 userAge = 19, 8 addTime = DateTime.Now 9 }; 10 var u2 = new T_UserInfor() 11 { 12 id = Guid.NewGuid().ToString("N"), 13 userName = "ypf2", 14 userSex = "男2", 15 userAge = 19, 16 addTime = DateTime.Now 17 }; 18 var u3 = new T_UserInfor() 19 { 20 id = Guid.NewGuid().ToString("N"), 21 userName = "ypf", 22 userSex = "男", 23 userAge = 19, 24 addTime = DateTime.Now 25 }; 26 var u4 = new T_UserInfor() 27 { 28 id = Guid.NewGuid().ToString("N"), 29 userName = "ypf2", 30 userSex = "男2", 31 userAge = 19, 32 addTime = DateTime.Now 33 }; 34 db.AddRange(u1, u2); 35 36 var list = new List(); 37 list.Add(u3); 38 list.Add(u4); 39 db.AddRange(list); 40 41 int count = db.SaveChanges(); 42 Console.WriteLine($"count={count}"); 43 44 }

4. 指定自增键的插入

  通过ExecuteSqlCommand("SET IDENTITY_INSERT [T_RoleInfor] ON");先关闭自增,然后插入数据后,再通过ExecuteSqlCommand("SET IDENTITY_INSERT [T_RoleInfor] OFF");开启自增

1 try 2 { 3 db.Database.OpenConnection(); 4 db.Database.ExecuteSqlCommand("SET IDENTITY_INSERT [T_RoleInfor] ON"); 5 var r2 = new T_RoleInfor() 6 { 7 id = 123, 8 roleName = "管理员", 9 roleDescription = "我是管理员" 10 }; 11 db.Add(r2); 12 int count2 = db.SaveChanges(); 13 db.Database.ExecuteSqlCommand("SET IDENTITY_INSERT [T_RoleInfor] OFF"); 14 } 15 catch (Exception) 16 { 17 } 18 finally 19 { 20 db.Database.CloseConnection(); 21 }

5. 调用SQL语句增加

  利用方法ExecuteSqlCommand("SQL增加语句")

三. 修改

1. 原理

  数据库中有主键所对应的记录,修改实体到 Modified 状态,调用 SaveChanges 时,生成 Update 语句。

2. 几种更新情况

 (1).更新已经跟踪的实体(即从数据库中查询出来的),当修改值和数据库中不同时,状态变化为:Unchanged→Modified→Unchanged,直接执行SaveChanges方法执行修改。 当修改值和数据库中原值相同时,状态不发生变化:Unchanged→Unchanged→Unchanged,即使调用SaveChanges也不执行任何sql操作。

1 { 2 var u1 = db.T_UserInfor.Where(u => u.id == "01").FirstOrDefault(); 3 var state1 = db.Entry(u1).State; 4 if (u1 != null) 5 { 6 u1.userName = "kkkk"; 7 } 8 var state2 = db.Entry(u1).State; 9 int count = db.SaveChanges(); 10 var state3 = db.Entry(u1).State; 11 Console.WriteLine($"count={count}"); 12 Console.WriteLine($"{state1}→{state2}→{state3}"); 13 }

 (2).更新未跟踪实体数据

 新建一个实体,这个实体必须有主键(且数据库中存在),未包含的属性则当做空值来更新,当修改值和数据库值不同时候,状态变化为: Detached→Modified→Unchanged。

 方案一:调用Update方法,其原理也是修改状态为 Modified。

1 { 2 var u1 = new T_UserInfor() 3 { 4 id = "01", 5 userName = "Marren", 6 addTime = DateTime.Now 7 }; 8 var state1 = db.Entry(u1).State; 9 db.Update(u1); 10 //db.Set().Update(u1); //效果同上 11 var state2 = db.Entry(u1).State; 12 int count = db.SaveChanges(); 13 var state3 = db.Entry(u1).State; 14 Console.WriteLine($"count={count}"); 15 Console.WriteLine($"{state1}→{state2}→{state3}"); 16 }

 方案二:直接修改状态 db.Entry(u1).State = EntityState.Modified;

1 { 2 var u1 = new T_UserInfor() 3 { 4 id = "01", 5 userName = "Marren", 6 addTime = DateTime.Now 7 }; 8 var state1 = db.Entry(u1).State; 9 db.Entry(u1).State = EntityState.Modified; 10 var state2 = db.Entry(u1).State; 11 int count = db.SaveChanges(); 12 var state3 = db.Entry(u1).State; 13 Console.WriteLine($"count={count}"); 14 Console.WriteLine($"{state1}→{state2}→{state3}"); 15 }

  特别注意:Update 方法 与 设置 EntityState 方案一样,会将实体状态设置为 Modified 状态。由于跟踪器没有任何方法来识别哪些属性值已经更改,所以生成的 UPDATE 语句会更新所有字段属性。Update 方法与显示设置设置 EntityState 不同的是,Update 方法会修改相关实体(如 Blog 的 Posts 导航属性)的状态为已修改,从而会为每个实体生成UPDATE语句。如果相关实体没有对应的键值,就会标记为 Added 状态,生成一条 Insert语句。

 方案三:Attach()用法。

 ①.新建一个实体,有主键(且数据库中存在、修改值和数据库值不同),调用Attach,状态变化 Detached→Unchanged→Unchanged ,未执行任何sql操作。

 ②.新建一个实体,有主键(且数据库中存在、修改值和数据库值不同),调用Attach,然后指定字段修改状态: db.Entry(u1).Property("userName").IsModified = true;状态变化为:Detached→Modified→Unchanged。 且只有userName这一个字段被修改

 ③. 该表主键是自增的,新建实体不设置主键,状态变化为:Detached→Addedd→Unchanged,执行了插入操作。

1 //该主键在数据库中已经存在 2 //Detached→Unchanged→Unchanged(未执行任何sql操作) 3 { 4 var u1 = new T_UserInfor() 5 { 6 id = "01", 7 userName = "Marren1", 8 addTime = DateTime.Now 9 }; 10 var state1 = db.Entry(u1).State; 11 db.Attach(u1); 12 var state2 = db.Entry(u1).State; 13 14 int count = db.SaveChanges(); 15 16 var state3 = db.Entry(u1).State; 17 Console.WriteLine($"count={count}"); 18 Console.WriteLine($"{state1}→{state2}→{state3}"); 19 } 20 21 //该主键在数据库中已经存在 22 //Detached→Modified→Unchanged。 且只有userName这一个字段被修改 23 { 24 var u1 = new T_UserInfor() 25 { 26 id = "01", 27 userName = "Marren1", 28 addTime = DateTime.Now 29 }; 30 var state1 = db.Entry(u1).State; 31 db.Attach(u1); 32 db.Entry(u1).Property("userName").IsModified = true; 33 var state2 = db.Entry(u1).State; 34 35 int count = db.SaveChanges(); 36 37 var state3 = db.Entry(u1).State; 38 Console.WriteLine($"count={count}"); 39 Console.WriteLine($"{state1}→{state2}→{state3}"); 40 } 41 42 //该表主键是自增的,实体不设置主键 43 //Detached→Addedd→Unchanged。 (执行了插入操作) 44 { 45 var u1 = new T_RoleInfor() 46 { 47 roleName = "Marren1", 48 addTime = DateTime.Now 49 }; 50 var state1 = db.Entry(u1).State; 51 db.Attach(u1); 52 var state2 = db.Entry(u1).State; 53 54 int count = db.SaveChanges(); 55 56 var state3 = db.Entry(u1).State; 57 Console.WriteLine($"count={count}"); 58 Console.WriteLine($"{state1}→{state2}→{state3}"); 59 } View Code

3. 调用SQL语句更新

  利用方法ExecuteSqlCommand("SQL更新语句")

 

四. 删除

1. 原理

 数据库中有主键所对应的记录,修改实体到 Deleted 状态,调用 SaveChanges 时,生成 Delete 语句。

2. 删除已经跟踪的实体

 调用Remove方法或者直接设置EntityState.Deleted,状态变化为:Unchanged→Deleted→Detached

 注:查询出来的实体为空的话会报错。

1 //Unchanged→Deleted→Detached 2 //实体为空会报错 3 { 4 var u1 = db.T_UserInfor.Find("02"); 5 var state1 = db.Entry(u1).State; 6 if (u1 != null) 7 { 8 db.Remove(u1); 9 } 10 var state2 = db.Entry(u1).State; 11 int count = db.SaveChanges(); 12 var state3 = db.Entry(u1).State; 13 Console.WriteLine($"count={count}"); 14 Console.WriteLine($"{state1}→{state2}→{state3}"); 15 } 16 //Unchanged→Deleted→Detached 17 //实体为空会报错 18 { 19 var u1 = db.T_UserInfor.Find("03"); 20 var state1 = db.Entry(u1).State; 21 if (u1 != null) 22 { 23 db.Entry(u1).State = EntityState.Deleted; 24 } 25 var state2 = db.Entry(u1).State; 26 int count = db.SaveChanges(); 27 var state3 = db.Entry(u1).State; 28 Console.WriteLine($"count={count}"); 29 Console.WriteLine($"{state1}→{state2}→{state3}"); 30 }

3. 删除未跟踪的实体

 调用Remove方法或者直接设置EntityState.Deleted,状态变化为:Unchanged→Deleted→Detached

 注:如果数据库中不存在这个id,会报错

1 //Detached→Deleted→Detached 2 //如果数据库中不存在这个id,会报错 3 { 4 var u1 = new T_UserInfor() { id = "04" }; 5 var state1 = db.Entry(u1).State; 6 db.Remove(u1); 7 var state2 = db.Entry(u1).State; 8 int count = db.SaveChanges(); 9 var state3 = db.Entry(u1).State; 10 Console.WriteLine($"count={count}"); 11 Console.WriteLine($"{state1}→{state2}→{state3}"); 12 } 13 //Detached→Deleted→Detached 14 //如果数据库中不存在这个id,会报错 15 { 16 var u1 = new T_UserInfor() { id = "05" }; 17 var state1 = db.Entry(u1).State; 18 db.Entry(u1).State = EntityState.Deleted; 19 var state2 = db.Entry(u1).State; 20 int count = db.SaveChanges(); 21 var state3 = db.Entry(u1).State; 22 Console.WriteLine($"count={count}"); 23 Console.WriteLine($"{state1}→{state2}→{state3}"); 24 }

总结:无论是跟踪的实体还是未跟踪的实体,都可以调用Remove方法或者直接设置状态为 Deleted进行删除。(PS:与传统的EF不一样,不需要Attach)

4. 批量删除或者调用SQL语句删除

 (1).批量删除:调用RemoveRange方法,生成一条SQL语句,性能相对更高。

1 { 2 var uList = db.T_UserInfor.Where(u => u.id != "01").ToList(); 3 if (uList.Count() != 0) 4 { 5 db.RemoveRange(uList); 6 } 7 int count = db.SaveChanges(); 8 Console.WriteLine($"count={count}"); 9 }

 (2).调用SQL语句:利用方法ExecuteSqlCommand("SQL删除语句")

5. 级联删除

 暂时用不到,后续补充。

 

 

 

 

 

!

作       者 : Yaopengfei(姚鹏飞) 博客地址 : http://www.cnblogs.com/yaopengfei/ 声     明1 : 本人才疏学浅,用郭德纲的话说“我是一个小学生”,如有错误,欢迎讨论,请勿谩骂^_^。 声     明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。  


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有