Entity Framework 添加、附加、和实体状态

  这篇文章将会覆盖如何新增和附加实体到上下文以及在 SaveChanges 中Entity Framework 如何处理它们。 Entity Framework 会在实体与上下文连接时追踪它们的状态,但你能在实体与上下文断开连接或者 N-Tier 场景下让 EF 知道你的实体的状态是什么。在这篇文章中展示的技术同时适用于 通过Code First 创建的模型 和 EF 设计器创建的模型 。

实体状态 和 SaveChanges

在 EntityState 枚举定义中,一个实体能够处于以下的五个状态之一。这些状态是:

1、Added(新增的):实体将会被上下文追踪但尚未持久化到数据库中

2、Unchanged(未改变的):实体在数据库中存在并且将会被上下文追踪,但它的属性值和数据库中存在的值相比是尚未改变的(一致的)

3、Modified(已修改的):实体在数据库中存在并且将会被上下文追踪,同时它的部分或全部值已经被改变

4、Deleted(被删除的):实体在数据库中存在并且将会被上下文追踪,但已经被标记为在下一次 SaveChanges 被调用时数据库中将会删除的部分

5、Detached(分离的):实体将不会被上下文追踪

SaveChanges 在实体处于不同的状态时做不同的事:

1、Unchanged 的实体不会被SaveChanges 提及到。当实体在Unchanged 状态下,更新命令将不会被发送到数据库。

2、Added 的实体在SaveChanges 结束时会被插入到数据中,并且在上下文中的状态会变成 Unchanged 。

3、Modified 的实体在SaveChanges 结束时会被更新到数据库中,并且在上下文中的状态会变成 Unchanged 。

4、Deleted 的实体在SaveChanges 结束时会从数据库中删除,然后从当前上下文中分离,即 Detached。

下面的例子展示了实体的状态和实体图能够被改变的方式

添加一个实体到上下文中

一个实体能在数据集中通过调用 Add 方法被添加到上下文中。这将会使实体处于Added 状态,意味着它将在下次调用SaveChanges 方法时被插入到数据库中,例如:



using (var context = new BloggingContext())

{

var blog = new Blog { Name = "ADO.NET Blog" };

context.Blogs.Add(blog);

context.SaveChanges();

}


另一种添加一个实体到上下文中的方式是改变它的状态为 Added 。例如:



using (var context = new BloggingContext())

{

var blog = new Blog { Name = "ADO.NET Blog" };

context.Entry(blog).State = EntityState.Added;

context.SaveChanges();

}


最后,你也可以通过将一个实体挂勾到一个已被上下文追踪的实体来添加它到上下文中。这可以通过将新实体添加到另一个实体的导航属性集合中或着通过设置另一个实体的导航属性引用指向新实体。例如:



using (var context = new BloggingContext())

{

// 通过从已被追踪的Blog中设置引用来新增一个新 User

var  blog = context.Blogs.Find(1);

blog.Owner=new User{UserName="johndoe1987"});

//通过添加到一个已被追踪的Blog中的集合中来新增一个新 User

var blog = context.Blogs.Find(2);

blog.Posts.Add(new Post{ Name ="How to Add Entities" });

context.SaveChanges();

}



注意以上所有的例子中,如果一个被新增的实体已关联其他未被上下文追踪的实体,这些新实体将会被新增到上下文中,并且会在下次调用SaveChanges 时插入到数据库中。

附加一个已存在的实体到上下文中

如果你有一个已知的已在数据库中存在但当前未被上下文追踪的实体,你能通过在数据集上使用 Attach 方法来告知上下文去追踪这个实体。这个实体将处于 Unchanged 状态。例如:



var existingBlog = new Blog { BlogId = 1, Name = "ADO.NET Blog" };

using (var context = new BloggingContext())

{

context.Blogs.Attach(existingBlog);

// Do some more work…

context.SaveChanges();

}



注意如果调用SaveChanges 时没有对附加的实体进行其他的操作,那么对数据库将不会有任何的改变。这是因为这个实体处于Unchanged状态下。

