Entity Framework入门教程(10)---离线场景保存和删除实体/实体图集
离线场景保存和删除实体/实体图集
这一节的内容是在离线场景中保存实体和实体图集
在离线场景中,当我们保存一个离线的实体图集或一个单独的离线实体时,我们需要做两件事。首先,我们要把实体附加到新的上下文中,让上下文了知道存在这些实体。其次,我们需要手动设置每个实体的EntityState,因为新的上下文不知道这些离线实体都经过了些什么操作,所以新的上下文不能自动地给实体添加EntityState。上一节我们清楚了附加离线图集的方法,附加离线图集时默认添加的EntityState不一定合适,所以我们就要执行第二步:给实体或实体图集添加合适的EntityState。
1.离线场景中保存实体
在离线场景中我们保存一个实体时,最核心的问题:我们需要知道一个实体是新建的还是本来就存在的。只有知道了这个问题的答案,我们才能给实体设置EntityState。如果实体主键值是0(主键是Int类型,默认值为0)我们认为这个实体是新建的,给它的状态标记为Added;如果主键值大于0,那么我们就认为这个实体是已经存在的,将它的状态标记为Modified。如下图所示:

下边是一个栗子:
// 新建的离线实体
var student = new Student(){ StudentName = "Bill" }; using (var context = new SchoolDBEntities())
{
context.Entry(student).State = student.StudentId == ? EntityState.Added : EntityState.Modified; context.SaveChanges();
}
因为Student是新建的,Id默认为0,所以Student被标记为Added,在数据库中执行:
exec sp_executesql N'INSERT [dbo].[Student]([StudentName], [StandardId])
VALUES (@0, NULL)
SELECT [StudentID] FROM [dbo].[Student]
WHERE @@ROWCOUNT > 0 AND [StudentID] = scope_identity(),@0='Bill'
同样的,如果一个实体的主键不是0,那么将它的状态被标记为Modified,一个栗子:
// 虽然是新建的,但是因为Id不是0,所以EF认为是已存在的
var student = new Student(){ StudentId = , StudentName = "Steve" }; using (var context = new SchoolDBEntities())
{
context.Entry(student).State = student.StudentId == ? EntityState.Added : EntityState.Modified; context.SaveChanges();
}
在数据库中执行如下代码,注意:如果数据库中没有StudentId 为1的记录时,会报异常
exec sp_executesql N'UPDATE [dbo].[Student]
SET [StudentName] = @0
WHERE @@ROWCOUNT > 0 AND [StudentID] = @1'N'@0 varchar(50),@1 int',@0='Steve',@1=1
2.离线场景中保存实体图集
上边部分我们学习了通过主键值来设置实体的状态,这里我们将学习怎么去保存一个实体图集。
在离线场景中保存一个实体图集是一件比较复杂的事,我们需要进行认真的设计。离线场景中保存实体图集最需要解决的问题是给实体图集中的每一个实体添加标记适当的状态。但是怎么去设计呢?在下图中我们可以看到新的Context根本不知道每个实体的状态。

