一. 整体说明

1. 本节用到的表

2. 状态说明补充

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

 ②.Added: 增加的状态。

 ③.Deleted: 删除的状态。

 ④.Modified: 修改的状态。

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

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

  using (DbContext db = new EFDB01Context())
{
var d1 = db.Set<T_UserInfor>().Where(u => u.id == "").FirstOrDefault();
Console.WriteLine(db.Entry(d1).State); //Unchanged
var d2 = db.Set<T_UserInfor>().AsNoTracking().Where(u => u.id == "").FirstOrDefault();
Console.WriteLine(db.Entry(d2).State); //Detached
}

二. 增加

1. 原理

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

2. 几种增加情况

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

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

                     {
var u1 = new T_UserInfor()
{
id = Guid.NewGuid().ToString("N"),
userName = "ypf",
userSex = "男",
userAge = ,
addTime = DateTime.Now
};
var u2 = new T_UserInfor()
{
id = Guid.NewGuid().ToString("N"),
userName = "ypf2",
userSex = "男2",
userAge = ,
addTime = DateTime.Now
};
var state1 = db.Entry(u1).State;
var state2 = db.Entry(u2).State; db.Set<T_UserInfor>().Add(u1);
db.Add(u2); var state3 = db.Entry(u1).State;
var state4 = db.Entry(u2).State; int count = db.SaveChanges(); var state5 = db.Entry(u1).State;
var state6 = db.Entry(u2).State; Console.WriteLine($"count={count}");
Console.WriteLine($"{state1}→{state3}→{state5}");
Console.WriteLine($"{state2}→{state4}→{state6}");
}
                     {
var u1 = new T_UserInfor()
{
id = Guid.NewGuid().ToString("N"),
userName = "ypf",
userSex = "男",
userAge = ,
addTime = DateTime.Now
};
var u2 = new T_UserInfor()
{
id = Guid.NewGuid().ToString("N"),
userName = "ypf2",
userSex = "男2",
userAge = ,
addTime = DateTime.Now
};
var state1 = db.Entry(u1).State;
var state2 = db.Entry(u2).State; db.Entry(u1).State = EntityState.Added;
db.Entry(u2).State = EntityState.Added; var state3 = db.Entry(u1).State;
var state4 = db.Entry(u2).State; int count = db.SaveChanges(); var state5 = db.Entry(u1).State;
var state6 = db.Entry(u2).State; Console.WriteLine($"count={count}");
Console.WriteLine($"{state1}→{state3}→{state5}");
Console.WriteLine($"{state2}→{state4}→{state6}");
}

3. 批量增加

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

                     {
var u1 = new T_UserInfor()
{
id = Guid.NewGuid().ToString("N"),
userName = "ypf",
userSex = "男",
userAge = ,
addTime = DateTime.Now
};
var u2 = new T_UserInfor()
{
id = Guid.NewGuid().ToString("N"),
userName = "ypf2",
userSex = "男2",
userAge = ,
addTime = DateTime.Now
};
var u3 = new T_UserInfor()
{
id = Guid.NewGuid().ToString("N"),
userName = "ypf",
userSex = "男",
userAge = ,
addTime = DateTime.Now
};
var u4 = new T_UserInfor()
{
id = Guid.NewGuid().ToString("N"),
userName = "ypf2",
userSex = "男2",
userAge = ,
addTime = DateTime.Now
};
db.AddRange(u1, u2); var list = new List<T_UserInfor>();
list.Add(u3);
list.Add(u4);
db.AddRange(list); int count = db.SaveChanges();
Console.WriteLine($"count={count}"); }

4. 指定自增键的插入

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

                     try
{
db.Database.OpenConnection();
db.Database.ExecuteSqlCommand("SET IDENTITY_INSERT [T_RoleInfor] ON");
var r2 = new T_RoleInfor()
{
id = ,
roleName = "管理员",
roleDescription = "我是管理员"
};
db.Add(r2);
int count2 = db.SaveChanges();
db.Database.ExecuteSqlCommand("SET IDENTITY_INSERT [T_RoleInfor] OFF");
}
catch (Exception)
{
}
finally
{
db.Database.CloseConnection();
}

5. 调用SQL语句增加

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

三. 修改

1. 原理

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

