上一篇我们介绍了Entity Framework Core系列之DbContext(添加),这一篇我们介绍下修改数据

修改实体的方法取决于context是否正在跟踪需要修改的实体。

下面的示例中实体由context获得,所以context会开始追踪这个实体。当我们更改这个实体的属性值时,context会将实体的EntityState更改为已修改,ChangeTracker将记录旧属性值和新属性值。当调用SaveChanges时,会生成update语句并执行。

 var author = context.Authors.First(a => a.AuthorId == );
author.FirstName = "Bill";
context.SaveChanges();

由于ChangeTracker记录哪些属性已被修改,Context将发出一条SQL语句,该语句只更新已修改的属性:

exec sp_executesql N'SET NOCOUNT ON;
UPDATE [Authors] SET [FirstName] = @p0
WHERE [AuthorId] = @p1;
SELECT @@ROWCOUNT;
',N'@p1 int,@p0 nvarchar(4000)',@p1=1,@p0=N'Bill'

断开连接的场景

在一个断开连接的场景如ASP.NET应用程序中,在controller或者服务方法中可能会发生更改现有实体属性值。在这种情况下,需要告知Context实体处于修改状态, 有几种方法: 显式地为实体设置EntityState; 用DbContext.Update 方法(EF Core新内容); 使用DbContext.Attach方法,然后“遍历对象图”,以显式地设置图中各个属性的状态.

设置EntityState

通过EntityEntry设置实体的EntityState

 public void Save(Author author)
{
using (var context = new EFCoreContext())
{
context.Entry(author).State = EntityState.Modified;
context.SaveChanges();
}
}

这种方法只会导致Author实体被设置成修改后的状态。不会设置任何相关对象。由于ChangeTracker不知道修改了哪些属性,因此Context生成一条SQL语句来更新所有属性值(除了主键值之外)。

DbContext Update

DbContext类提供用于处理单个或多个实体的Update和UpdateRange方法。

 public void Save(Author author)
{
using (var context = new EFCoreContext())
{
context.Update(author);
context.SaveChanges();
}
}

与设置EntityState方法一样,这个方法也会将Context追踪的实体设置成修改状态。同样,Context没有任何方法来识别哪些属性值已经更改,所以生成SQL来更新所有属性。与显示设置设置EntityState不同的是,Context也会修改相关实体(如本例中的Books)的状态为已修改,从而会为每个实体生成update语句。如果相关实体没有对应的键值,就会标记为add,生成一条Insert语句。

DbContext Attach

当在实体上使用Attach方法时,它的状态将被设置为unchanged,这将导致根本不会生成任何sql语句,所有定义了键值的其他可访问实体也将被设置为unchanged。那些没有键值的将被标记为Added。但是,现在该实体正在被Context跟踪,我们可以通知上下文哪些属性被修改,生成正确的UPDATE SQL:

 using (var context = new EFCoreContext())
{
var author = new Author
{
AuthorId = ,
FirstName = "yixuan",
LastName = "han"
};
author.Books.Add(new Book { BookId = , Title = "Othello" }); context.Attach(author);
context.Entry(author).Property("FirstName").IsModified = true;
context.SaveChanges();
}

上面的代码会将Author实体设置成被修改,生成的sql语句也之后更新FirstName。

exec sp_executesql N'SET NOCOUNT ON;
UPDATE [Authors] SET [FirstName] = @p0
WHERE [AuthorId] = @p1;
SELECT @@ROWCOUNT;
',N'@p1 int,@p0 nvarchar(4000)',@p1=1,@p0=N'William'

TrackGraph

TrackGraph API提供了对对象图中各个实体的访问,并允许您对每个实体分别执行定制代码。这在处理这种由不同对象的相关实体的复杂对象图的场景中非常有用。下面的示例复制了一个场景,其中对象图是在Context之外构造的。然后用TrackGraph方法“走图”:

   var author = new Author
{
AuthorId = ,
FirstName = "yixuan",
LastName = "han"
};
author.Books.Add(new Book { AuthorId = , BookId = , Title = "Hamlet", Isbn = "" });
author.Books.Add(new Book { AuthorId = , BookId = , Title = "Othello", Isbn = "" });
author.Books.Add(new Book { AuthorId = , BookId = , Title = "MacBeth", Isbn = "" });
using (var context = new EFCoreContext())
{
context.ChangeTracker.TrackGraph(author, e => {
if ((e.Entry.Entity as Author) != null)
{
e.Entry.State = EntityState.Unchanged;
}
else
{
e.Entry.State = EntityState.Modified;
}
});
context.SaveChanges();
}

