查缺补漏系统学习 EF Core 6 - 修改实体数据

推荐关注「码侠江湖」星标,时刻不忘江湖事

这是 EF Core 系列的第六篇文章,上一篇文章讲述了 EF Core 中的原始 SQL 语句查询。

这篇文章讲一讲 EF Core 如何修改实体数据。

点击上方或后方蓝字,阅读 EF Core 系列合集。

b9afbd3d71fb0a836958986cd73cebcb.png

实体状态

在开始学习 EF Core 修改数据之前,我们必须要熟悉 EF Core 中的一些机制。

前面的内容中,我们讲到 DbContext 包括三个属性:ChangeTrackerDatabaseModel

之前的示例中,DatabaseModel 我们都有用到过,那么 ChangeTracker 是做什么的?

ChangeTracker 属性提供了对当前加载的实体的,变化跟踪信息和操作的访问。

当我们想执行任何数据库修改操作时,无论是创建、修改还是删除一个实体,EF Core 都有关于跟踪和操作的信息。

为什么要保存这些信息呢?

因为在 EF Core 中,修改实体属性的值,并不会直接被保存到数据库中。

而是要我们调用 SaveChanges 方法,EF Core 才会将修改反应到数据库,在此之前,EF Core 不会执行任何操作。

因此,在调用 SaveChanges 方法之前, EF Core 需要知道我们都执行了什么操作,这对 EF Core 来说非常重要。

每一个被追踪的实体,都有附属于它的 State 属性。

当我们使用上下文对象加载实体,而不使用 AsNoTracking 方法时,或者我们通过 UpdateRemoveAdd 方法,改变实体状态时,该实体都会成为被跟踪的实体。

状态属性的值可以通实体的 State 方法获得。

那么实体的状态有哪些呢?

  • 「Detached」 - 该实体没有被追踪,调用 SaveChanges 方法不会有任何效果

  • 「Unchanged」 - 该实体从数据库中加载,但没有任何变化。调用 SaveChanges 方法也不会有任何效果

  • 「Added」 - 该实体不存在于数据库中,调用 SaveChanges 方法会将其添加到数据库中。

  • 「Modified」 - 该实体存在于数据库中,并被修改过,因此,调用 SaveChanges 方法将在数据库中修改它

  • 「Deleted」 - 该实体存在于数据库中,调用 SaveChanges 方法,会将它从数据库中删除。

实体操作

接下来,让我们结合示例来演示增删改,并观察实体状态的变化:

var account = new Account
{Name = "张三",Age = 18
};
_context.Add(account);
_context.SaveChanges();

示例中,首先创建了一个 account 对象,此时它还未被附加到 EF Core 上下文中,它的状态应该是 Detached

当我们使用 Add 方法,将account对象作为实体添加到上下文后,它的状态应该是 Added

紧接着,使用 SaveChanges 方法,将新添加的实体,保存到数据库中,它的状态应该是 Unchanged

当我们再次修改实体中的任意属性时,它的状态会变成 Modified

// ...
account.Age = 20;
_context.SaveChanges();

使用 SaveChanges 方法,将已修改的实体,应用到数据库时,它的状态又会变回 Unchanged

最后,当我们从上下文中删除这个实体后,实体的状态会变成 Deleted

// ...
_context.Remove(account);
_context.SaveChanges();

再次使用 SaveChanges 方法,将实体从数据库中彻底删除,大家想一想,此时它的状态依然会变成什么?

这次可不是 Unchanged 了,因为它已经从上下文中被移除了,所以它的状态是 Detached

EF Core 正是用这么几个方法,对实体进行增删改。

当然,这只是其中一种方式。

在这个示例中,新增的对象经过 Add 方法,被添加到了上下文。

之后的更新和删除操作,都是针对实体已经存在于上下文中的情况。

那么如果,我们有一个对象,它不存在于上下文中,但它确实存在于数据库中,我们该如何对它就行更新或删除呢?

首先,你肯定不能用 Add 方法,虽然它可以将一个对象,作为实体添加到上下文中

但它还会使实体状态成为 Added,而不是 Modified,这种情况下执行 SaveChanges 方法,EF Core 只会生成插入数据的语句,肯定会造成数据库冲突,因为数据已存在。

比如,这个对象:

var account = new Account
{Id = new Guid("dd4feb0b-b57c-4338-a40a-7aa73fc6e460"),Name = "Zilor",Age = 99
};

实际开发中,它可能来自的客户端,这个对象的数据是经过之前的查询得到的。

现在客户端对它的属性进行了修改,主键肯定是不会变的。

此时,它的状态是 Detached,没有被附加到上下文中,我们该如何直接更新到数据库呢?

这里有两种方法可以做到:

一是先用 ID 从 EF Core 中查询出实体,然后用 account 对象中的属性值,修改实体中的值,再使用 SaveChanges 保存数据。