2. 几种更新情况

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

                     {
var u1 = db.T_UserInfor.Where(u => u.id == "").FirstOrDefault();
var state1 = db.Entry(u1).State;
if (u1 != null)
{
u1.userName = "kkkk";
}
var state2 = db.Entry(u1).State;
int count = db.SaveChanges();
var state3 = db.Entry(u1).State;
Console.WriteLine($"count={count}");
Console.WriteLine($"{state1}→{state2}→{state3}");
}

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

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

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

                     {
var u1 = new T_UserInfor()
{
id = "",
userName = "Marren",
addTime = DateTime.Now
};
var state1 = db.Entry(u1).State;
db.Update(u1);
//db.Set<T_UserInfor>().Update(u1); //效果同上
var state2 = db.Entry(u1).State;
int count = db.SaveChanges();
var state3 = db.Entry(u1).State;
Console.WriteLine($"count={count}");
Console.WriteLine($"{state1}→{state2}→{state3}");
}

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

                     {
var u1 = new T_UserInfor()
{
id = "",
userName = "Marren",
addTime = DateTime.Now
};
var state1 = db.Entry(u1).State;
db.Entry(u1).State = EntityState.Modified;
var state2 = db.Entry(u1).State;
int count = db.SaveChanges();
var state3 = db.Entry(u1).State;
Console.WriteLine($"count={count}");
Console.WriteLine($"{state1}→{state2}→{state3}");
}

  特别注意: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,执行了插入操作。

  //该主键在数据库中已经存在
//Detached→Unchanged→Unchanged(未执行任何sql操作)
{
var u1 = new T_UserInfor()
{
id = "",
userName = "Marren1",
addTime = DateTime.Now
};
var state1 = db.Entry(u1).State;
db.Attach(u1);
var state2 = db.Entry(u1).State; int count = db.SaveChanges(); var state3 = db.Entry(u1).State;
Console.WriteLine($"count={count}");
Console.WriteLine($"{state1}→{state2}→{state3}");
} //该主键在数据库中已经存在
//Detached→Modified→Unchanged。 且只有userName这一个字段被修改
{
var u1 = new T_UserInfor()
{
id = "",
userName = "Marren1",
addTime = DateTime.Now
};
var state1 = db.Entry(u1).State;
db.Attach(u1);
db.Entry(u1).Property("userName").IsModified = true;
var state2 = db.Entry(u1).State; int count = db.SaveChanges(); var state3 = db.Entry(u1).State;
Console.WriteLine($"count={count}");
Console.WriteLine($"{state1}→{state2}→{state3}");
} //该表主键是自增的,实体不设置主键
//Detached→Addedd→Unchanged。 (执行了插入操作)
{
var u1 = new T_RoleInfor()
{
roleName = "Marren1",
addTime = DateTime.Now
};
var state1 = db.Entry(u1).State;
db.Attach(u1);
var state2 = db.Entry(u1).State; int count = db.SaveChanges(); var state3 = db.Entry(u1).State;
Console.WriteLine($"count={count}");
Console.WriteLine($"{state1}→{state2}→{state3}");
}

3. 调用SQL语句更新

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

四. 删除

1. 原理

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

2. 删除已经跟踪的实体

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

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

                    //Unchanged→Deleted→Detached
//实体为空会报错
{
var u1 = db.T_UserInfor.Find("");
var state1 = db.Entry(u1).State;
if (u1 != null)
{
db.Remove(u1);
}
var state2 = db.Entry(u1).State;
int count = db.SaveChanges();
var state3 = db.Entry(u1).State;
Console.WriteLine($"count={count}");
Console.WriteLine($"{state1}→{state2}→{state3}");
}
//Unchanged→Deleted→Detached
//实体为空会报错
{
var u1 = db.T_UserInfor.Find("");
var state1 = db.Entry(u1).State;
if (u1 != null)
{
db.Entry(u1).State = EntityState.Deleted;
}
var state2 = db.Entry(u1).State;
int count = db.SaveChanges();
var state3 = db.Entry(u1).State;
Console.WriteLine($"count={count}");
Console.WriteLine($"{state1}→{state2}→{state3}");
}

3. 删除未跟踪的实体

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

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

                    //Detached→Deleted→Detached
//如果数据库中不存在这个id,会报错
{
var u1 = new T_UserInfor() { id = "" };
var state1 = db.Entry(u1).State;
db.Remove(u1);
var state2 = db.Entry(u1).State;
int count = db.SaveChanges();
var state3 = db.Entry(u1).State;
Console.WriteLine($"count={count}");
Console.WriteLine($"{state1}→{state2}→{state3}");
}
//Detached→Deleted→Detached
//如果数据库中不存在这个id,会报错
{
var u1 = new T_UserInfor() { id = "" };
var state1 = db.Entry(u1).State;
db.Entry(u1).State = EntityState.Deleted;
var state2 = db.Entry(u1).State;
int count = db.SaveChanges();
var state3 = db.Entry(u1).State;
Console.WriteLine($"count={count}");
Console.WriteLine($"{state1}→{state2}→{state3}");
}

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

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

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

                     {
var uList = db.T_UserInfor.Where(u => u.id != "").ToList();
if (uList.Count() != )
{
db.RemoveRange(uList);
}
int count = db.SaveChanges();
Console.WriteLine($"count={count}");
}

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

5. 级联删除

 暂时用不到,后续补充。

!

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