在这个场景中,假定Author实体没有被修改,但是Book可能被编辑过。TrackGraph方法将根实体作为参数,并使用lambda指定要执行的操作。在这种情况下,根实体(Author)将其EntityState设置为不变。Context开始跟踪实体,设置EntityState,只有这样才能发现和它相关的实体。Books的EntityState设置为Modified,与前面的示例一样,这将导致生成SQL更新实体上的所有属性:

exec sp_executesql N'SET NOCOUNT ON;
UPDATE [Books] SET [AuthorId] = @p0, [Isbn] = @p1, [Title] = @p2
WHERE [BookId] = @p3;
SELECT @@ROWCOUNT;
UPDATE [Books] SET [AuthorId] = @p4, [Isbn] = @p5, [Title] = @p6
WHERE [BookId] = @p7;
SELECT @@ROWCOUNT;
UPDATE [Books] SET [AuthorId] = @p8, [Isbn] = @p9, [Title] = @p10
WHERE [BookId] = @p11;
SELECT @@ROWCOUNT;
',N'@p3 int,@p0 int,@p1 nvarchar(4000),@p2 nvarchar(150),@p7 int,@p4 int,@p5 nvarchar(4000),
@p6 nvarchar(150),@p11 int,@p8 int,@p9 nvarchar(4000),@p10 nvarchar(150)',
@p3=1,@p0=1,@p1=N'',@p2=N'Hamlet',
@p7=2,@p4=1,@p5=N'',@p6=N'Othello',
@p113,@p8=1,@p9=N'',@p10=N'MacBeth'

因为SQL更新了所有属性,所以它们都需要显示并分配一个有效值,否则它们将被更新为默认值。在下一个示例中,对象图再次在Context之外构造,但只修改了books的Isbn属性。因此,其他属性(除了实体键)被省略:

 var author = new Author
{
AuthorId = ,
FirstName = "William",
LastName = "Shakespeare"
};
author.Books.Add(new Book { BookId = , Isbn = "" });
author.Books.Add(new Book { BookId = , Isbn = "" });
author.Books.Add(new Book { BookId = , Isbn = "" }); using (var context = new EFCoreContext())
{
context.ChangeTracker.TrackGraph(author, e => {
e.Entry.State = EntityState.Unchanged; //starts tracking
if ((e.Entry.Entity as Book) != null)
{
context.Entry(e.Entry.Entity as Book).Property("Isbn").IsModified = true;
}
});
}

这一次,lambda的方法主体确保所有实体都被设置成Unchanged,然后指示Isbn属性被修改。这导致生成的SQL只更新Isbn属性值:

exec sp_executesql N'SET NOCOUNT ON;
UPDATE [Books] SET [Isbn] = @p0
WHERE [BookId] = @p1;
SELECT @@ROWCOUNT;
UPDATE [Books] SET [Isbn] = @p2
WHERE [BookId] = @p3;
SELECT @@ROWCOUNT;
UPDATE [Books] SET [Isbn] = @p4
WHERE [BookId] = @p5;
SELECT @@ROWCOUNT;
',N'@p1 int,@p0 nvarchar(4000),@p3 int,@p2 nvarchar(4000),@p5 int,@p4 nvarchar(4000)',
@p1=1,@p0=N'',
@p3=2,@p2=N'',
@p5=3,@p4=N''

