更新实体而不读取EF核心中的整个实体

问题描述

当我们只有主键时,是否可以仅更新特定属性,而我不想读取现有的完整实体。我认为可以做到 如下

using(var context = new SampleContext())
{
    var commandText = "Update Book SET Name='WhatEver' WHERE id=@id";
    var name = new sqlParameter("@id","10001");
    context.Database.ExecutesqlCommand(commandText,name);
}

但是在EF核心中不使用SQL查询还有什么方法可以更新吗?

注意:典型方法

  1. 阅读现有的图书实体
  2. 更新名称 3然后保存更改

但是,当我们需要更新2万条记录时,这种典型的方式会更昂贵

解决方法

EF虽然确实是工具带中的一种工具,但它并不是真正适合于批处理操作,因此,当遇到不适合电钻的要求时,拔出螺丝刀进行更精细的控制是非常好的。

如果您需要执行批量更新,例如更新状态或日期,或在大量行中进行一些其他静态更改,则将其脚本化为语句并使用ExecuteSqlCommand在数据库中执行它没有任何问题。 。这里的问题是,如果这些记录中的任何一个恰好在您可能正在使用的DbContext中被跟踪的实体,您将需要刷新它们并在执行命令以查看更改后从数据库中重新加载它们。

如果您需要对大量行执行逻辑检查,并且宁愿使用代码而不是SQL或Sproc之类的方法进行检查,那么另一种选择是使用具有最小化实体定义的作用域DbContext,批量保存实体。例如,如果您有一个由100列(不包括关系)组成的实体,而您仅需要4列即可涵盖您需要检查和更新的内容,那么您可以使用仅包含这四列的实体定义来定义一个DbContext来处理更新。可以从更新DbContext一次读取成批的行,即一次读取1000-10000,然后在调用SaveChanges()之前将其馈入一种用于验证和更新的方法,然后为下一批转储并重新创建DbContext实例。这种方法的警告是事务性的,因为如果更新失败,则仅该批次将被回滚。由于实体占用空间较小,因此系统可能会一次性管理更新大量实体(可能是所有实体)的情况,但这需要对其性能成本进行监控。批量操作最好在下班后安排,以免在忙碌期间临时触发读取锁/死锁或对数据库造成繁重的事务操作。