c# - EF Core Update 会更新所有列,即使只有一列已更改

标签 c# entity-framework-core

我对使用 EF Core 有点陌生。据我了解,EF Core 有一个“更改跟踪器”,它查看数据以查看哪些列已被修改并构建一个 SQL UPDATE 语句,该语句仅更新修改后的列,如此处的答案所述:

Does EF core compares value to include columns in update statement?

但是,这不是我所看到的。例如,我有这个实体:

public class Book
{
    public int BookId { get; set; }
    [StringLength(255)]
    public string Title { get; set; }
    public int AuthorId { get; set; }
    public Author Author { get; set; }
    [StringLength(500)]
    public string Description { get; set; }
}

然后我使用以下代码更新现有行:
class Program
{
    static void Main(string[] args)
    {
        var context = new TestContext();
        var book = context.Books.Find(1);
        book.Title += " x";
        context.Books.Update(book);
        context.SaveChanges();
    }
}

我启动了 SQL Profiler 并运行了这段代码。我希望看到一个只更新“标题”列的 UPDATE 语句,但它总是更新每一列:
exec sp_executesql N'SET NOCOUNT ON;
UPDATE [Books] SET [AuthorId] = @p0, [Description] = @p1, [Title] = @p2
WHERE [BookId] = @p3;
SELECT @@ROWCOUNT;
',N'@p3 int,@p0 int,@p1 nvarchar(500),@p2 nvarchar(255)',@p3=1,@p0=1,@p1=N'',@p2=N'Some Title x'

例如,列 Description 未更改,但它在 UPDATE 语句中,就像 AuthorId 一样。

这是为什么?它不应该只在 SET 子句中有 Title 吗?

最佳答案

It was my understanding that EF Core has a "Change Tracker"



这是正确的,这就是为什么一旦实体附加到上下文中,您就可以免于将它们标记为已更新。线后...

book.Title += " x";

...EF 检测到此更改并标记标记 Title如修改。无需调用Update方法。

这就是所谓的“连接”场景。
Update方法适用于 disconnected scenario .那时实体对象未附加到上下文,但其值应保存到数据库中,例如,在 Web API 后端中。其基本形式:

public void SaveBook(Book book)
{
    // Here, 'book' is the book with the changed Title.
    using(var context = new TestContext())
    {
        context.Books.Update(book);
        context.SaveChanges();
    }
}

现在,EF 无法检测到更改,因为 book进入方法时已经修改。你必须告诉 EF 这本书必须更新。但是 EF 不知道修改了什么;它可以做的最好的是将所有属性(主键除外)标记为已修改。

但是,仍然可以通过将断开连接的场景转换为连接来使 EF 仅更新实际更新的属性:

public void SaveBook(Book book)
{
    // Here, 'book' is the book with the changed Title.
    using(var context = new TestContext())
    {
        var dbBook = context.Books.Find(book.ID);

        // Copy book's property values to dbBook.
        context.Entry(dbBook).CurrentValues.SetValues(book);

        context.SaveChanges();
    }
}

可能有good reasons比前者更喜欢后者的方法。

关于c# - EF Core Update 会更新所有列,即使只有一列已更改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60905605/

相关文章:

c# - EF Core 拥有的属性状态传播到父实体

.net-core - 错误 使用 Scaffold-DbContext、EntityFrameworkCore.Jet、.NetCore 时,无法从程序集 System.Data 加载类型 System.Data.OleDb.OleDbConnection

entity-framework-core - 在 FromSQL 查询和 Where In 子句中使用整数参数数组

c# - 多个foreach用于多个列表数据

c# - 将 ascx 控件添加到页面两次时调用了错误的 javascript 函数

c# - 从字典中的列表中获取第一个元素 C#

c# - 跳过并接受 Entity Framework Core

c# - AddDbContext 和 AddDbContextFactory 之间的区别

c# 使用 Linq2Sql 在表列中查找匹配词

c# - Entity Framework 复合主键-如何获取列的顺序