另一个附加已存在的实体到上下文中的方式是改变它的状态为Unchanged。例如:



var existingBlog = new Blog { BlogId = 1,Name="ADO.NET Blog" };

using   (var context = new BloggingContext())

{

context.Entry(existingBlog).State = EntityState.Unchanged;

//Do some more work…

context.SaveChanges();

}



注意在以上的例子中,如果被附加的实体已关联其他尚未被追踪的实体,那么这些新实体也会被附加到以Unchanged的状态附加到上下文中。

 

附加一个已存在但已被修改的实体到上下文中

如果你有一个已经在数据库中存在并将会被改变的实体,你可以通过设置它的状态为Modified 来告知上下文去附加这个实体。例如:



var existingBlog = new Blog {BlogId=1,Name="ADO.NET Blog" };

using    (var context = new BloggingContext())

{

context.Entry(existingBlog).State = EntityState.Modified;

//Do some more work…

context.SaveChanges();

}



当你修改实体的状态为 Modified 时,该实体的所有属性将会被标识为已修改并所有的属性值将会在SaveChanges被调用时发送到数据库。

注意如果一个已被附加的实体已关联其他尚未被追踪的实体,那么这些实体将会以Unchanged的状体附加到上下文中——它们不会自动被修改。如果你有多个实体需要被标识为Modified ,你应该单独设置每一个实体的状态。

修改已被追踪的实体的状态

你可以在一个已被追踪的实体进入上下文时通过设置它的状态来直接修改状态



var   existingBlog = new Blog { BlogId = 1,Name = "ADO.NET Blog" };

using    (var context = new BloggingContext())

{

context.Blogs.Attach(existingBlog);

context.Entry(existingBlog).State = EntityState.Unchanged;

//Do some more work…

context.SaveChanges();

}



注意 为一个已被追踪的实体调用 Add 或者 Attach 方法通常用来修改实体的状态。例如,为一个已处于Added 状态下的实体调用 Attach 方法会修改它的状态为 Unchanged。

新增或者更新模式

一些应用程序中的一个常见的模式是根据主键的值来新增一个实体(导致数据库插入)或者附加一个已存在的实体并标识其为已修改(导致数据库更新)。例如,在使用数据库自增整型作为主键时,通过识别主键是否为0来判断一个实体是新实体还是已存在的是很常见的(实体的主键为0时视为新实体,主键非0时视为已存在)。这种模式能通过基于检查主键值来设置实体状态来实现。例如:



public void InsertOrUpdate(Blog blog)

{

using (var context = new BloggingContext())

{

context.Entry(blog).State = blog.BlogId == 0 ?

EntityState.Added :

EntityState.Modified;

context.SaveChanges();

}

}



注意当你修改实体的状态为 Modified 时,该实体的所有属性将会被标识为已修改并所有的属性值将会在SaveChanges被调用时发送到数据库。

来源:

https://msdn.microsoft.com/en-us/library/jj592676(v=vs.113).aspx

时间: 2024-10-12 11:01:44

Entity Framework 添加、附加、和实体状态的相关文章

Entity Framework添加记录时获取自增ID值

var m = new 你的Model(); db.你的Model.add(m); db.SaveChange(); Response.Write(m.Id); //执行.SaveChange()保存后就直接可以取得id值了. 保存前没有id值. Entity Framework在将数据插入数据库时,如果主键字段是自增标识列,会将该自增值返回给实体对象对应的属性. 比如下面添加博客随笔至数据库的示例代码: var blogPost = new BlogPost() { Author = "博客园

Entity Framework 第三篇 实体特性声明