我们必须在执行SaveChange()方法前确定每一个实体的状态,下边介绍通过主键设置实体图集状态的方法
通过主键设置实体图集的状态
我们可以通过主键来设置实体图集中每一个实体的状态。如前边保存实体时介绍的,如果一个实体的主键是CLR数据类型的默认值(如int类型的默认值是0),那么我们认为这个实体是新建的,可以将这个实体标记为Added,在数据库执行Insert命令;如果主键值不是CLR数据类型的默认值,我们认为这个实体是已经存在了,标记为Modified,在数据库执行Update命令。
一个栗子:
var student = new Student() { //Root entity (没有主键值
Standard = new Standard() //Child entity (有主键值)
{
StandardId = ,
StandardName = "Grade 1"
},
Courses = new List<Course>() {
new Course(){ CourseName = "Machine Language" }, //Child entity (没有主键值)
new Course(){ CourseId = } //Child entity (有主键值)
}
};
using (var context = new SchoolDBEntities())
{
//给实体图集中的所有实体的状态进行标记
context.Entry(student).State = student.StudentId == ? EntityState.Added : EntityState.Modified;
context.Entry(student.Standard).State = student.Standard.StandardId == ? EntityState.Added : EntityState.Modified;
foreach (var course in student.Courses)
context.Entry(course).State = course.CourseId == ? EntityState.Added : EntityState.Modified;
context.SaveChanges();
}
在上边的栗子中,Student实体图集包含Standard和Course实体,context通过每个实体的主键对该实体的状态进行标记。
3.离线场景删除实体/实体图集
在离线场景删除一个实体很简单,只需通过Entry()方法把实体的状态标记为Deleted即可,注:我们在将离线实体附加到上下文提过,当父实体的状态是Deleted时,通过Entry()方法附加实体图集时,实体图集的所有子实体都为null,所以在执行SaveChange()进行数据库删除时,只删除父实体的记录!一个简单的栗子:
// 待删除的实体
var student = new Student(){ StudentId = }; using (var context = new SchoolDBEntities())
{
context.Entry(student).State = System.Data.Entity.EntityState.Deleted;
context.SaveChanges();
}
在上边的例子中,Student实体的实例只有主键值,删除一个实体也只需要主键值就可以了。在数据库中执行如下代码:
delete [dbo].[Student]
where ([StudentId] = @0)',N'@0 int',@0=1
EF系列目录链接:Entity Franmework系列教程汇总
Entity Framework入门教程(10)---离线场景保存和删除实体/实体图集的更多相关文章
- Entity Framework入门教程(9)---离线场景附加实体图集到上下文
附加离线实体图集到上下文 这节主要内容是通过不同的方法将离线实体附加到上下文中. 在离线场景中,保存一个实体要略微困难一些.当我们保存一个离线的实体图集或一个单独的离线实体时,我们需要做两件事.首先, ...
- Entity Framework入门教程(6)--- 在线场景中保存数据
在线场景中保存数据 在线场景中保存实体数据是一项相当容易的任务,因为使用的是同一个context,这个context会自动跟踪所有实体发生的更改. 下图说明了在线场景中的CUD(创建,更新,删除)操作 ...
- Entity Framework入门教程(5)---EF中的持久化场景
EF中的持久性场景 使用EF实现实体持久化(保存)到数据库有两种情况:在线场景和离线场景. 1.在线场景 在线场景中,context是同一个上下文实例(从DbContext派生),检索和保存实体都通过 ...
- Entity Framework入门教程(11)---EF6中的异步查询和异步保存
EF6中的异步查询和异步保存 在.NET4.5中介绍了异步操作,异步操作在EF中也很有用,在EF6中我们可以使用DbContext的实例进行异步查询和异步保存. 1.异步查询 下边是一个通过L2E语法 ...
- Entity Framework入门教程(1)---Entity Framework简介
什么是Entity Framework 学习EF的前提:熟练使用Linq和Ado.net,因为在使用EF框架进行开发时,我们大多数情况使用Linq进行查询和操作,而EF的底层实现用的是Ado.net. ...
- Entity Framework入门教程:什么是Entity Framework
Entity Framework简介 Entity Framework是微软提供的一个O/RM(对象关系映射)框架.它基于ADO.NET,为开发人员提供了一种自动化的机制来访问和存储数据库中的数据. ...
- Entity Framework入门教程(2)---EF工作流程
EF工作流程 1.EF基本CRUD流程 下边的图就可以很清晰地展示EF的CRUD操作的基本工作流程: 这里做一个EF CRUD操作的简单总结:1.定义模型:这是EF工作的前提,定义模型包括定义领域类( ...
- Entity Framework入门教程(13)---EF中的高并发
EF中的高并发 这里只介绍EF6中database-first开发方案的高并发解决方案,code-first开发方案中的高并发会在以后的EF CodeFirst系列中介绍. EF默认支持乐观并发:我们 ...
- ASP .NET MVC 之Entity Framework入门教程及源码
本文主要的目的是 1. 说明Entity Framework Power Tools如何使用. 2. Entity Framework 快速门 实验环境: OS: Windows Server 20 ...
随机推荐
- 文件比较命令(comp)
comp命令: // 描述: 逐字节比较两个文件或文件集的内容. 如果在没有参数的情况下使用,comp会提示你输入要比较的文件. // 语法: comp [<Data1>] [<Da ...
- 完成代码将x插入到该顺序有序线性表中,要求该线性表依然有序
#include <stdio.h> #include <malloc.h> int main(void) { int i, n; double s = 1.3; double ...
- Allowed memory size of 134217728 bytes exhausted解决办法(php内存耗尽报错)【简记】
报错: PHP Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 72 bytes) i ...
- ios兼容 iphoneX ios10 ios11
假设你有一个固定位置的标题栏,你的iOS10的CSS可能是这样写的: header { position: fixed; top:; left:; right:; height: 44px; padd ...
- Oracle Metric sequence load elapsed time
Oracle Metric sequence load elapsed time The sequence load elapsed time Oracle metric is the amount ...
- loc iloc函数的区别
import pandas as pd data1 = pd.read_excel(r"G:\Python\example1.xlsx") loc 用行列标签,iloc用数字索引. ...
- MATLAB accumarray
先看看subs和val的具体内容 subs = [1 1 1; 2 1 2; 2 3 2; 2 1 2; 2 3 2]; subs = 1 1 1 2 1 2 2 ...
- SkylineGlobe 7.0.1 & 7.0.2版本Web开发 如何实现对三维模型和地形的剖切展示
现在很多三维项目中,不仅仅要用到三维地形,正射影像和矢量数据,还会融合到各种三维模型,包括传统的3DMax手工建模,BIM,倾斜摄影自动建模,激光点云模型,三维地质体模型等等. 三维平台首先要做的是把 ...
- System.getProperty System.getenv 区别 log4j取法
log4j 可以${}取系统变量相关属性 getProperty Java提供了System类的静态方法getenv()和getProperty()用于返回系统相关的变量与属性,getenv方法返回 ...
- 【原创】分布式之大话CAP
引言 本文翻译自博客 http://ksat.me/a-plain-english-introduction-to-cap-theorem/ 博主觉得这个故事讲的生动活泼,因此翻译来给大家分享,顺便加 ...