第二节:EF Core的常规“增删改”及状态的变化的更多相关文章

  1. Asp.net MVC4 使用EF实现数据库的增删改查

    EF的使用 步骤: (1)将EF添加到项目:在Model右击添加新建项 找到ADO.NET实体数据模型,接着... (2)实现数据库的增删改查       查询 (因为在Model中已经添加EF实体了 ...

  2. 使用EF实现数据库的增删改查

    EF的使用步骤:(1)将EF添加到项目:在Model右击添加新建项找到ADO.NET实体数据模型,接着…(2)实现数据库的增删改查查询(因为在Model中已经添加EF实体了,所以就可以在Control ...

  3. 使用Asp.Net Core MVC 开发项目实践[第二篇:EF Core]

    在项目中使用EF Core还是比较容易的,在这里我们使用的版本是EF Core 2.2. 1.使用nuget获取EF Core包 这个示例项目使用的是SQLSERVER,所以还需要下载Microsof ...

  4. EF学习笔记——通用增删改查方案

    http://blog.csdn.net/leftfist/article/details/25005307 我刚接触EF未久,还不知道它有什么强大之处,但看上去,EF提供了一般的增删改查功能.以往用 ...

  5. .NET MVC+ EF+通用存储过程实现增删改功能以及使用事物处理

    引摘: 1.EF对事务进行了封装:无论何时执行任何涉及Create,Update或Delete的查询,都会默认创建事务.当DbContext类上的SaveChanges()方法被调用时,事务就会提交, ...

  6. EF实现简单的增删改查

    1.在项目中添加ADO.NET实体数据模型: 2.接着根据提示配置数据库连接,配置完毕之后项目中生成了大致如下的内容(EF6.x): 其中TestData.tt中的Consumer,Stores是创建 ...

  7. WebForm 内置对象、数据增删改、状态保持

    一.内置对象 1.Response对象:响应请求 Response.Write("<script>alert('添加成功!')</script>"); → ...

  8. asp.net core webapi 使用ef 对mysql进行增删改查,并生成Docker镜像构建容器运行

    1.构建运行mysql容器,添加数据库user 参考Docker创建运行多个mysql容器,地址 http://www.cnblogs.com/heyangyi/p/9288402.html 添加us ...

  9. 使用EF 的简单的增删改查

    using DAL; using Model; using System; using System.Collections.Generic; using System.Linq; using Sys ...

随机推荐

  1. SpringBoot自动装配原理解析

    本文包含:SpringBoot的自动配置原理及如何自定义SpringBootStar等 我们知道,在使用SpringBoot的时候,我们只需要如下方式即可直接启动一个Web程序: @SpringBoo ...

  2. 解决IIS Web部署 svg/woff/woff2字体找不到问题(vue部署后找不到)

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/smartsmile2012/articl ...

  3. 个人项目-wc

    个人项目-WC   (C语言) 一.Github地址:https://github.com/Lin-J-F/WC 二.PSP表格 PSP2.1 Personal Software Process St ...

  4. Canny算法检测边缘

    Canny算法是边缘检测的一个经典算法,比单纯用一些微分算子来检测的效果要好很多,其优势有以下几点: 边缘误检与漏检率低. 边缘定位准确,且边界较细. 自带一定的滤噪功能,或者说,对噪声的敏感度要比单 ...

  5. PHP查询附近的人及其距离的实现方法

    1.附近的人 //获取该点周围的4个点 $distance = 1;//范围(单位千米) $lat = 113.873643; $lng = 22.573969; define('EARTH_RADI ...

  6. Linux的DNS主从服务器部署

    下面的部署是在Linux的DNS正向解析部署上进行修改的. 如果有什么问题或者错误,可以访问上篇帖子 下面开始有关DNS的服务部署.<DNS主从服务器> 环境描述: 192.168.196 ...

  7. 修改GIT已提交的用户名和邮箱

    修改GIT已提交的用户名和邮箱 原文:https://help.github.com/en/github/using-git/changing-author-info 说明 要更改在现有提交中记录的名 ...

  8. MySQL服务的构成(二)

    一.什么是实例 这里的实例不是类产生的实例对象,而是Linux系统下的一种机制 1.MySQL的后台进程+线程+预分配的内存结构. 2.MySQL在启动的过程中会启动后台守护进程,并生成工作线程,预分 ...

  9. 团队第四次作业:alpha1发布成绩汇总

    一.作业题目 团队第四次作业:alpha1发布 二.作业评分标准 博客评分规则(总分100)博客要求 给出开头和团队成员列表(10') 给出发布地址以及安装手册(20') 给出测试报告(40') 给出 ...

  10. input 关键字提示,对于一些特定优化来说,很有用处

    只用html就可以做出提醒操作:效果如下图 这里是代码,怎么样,很简单吧 <form action="/server" method="post"> ...