比如这样:

var dbAccount = _context.Accounts.FirstOrDefault(a => a.Id == account.Id);
dbAccount.Name = account.Name;
dbAccount.Age = account.Age;
_context.SaveChanges();

需要注意的是,如果修改的操作,没有造成实体值的任何变化,实体状态将仍是 Unchanged

此时,即便执行SaveChanges方法, 也不会有任何效果。

二是用附加方法,将 account 对象附加到上下文,然后手动修改它的状态,再使用 SaveChanges 保存数据。

比如这样:

var account = new Account
{Id = new Guid("dd4feb0b-b57c-4338-a40a-7aa73fc6e460"),Name = "Zilor",Age = 99
};_context.Accounts.Attach(account);
_context.Entry(account).State = EntityState.Modified;
_context.SaveChanges();

Attach 方法用来附加实体,被附加的实体初始状态为 Unchanged,所以我们要手动修改实体状态。

执行应用,可以看到实体状态的流转。

第二种方式相对第一种方式,少了一步查询,也少了实体属性的赋值。

但是,无论实体的值相对于数据库是否有变化,更新操作都会执行。

这是方式适合全量更新,因为如果客户端传来的是不完整的对象,只包含了修改的属性,那么更新时可能会造成问题。

比如这个例子,如果 Account 对象中没有 Age 属性,更新到数据库时,Age 列的值会是个 「Null」

第一种方式,由于是从实体查询出来的数据,数据是完整的,修改也只是针对个别属性,所以保存数据时,不会发生这种情况。

而且第一种方式,可以判断出实体是否真的已经修改,无修改的话,不会执行任何操作。

所以,对于更新操作,建议使用第一种方式,更安全也更靠谱;

删除操作也是如此,只需要将实体状态修改为 Deleted,就可以直接删除,不够删除操作可以使用第二种方式。

更多精彩内容,请关注我▼▼

c86db9f4bb0281dee67532f2e4f97ec6.gif

如果喜欢我的文章,那么

在看和转发是对我最大的支持!

(戳下面蓝字阅读)

e4390b71d0dd332557a03d3060e4db56.png

推荐关注微信公众号:码侠江湖

                        a7606bd73dcef202e659b3be38047415.png觉得不错,点个在看再走哟

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/287462.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

情人节,我表白了CSDN小姐姐后,竟然...【为表白写了一个绘图工具,让我不再手残】