Entity Framework Core系列之DbContext(修改)的更多相关文章

  1. Entity Framework Core系列之DbContext(删除)

    上一篇我们介绍了Entity Framework Core系列之DbContext(修改),这一篇我们介绍下删除数据 修改实体的方法取决于context是否正在跟踪需要删除的实体. 下面的示例中con ...

  2. Entity Framework Core系列之DbContext

    前言: EF Core DbContext表示与数据库的会话,并提供与数据库通信的API,具有以下功能: 数据库连接 数据操作,如查询和持久化 更改追踪 模型构建 数据映射 对象缓存 事务管理 数据库 ...

  3. Entity Framework Core系列之DbContext(添加)

    上一篇我们介绍了Entity Framework Core系列之DbContext,对DbContext有了概念上的了解,这篇将介绍DbContext添加数据 通过DbContext添加实体的主要方法 ...

  4. Entity Framework Core系列之什么是Entity Framework Core

    前言 Entity Framework Core (EF Core)是微软推荐的基于.NET Core framework的应用程序数据访问技术.它是轻量级,可扩展并且支持跨平台开发.EF Core是 ...

  5. Entity Framework Core(3)-配置DbContext

    设计时 DbContext 配置 EF Core 设计时工具如迁移需要能够发现和创建的工作实例DbContext以收集有关应用程序的实体类型以及它们如何映射到数据库架构的详细信息的类型. 此过程可以为 ...

  6. Entity Framework Core系列之实战(ASP.NET Core MVC应用程序)

    本示例演示在ASP.NET 应用程序中使用EF CORE创建数据库并对其做基本的增删改查操作.当然我们默认你的机器上已经安装了.NET CORE SDK以及合适的IDE.本例使用的是Visual St ...

  7. ASP.NET CORE系列【六】Entity Framework Core 之数据迁移

    原文:ASP.NET CORE系列[六]Entity Framework Core 之数据迁移 前言 最近打算用.NET Core写一份简单的后台系统,来练练手 然后又用到了Entity Framew ...

  8. ASP.NET CORE系列【六】Entity Framework Core 之数据库迁移

    前言 最近打算用.NET Core写一份简单的后台系统,来练练手 然后又用到了Entity Framework Core 发现园子里有些文章讲得不是那么细节,对于新手小白来说,可能会有点懵. 特意整理 ...

  9. 002从零开始入门Entity Framework Core——DbContext生存期、配置和初始化

    阅读须知:本文为入门介绍.指引文章,所示代码皆为最简易(或仅为实现功能)的演示示例版本,不一定切实符合个人(企业)实际开发需求. 一.DbContext生存期 DbContext 的生存期从创建实例时 ...

随机推荐

  1. Spring中使用的设计模式

    目录 Spring使用的设计模式 1.单例模式 2.原型模式 3.模板模式 4.观察者模式 5.工厂模式 简单工厂模式 工厂方法模式 6.适配器模式 7.装饰者模式 8.代理模式 9.策略模式   S ...

  2. [日常] Go-逐行读取文本信息

    go逐行读取文本信息:1.os包提供了操作系统函数的不依赖平台的接口,Open方法打开一个文件用于读取,func Open(name string) (file *File, err error)2. ...

  3. Java_设计模式之享元模式

    1.关于享元模式 享元模式有点类似于单例模式,都是只生成一个对象被共享使用.享元模式主要目的就是让多个对象实现共享,减少不会要额内存消耗,将多个对同一对象的访问集中起来,不必为每个访问者创建一个单独的 ...

  4. 通过hash实现前端路由

    router.js //构造函数 function Router() { this.routes = {}; this.currentUrl = ''; } Router.prototype.rout ...

  5. Javascript异步编程之一异步原理

    本系列的例子主要针对node.js环境,但浏览器端的原理应该也是类似的. 本人也是Javascript新手,把自己这段时间学习积累的要点总结下来,希望可以对同样在学习Javascript/node.j ...

  6. 基于GIS的视频管理指挥平台

    平台利用空间地理信息技术,以GIS地图为基础,将各类信息空间化.可视化,实现基于空间电子地图的可视化查询和分析,它能使情报.推理.分析与其他可用数据融为一体,提供依托于电子地图的清晰而精确的现场态势图 ...

  7. android引用arr包

    转载请标明出处,维权必究:https://www.cnblogs.com/tangZH/p/9939494.html android中引用的包一般分为两种: 1.jar包 2.aar包 arr包其实带 ...

  8. Android 图片Bitmap,drawable,res资源图片之间转换

    一.知识介绍 ①res资源图片是放在项目res文件下的资源图片 ②BitMap位图,一般文件后缀为BMP,需要编码器编码,如RGB565,RGB8888等.一种逐像素的显示对象,其执行效率高,但缺点也 ...

  9. eclipse如何修改android工程的包名?

    在我们android项目开发到一定的程度时由于需要,我们必须修改一下工程的包名,以便更好的发布我们的项目.但是在这个过程中有时候修改好了之后会出现一些错误.下面由小编一步步教你如何更改包名,和解决出现 ...

  10. SQL Server中LIKE %search_string% 走索引查找(Index Seek)浅析

      在SQL Server的SQL优化过程中,如果遇到WHERE条件中包含LIKE '%search_string%'是一件非常头痛的事情.这种情况下,一般要修改业务逻辑或改写SQL才能解决SQL执行 ...