Entity Framework中对实体的特性声明有着严格的要求 1.实体必须要有主键特性,但是如果实体没有主键特性那怎么办? public int ExecuteSqlCommand(string sql, params SqlParameter[] paras) { if (this.IsTransaction) { if (dbContext.Database.CurrentTransaction == null) { dbContext.Database.BeginTransaction

Entity Framework应用:根据实体的EntityState状态实现增删改查

在上一篇文章中,我们讲解了使用EF实现简单的增删改成,在这篇文章中我们使用实体的EntityState状态来优化数据的增删改查. 一.修改数据 上篇文章中的修改数据的方法是EF官方推荐的方式,即先查询出来要修改的数据,然后在修改.但是这种操作会导致多次操作数据库: 从上面的截图中可以看出,查询数据的时候会执行一次事物,修改的时候又执行了一次事物,即修改数据会操作两次数据库.那么有没有什么方法可以只操作一次数据库呢?那就是下面要讲解的EntityState. 使用EntityState优化上面的修

[C#/.NET]Entity Framework(EF) Code First 多对多关系的实体增,删,改,查操作全程详细示例

本文我们来学习一下在Entity Framework中使用Context删除多对多关系的实体是如何来实现的.我们将以一个具体的控制台小实例来了解和学习整个实现Entity Framework 多对多关系的实体删除的操作过程. 你将学习到 怎样创建一个引用Entity Framework的项目: 怎样配置Entity Framework的数据库连接: 怎样去掉Entity Framework Code First 生成的表名的复数: 怎样通过EntityTypeConfiguartion配置实体的

Entity Framework 使用注意:Where查询条件中用到的关联实体不需要Include

来自博客园开发团队开发前线最新消息: 在Entity Framework中,如果实体A关联了实体B,你想在加载实体A的同时加载实体B.通常做法是在LINQ查询中使用Include().但是,如果你在查询条件中用到了实体B,EF会自动加载实体B,这时Include不仅是多余的,而且还会增加额外的LEFT OUTER JOIN查询,影响性能. 请看我们在博问开发中遭遇这个问题时的一段代码: //For q.cnblogs.com public class QuestionService { priv

entity framework 新手入门篇(2)-entity framework基本的增删改查

经过前两节的简单描述,终于可以进入entity framework的使用部分了.本节将对entity framework原生的增删改查进行讲解. 承接上面的部分,我们有一个叫做House的数据库,其中包含house表和seller表. 一.entity framework 相关类的理解. 首先,House数据库在映射后会生成一个名为HouseEntities的类,这个类我们称之为数据上下文,可以简单的理解为数据库的部分映射(如果映射了全部的表,视图,存储过程,则可看作全部映射). 使用数据库的时

Entity Framework 基础

一.什么是Entity Framework 微软官方提供的ORM工具,ORM让开发人员节省数据库访问的代码时间,将更多的时间放到业务逻辑层代码上.EF提供变更跟踪.唯一性约束.惰性加载.查询事物等.开发人员使用Linq语言,对数据库操作如同操作Object对象一样省事. EF有三种使用场景,1. 从数据库生成Class,2.由实体类生成数据库表结构,3.  通过数据库可视化设计器设计数据库,同时生成实体类. O/RM是什么? ORM 是将数据存储从域对象自动映射到关系型数据库的工具.ORM主要包

MVC5 Entity Framework学习之实现基本的CRUD功能

在上一篇文章中,我们使用Entity Framework 和SQL Server LocalDB创建了一个MVC应用程序,并使用它来存储和显示数据.在这篇文章中,你将对由 MVC框架自动创建的CRUD(create, read, update, delete)代码进行修改. 注意:通常我们在控制器和数据访问层之间创建一个抽象层来实现仓储模式,为了将注意力聚焦在如何使用实体框架上,这里暂没有使用仓储模式. 在本篇文章中,要创建的web页面: 1.创建一个Details页面 由框架代码生成的Stud

Code First Entity Framework 6化被动为主动之explicit loading模式实战分析( 附源码)

在使用Entity Framework加载关联实体时,可以有三种方式: 1.懒加载(lazy Loading); 2.贪婪加载(eager loading); 3.显示加载(explicit loading). EF默认使用的是懒加载(lazy Loading).一切由EF自动处理. 这种方式会导致应用程序多次连接数据库,这种情况推荐在数据量较大的情况下使用.当我们需要加载数据较少时,一次性全部加载数据会相对更高效. 我们来看看EF的显示加载(explicit loading)如何让我们完全掌控