情人节,我表白了CSDN小姐姐后,竟然…竟然有人看了这篇文。 以下图片素材由一个还没写完的工具绘制,稍后会放在CSDN的代码仓库(现在能用了,还没时间改,颜色填充算法还没写,有能力的朋友可以修改一…

【小程序】刘一哥课堂随机点名提问神器V1.0(附源程序)

为了能让我们的孩子们尽量来教室上课,增强课堂的参与度,激发课堂激情,提高学习效率,一哥也是煞费苦心,于是开发出了这么一款课堂点名提问神器,跟大家分享一下。 打开神器,看到的界面是这样子的,我很感激有勇气按时起床并能到教室的每一位有志之士。 点击【开始】按钮,…

Git客户端TortoiseGit(Windows系统)的使用方法

本文环境: 操作系统:Windows XP SP3 Git客户端:TortoiseGit-1.8.8.0-32bit 一、安装Git客户端 全部安装均采用默认! 1. 安装支撑软件 msysgit: https://code.google.com/p/msysgit/downloads/list?qfullinstallerofficialgit 当前…

.Net 在容器中操作宿主机

1方案描述 在 docker 容器中想操作宿主机,一般会使用 ssh 的方式,然后 .Net 通过执行远程 ssh 指令来操作宿主机。本文将使用 交互式 .Net 容器版 中提供的镜像演示 .Net 在容器中如何操作宿主机。2前期准备 1. 宿主机上生成 ssh key生成 ss…

【看动漫学编程】程序员在异世界生个娃 第1篇:太极村

前言 作者文笔比较水,还请见谅。 以下内容还将使用视频动态漫画表现,剪辑完将会贴出链接。 小说剧情为剧情需要,过渡到知识点,部分篇幅可能没有技术知识点还望谅解。 由于没有经费支持,所以画出来的东西是我自己用代码…

【ArcGIS风暴】最牛逼空间数据批处理神器来了:用户自定义工具箱GeoStorm.tbx

【Warming up】在学习和工作的过程中,作者曾写过很多采用ArcGIS模型构建器(Model Builder)、Python代码等批处理方法(感兴趣的GISers可以去【测绘地理信息Big风暴专】栏去交流学习指导),大大的减轻了操作压力,提高了工作效率。今天给大家展示一款神器:自定义工具箱GeoS…

Linux下c/c++项目代码覆盖率的产生方法

最近做了一系列的单元测试相关的工作,除了各种规范及测试框架以外,讨论比较多的就是关于代码覆盖率的产生,c/c与其他的一些高级语言或者脚本语言相比较而言,例如 Java、.Net和php/python/perl/shell等,由于没有这些高级…

C# WPF从后台代码生成行列可变的表格

z概述WPF常用的表格控件是DataGrid,这个控件在前台XAML编写的话,一般列已经固定,然后给每个列去绑定数据,但是如果我的列不固定,随着运算结果变动呢?这时候DataGrid,就比较难实现这个需求&#…

软件架构实践文章链接

2019独角兽企业重金招聘Python工程师标准>>> 架构 InfoQ: 又拍网架构中的分库设计 SNS网站数据库技术分析 - 51CTO.COM 数据库水平切分的实现原理解析 - iBATIS - Java - JavaEye论坛 基于amoeba的mysql分布式数据库学习(一) - Java - JavaEy…

数据库SQL语句学习笔记(6)-使用函数处理数据

1.SQL也可以用函数来处理数据,函数一般是在数据上执行的,为数据的转换和处理提供了方便。但是每一个数据库管理系统(DBMS)都有特定的函数,事实上,只有少数几个函数被所有的DBMS等同地支持。例如&#xff0c…

【遥感物候】Matlab求解一元六次多项式,计算植被生长季始期

一元六次多项式能很好的逼近滤波后的曲线,与二次多项式相比,在拟合植被整个生长季曲线方面有更好的优势,该方法常用来描述北方温带和高纬度地区时序NDVI生长季模式。因此,本文使用一元六次多项式来拟合植被整个生长季曲线,效果很好。那么拟合后,这样解方程呢求生长季参数…

最全面透彻的RabbitMQ指南

概念RabbitMQ是实现了高级消息队列协议(AMQP)的开源消息代理软件(亦称面向消息的中间件)。RabbitMQ服务器是用Erlang语言编写的,而集群和故障转移是构建在开放电信平台框架上的。所有主要的编程语言均有与代理接口通讯…

TensorFlow中RNN实现的正确打开方式

上周写的文章《完全图解RNN、RNN变体、Seq2Seq、Attention机制》介绍了一下RNN的几种结构,今天就来聊一聊如何在TensorFlow中实现这些结构,这篇文章的主要内容为: 一个完整的、循序渐进的学习TensorFlow中RNN实现的方法。这个学习路径的曲线较…

《看聊天记录都学不会C语言?太菜了吧》(2)我说编程很容易你们不服?

若是大一学子或者是真心想学习刚入门的小伙伴可以私聊我,若你是真心学习可以送你书籍,指导你学习,给予你目标方向的学习路线,无套路,博客为证。 本系列文章将会以通俗易懂的对话方式进行教学,对话中将涵盖…

LCD1602,4位数据总线液晶屏时钟,STC12C5A60S2的10位ADC功能程序

/* 程序名:    LCD1602,4位数据总线液晶屏时钟,STC12C5A60S2的10位ADC功能程序 编写时间:  2015年10月4日 硬件支持:  LCD1602液晶屏 STC12C5A60S2 外部12MHZ晶振 接线定义: DB7 --> P1^7DB6…

WPF|黑暗模式的钱包支付仪表盘界面设计

收集下大家的意见,是否需要在文中贴上源码(文末会给出源码链接),请大家踊跃留言。阅读目录效果展示准备简单说明 源码结尾(视频及源码仓库)1. 效果展示欣赏效果:2. 准备创建一个WPF工程&#x…

《看聊天记录都学不会C语言?太菜了吧》(3)人艰不拆,代码都在谈恋爱?!

若是大一学子或者是真心想学习刚入门的小伙伴可以私聊我,若你是真心学习可以送你书籍,指导你学习,给予你目标方向的学习路线,无套路,博客为证。 本系列文章将会以通俗易懂的对话方式进行教学,对话中将涵盖…

DB2常用命令

查看DB2License信息 DB2基础命令 转载于:https://www.cnblogs.com/arcer/p/5573317.html

.NET7 Preview4之MapGroup

这篇是“闻(看)香(码)识(学)女(技)人(术)”。这也是一个有意思的功能,路由分组,啥也不说了,看代码看结果:using Microsoft.AspNetCore.Http.HttpResults; using Microsoft.AspNetCore.OpenApi;var builder WebApplication.Create…

【空间数据库】ArcGIS 10.6 Database_Server_Desktop安装、连接数据库服务、创建企业级数据库(附server10.6.ecp)

由于作者一直使用SQL Server 2008 R2开发版,之前在ArcGIS中创建企业级数据库都是基于单独安装的SQL Server 2008 R2开发版,今天我们演示安装ArcGIS10.6自带的数据库服务(SQL Server 2014 Express版本)、连接数据库服务和创建数据库。 首先,我们来看一下完整的ArcGIS10.6安…